diff --git a/.cyignore b/.cyignore new file mode 100644 index 0000000000..4fd9598686 --- /dev/null +++ b/.cyignore @@ -0,0 +1,40 @@ +# wolfSSL folders +$(SEARCH_wolfssl)/IDE +$(SEARCH_wolfssl)/examples +$(SEARCH_wolfssl)/linuxkm +$(SEARCH_wolfssl)/mcapi +$(SEARCH_wolfssl)/mplabx +$(SEARCH_wolfssl)/mqx +$(SEARCH_wolfssl)/tirtos +$(SEARCH_wolfssl)/tests +$(SEARCH_wolfssl)/testsuite +$(SEARCH_wolfssl)/wolfcrypt/src/port/autosar +$(SEARCH_wolfssl)/zephyr + +# wolfSSL files +$(SEARCH_wolfssl)/wolfcrypt/src/aes_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/aes_xts_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/aes_gcm_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/aes_gcm_x86_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/chacha_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/fe_x25519_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/poly1305_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/sha256_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/sha512_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/sha3_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/sm3_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/sp_x86_64_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/sp_sm2_x86_64_asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/wc_kyber_asm.S + +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/armv8-32-aes-asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/armv8-32-curve25519.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/armv8-32-sha256-asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/armv8-curve25519.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/armv8-sha3-asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/armv8-sha512-asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/thumb2-aes-asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/thumb2-curve25519.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/thumb2-sha256-asm.S +$(SEARCH_wolfssl)/wolfcrypt/src/port/arm/thumb2-sha512-asm.S diff --git a/.github/workflows/hostap.yml b/.github/workflows/hostap.yml index 187c735b69..6e45126dbd 100644 --- a/.github/workflows/hostap.yml +++ b/.github/workflows/hostap.yml @@ -62,7 +62,7 @@ jobs: config: [ { hostap_ref: hostap_2_10, - hostap_cherry_pick: 5679ec5c3dda25a0547a5f66407fd9b0b55fd04a, + hostap_cherry_pick: 36fcbb1a4ee4aa604f15079eae2ffa4fe7f44680, remove_teap: true, # TLS 1.3 does not work for this version build_id: hostap-build1, @@ -70,7 +70,7 @@ jobs: # Test the dpp patch { hostap_ref: b607d2723e927a3446d89aed813f1aa6068186bb, - hostap_cherry_pick: 5679ec5c3dda25a0547a5f66407fd9b0b55fd04a, + hostap_cherry_pick: 36fcbb1a4ee4aa604f15079eae2ffa4fe7f44680, osp_ref: ad5b52a49b3cc2a5bfb47ccc1d6a5137132e9446, build_id: hostap-build2 }, diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4579eaabf9..8edb7a7f38 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,11 +42,14 @@ jobs: uses: ./.github/workflows/packaging.yml memcached: uses: ./.github/workflows/memcached.yml -# TODO: Currently this test fails. Enable it once it becomes passing. -# libssh2: -# uses: ./.github/workflows/libssh2.yml + libssh2: + uses: ./.github/workflows/libssh2.yml openssh: uses: ./.github/workflows/openssh.yml # TODO: Currently this test fails. Enable it once it becomes passing. # haproxy: # uses: ./.github/workflows/haproxy.yml + ocsp: + uses: ./.github/workflows/ocsp.yml + no-malloc: + uses: ./.github/workflows/no-malloc.yml diff --git a/.github/workflows/no-malloc.yml b/.github/workflows/no-malloc.yml new file mode 100644 index 0000000000..70360fee69 --- /dev/null +++ b/.github/workflows/no-malloc.yml @@ -0,0 +1,34 @@ +name: No Malloc Tests + +on: + workflow_call: + +jobs: + make_check: + strategy: + matrix: + config: [ + # Add new configs here + '--enable-rsa --enable-keygen --disable-dh CFLAGS="-DWOLFSSL_NO_MALLOC"', + ] + name: make check + runs-on: ubuntu-latest + # This should be a safe limit for the tests to run. + timeout-minutes: 6 + steps: + - uses: actions/checkout@v4 + name: Checkout wolfSSL + + - name: Test wolfSSL + run: | + ./autogen.sh + ./configure ${{ matrix.config }} + make + ./wolfcrypt/test/testwolfcrypt + + - name: Print errors + if: ${{ failure() }} + run: | + if [ -f test-suite.log ] ; then + cat test-suite.log + fi diff --git a/.github/workflows/ocsp.yml b/.github/workflows/ocsp.yml new file mode 100644 index 0000000000..edfd2b6f89 --- /dev/null +++ b/.github/workflows/ocsp.yml @@ -0,0 +1,28 @@ +name: OCSP Test + +on: + workflow_call: + +jobs: + ocsp_stapling: + name: ocsp stapling + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout wolfSSL + uses: actions/checkout@v4 + + - name: Build wolfSSL + run: autoreconf -ivf && ./configure --enable-ocsp --enable-ocspstapling && make + + - name: Start OCSP responder 1 + run: openssl ocsp -port 22221 -ndays 1000 -index certs/ocsp/index-intermediate1-ca-issued-certs.txt -rsigner certs/ocsp/ocsp-responder-cert.pem -rkey certs/ocsp/ocsp-responder-key.pem -CA certs/ocsp/intermediate1-ca-cert.pem & + + - name: Start OCSP responder 2 + run: openssl ocsp -port 22220 -ndays 1000 -index certs/ocsp/index-ca-and-intermediate-cas.txt -rsigner certs/ocsp/ocsp-responder-cert.pem -rkey certs/ocsp/ocsp-responder-key.pem -CA certs/ocsp/root-ca-cert.pem & + + - name: Start TLS server + run: ./examples/server/server -p 11111 -c ./certs/ocsp/server1-cert.pem -k ./certs/ocsp/server1-key.pem -d & + + - name: Test Look Up + run: ./examples/client/client -A ./certs/ocsp/root-ca-cert.pem -o diff --git a/.github/workflows/openvpn.yml b/.github/workflows/openvpn.yml index 314f9a4eb4..bf05107b2f 100644 --- a/.github/workflows/openvpn.yml +++ b/.github/workflows/openvpn.yml @@ -34,7 +34,7 @@ jobs: name: ${{ matrix.ref }} runs-on: ubuntu-latest # This should be a safe limit for the tests to run. - timeout-minutes: 6 + timeout-minutes: 10 needs: build_wolfssl steps: - name: Download lib diff --git a/CMakeLists.txt b/CMakeLists.txt index bf6bc75223..da758394a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # CMakeList.txt # -# Copyright (C) 2006-2023 wolfSSL Inc. +# Copyright (C) 2006-2024 wolfSSL Inc. # # This file is part of wolfSSL. (formerly known as CyaSSL) # @@ -21,6 +21,12 @@ cmake_minimum_required(VERSION 3.16) +if(${CMAKE_VERSION} VERSION_LESS "3.22") + message(STATUS "This project recommends using CMake version 3.22 or higher. You are using ${CMAKE_VERSION}.") +else() + cmake_policy(SET CMP0128 NEW) +endif() + if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message(FATAL_ERROR "In-source builds are not allowed.\ Run cmake from a separate directory from where CMakeLists.txt lives.\ @@ -1216,6 +1222,14 @@ if(WOLFSSL_OPENSSH OR override_cache(WOLFSSL_DES3 "yes") endif() +# DES3 TLS Suites +set(WOLFSSL_DES3_TLS_SUITES_STRING "Enable DES3 TLS cipher suites (default: disabled)") +add_option("WOLFSSL_DES3_TLS_SUITES" ${WOLFSSL_DES3_TLS_SUITES_STRING} "no" "yes;no") + +if(NOT WOLFSSL_DES3_TLS_SUITES) + list(APPEND WOLFSSL_DEFINITIONS "-DNO_DES3_TLS_SUITES") +endif() + # ARC4 set(WOLFSSL_ARC4_HELP_STRING "Enable ARC4 (default: disabled)") add_option("WOLFSSL_ARC4" ${WOLFSSL_ARC4_HELP_STRING} "no" "yes;no") @@ -2106,6 +2120,44 @@ else() endif() set(OPTION_FILE "${WOLFSSL_OUTPUT_BASE}/wolfssl/options.h") +# sccache +add_option("ENABLE_SCCACHE" + "Enable sccache (default: disabled)" + "no" "yes;no") + +if (ENABLE_SCCACHE AND (NOT WOLFSSL_SCCACHE_ALREADY_SET_FLAG)) + find_program(SCCACHE sccache REQUIRED) + if(SCCACHE) + message(STATUS "Enable sccache") + + if(CMAKE_C_COMPILER_LAUNCHER) + set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_C_COMPILER_LAUNCHER}" "${SCCACHE}") + else() + set(CMAKE_C_COMPILER_LAUNCHER "${SCCACHE}") + endif() + if(CMAKE_CXX_COMPILER_LAUNCHER) + set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_CXX_COMPILER_LAUNCHER}" "${SCCACHE}") + else() + set(CMAKE_CXX_COMPILER_LAUNCHER "${SCCACHE}") + endif() + + if (MSVC) + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + elseif(CMAKE_BUILD_TYPE STREQUAL "Release") + string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") + endif() + endif() + set(WOLFSSL_SCCACHE_ALREADY_SET_FLAG ON) + endif() +endif() + + file(REMOVE ${OPTION_FILE}) file(APPEND ${OPTION_FILE} "/* wolfssl options.h\n") diff --git a/Docker/Dockerfile b/Docker/Dockerfile index b45cff4dec..67db112c53 100644 --- a/Docker/Dockerfile +++ b/Docker/Dockerfile @@ -10,7 +10,7 @@ ARG DEPS_WOLFSSL="build-essential autoconf libtool clang clang-tools zlib1g-dev ARG DEPS_LIBOQS="astyle cmake gcc ninja-build libssl-dev python3-pytest python3-pytest-xdist unzip xsltproc doxygen graphviz python3-yaml valgrind git" ARG DEPS_UDP_PROXY="wget libevent-dev" ARG DEPS_TESTS="abi-dumper libcurl4-openssl-dev tcpdump libpsl-dev python3-pandas python3-tabulate libnl-genl-3-dev libcap-ng-dev" -ARG DEPS_TOOLS="ccache" +ARG DEPS_TOOLS="ccache clang-tidy maven" RUN DEBIAN_FRONTEND=noninteractive apt update && apt install -y apt-utils \ && apt install -y ${DEPS_WOLFSSL} ${DEPS_LIBOQS} ${DEPS_UDP_PROXY} ${DEPS_TESTS} ${DEPS_TOOLS} \ && apt clean -y && rm -rf /var/lib/apt/lists/* diff --git a/Docker/Dockerfile.cross-compiler b/Docker/Dockerfile.cross-compiler index a9868d38dd..f7635b3e42 100644 --- a/Docker/Dockerfile.cross-compiler +++ b/Docker/Dockerfile.cross-compiler @@ -3,7 +3,7 @@ FROM $DOCKER_BASE_IMAGE USER root -ARG DEPS_TESTING="gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf gcc-aarch64-linux-gnu" +ARG DEPS_TESTING="gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf gcc-aarch64-linux-gnu gcc-powerpc-linux-gnu gcc-powerpc64-linux-gnu gcc-arm-none-eabi" RUN DEBIAN_FRONTEND=noninteractive apt update \ && apt install -y ${DEPS_TESTING} \ && apt clean -y && rm -rf /var/lib/apt/lists/* diff --git a/Docker/yocto/Dockerfile b/Docker/yocto/Dockerfile index 5fda38f932..87f786716c 100644 --- a/Docker/yocto/Dockerfile +++ b/Docker/yocto/Dockerfile @@ -19,7 +19,9 @@ WORKDIR /opt/poky ARG YOCTO_VERSION=kirkstone RUN git checkout -t origin/${YOCTO_VERSION} -b ${YOCTO_VERSION} && git pull -RUN git clone --single-branch --branch=${YOCTO_VERSION} https://github.com/wolfSSL/meta-wolfssl.git && \ +# This arg is to be able to force a rebuild starting from this line +ARG DUMMY=date +RUN DUMMY=${DUMMY} git clone --single-branch --branch=master https://github.com/wolfssl/meta-wolfssl.git && \ /bin/bash -c "source oe-init-build-env" && \ echo 'IMAGE_INSTALL:append = " wolfssl wolfclu wolfssh wolfmqtt wolftpm wolfclu "' >> /opt/poky/build/conf/local.conf && \ sed -i '/\/opt\/poky\/meta-poky \\/a \\t/opt/poky/meta-wolfssl \\' /opt/poky/build/conf/bblayers.conf diff --git a/Docker/yocto/buildAndPush.sh b/Docker/yocto/buildAndPush.sh index d76a603e8c..8c749502c6 100755 --- a/Docker/yocto/buildAndPush.sh +++ b/Docker/yocto/buildAndPush.sh @@ -11,9 +11,9 @@ fi NUM_FAILURES=0 CUR_DATE=$(date -u +%F) -for ver in kirkstone dunfell; do +for ver in kirkstone langdale scarthgap; do echo "Building wolfssl/yocto:${ver}-${CUR_DATE} as ${DOCKER_BUILD_OPTIONS}" - docker build -t wolfssl/yocto:${ver}-${CUR_DATE} --build-arg YOCTO_VERSION=${ver} -f Dockerfile "${WOLFSSL_DIR}/Docker/yocto" && \ + docker build -t wolfssl/yocto:${ver}-${CUR_DATE} --build-arg YOCTO_VERSION=${ver} --build-arg BUILD_DATE=${CUR_DATE} -f Dockerfile "${WOLFSSL_DIR}/Docker/yocto" && \ docker tag wolfssl/yocto:${ver}-${CUR_DATE} wolfssl/yocto:${ver}-latest if [ $? -eq 0 ]; then echo "Pushing containers to DockerHub" diff --git a/IDE/Espressif/ESP-IDF/examples/template/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/template/components/wolfssl/CMakeLists.txt index e129a64efb..4ac276736c 100644 --- a/IDE/Espressif/ESP-IDF/examples/template/components/wolfssl/CMakeLists.txt +++ b/IDE/Espressif/ESP-IDF/examples/template/components/wolfssl/CMakeLists.txt @@ -384,7 +384,10 @@ else() "\"${WOLFSSL_ROOT}/src/ssl_bn.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_certman.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_crypto.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_load.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/x509.c\"" "\"${WOLFSSL_ROOT}/src/x509_str.c\"" "\"${WOLFSSL_ROOT}/wolfcrypt/src/evp.c\"" diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt index e129a64efb..4ac276736c 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt @@ -384,7 +384,10 @@ else() "\"${WOLFSSL_ROOT}/src/ssl_bn.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_certman.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_crypto.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_load.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/x509.c\"" "\"${WOLFSSL_ROOT}/src/x509_str.c\"" "\"${WOLFSSL_ROOT}/wolfcrypt/src/evp.c\"" diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/components/wolfssl/CMakeLists.txt index 615142bacd..39bce20c67 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_client/components/wolfssl/CMakeLists.txt +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_client/components/wolfssl/CMakeLists.txt @@ -384,7 +384,10 @@ else() "\"${WOLFSSL_ROOT}/src/ssl_bn.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_certman.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_crypto.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_load.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/x509.c\"" "\"${WOLFSSL_ROOT}/src/x509_str.c\"" "\"${WOLFSSL_ROOT}/wolfcrypt/src/evp.c\"" diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/components/wolfssl/CMakeLists.txt index e129a64efb..4ac276736c 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_server/components/wolfssl/CMakeLists.txt +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_server/components/wolfssl/CMakeLists.txt @@ -384,7 +384,10 @@ else() "\"${WOLFSSL_ROOT}/src/ssl_bn.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_certman.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_crypto.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_load.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/x509.c\"" "\"${WOLFSSL_ROOT}/src/x509_str.c\"" "\"${WOLFSSL_ROOT}/wolfcrypt/src/evp.c\"" diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt index e129a64efb..4ac276736c 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt @@ -384,7 +384,10 @@ else() "\"${WOLFSSL_ROOT}/src/ssl_bn.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_certman.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_crypto.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_load.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_p7p12.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_sess.c\"" # included by ssl.c "\"${WOLFSSL_ROOT}/src/x509.c\"" "\"${WOLFSSL_ROOT}/src/x509_str.c\"" "\"${WOLFSSL_ROOT}/wolfcrypt/src/evp.c\"" diff --git a/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt b/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt index ab9cb25f46..b63775e143 100644 --- a/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt +++ b/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt @@ -75,7 +75,10 @@ set(COMPONENT_SRCEXCLUDE "./src/ssl_bn.c" # included by ssl.c "./src/ssl_certman.c" # included by ssl.c "./src/ssl_crypto.c" # included by ssl.c + "./src/ssl_load.c" # included by ssl.c "./src/ssl_misc.c" # included by ssl.c + "./src/ssl_p7p12.c" # included by ssl.c + "./src/ssl_sess.c" # included by ssl.c "./src/x509.c" "./src/x509_str.c" "./wolfcrypt/src/evp.c" diff --git a/IDE/Infineon/README.md b/IDE/Infineon/README.md new file mode 100644 index 0000000000..f6406afb95 --- /dev/null +++ b/IDE/Infineon/README.md @@ -0,0 +1,33 @@ +# Infineon Modus Toolbox + +Steps for building wolfSSL/wolfTPM with the Infineon Modus Toolbox examples: + +1) Add Dependency: + +In "deps" folder add wolfssl.mtb containing: + +``` +https://github.com/wolfssl/wolfssl#v5.7.0-stable#$$ASSET_REPO$$/wolfssl/wolfssl-stable +``` + +For wolfTPM add wolftpm.mtb containing: + +``` +https://github.com/wolfssl/wolftpm#master#$$ASSET_REPO$$/wolftpm/wolftpm-stable +``` + +2) Add components: +In `Makefile` under `COMPONENTS` add `WOLFSSL` and `WOLFTPM`. + +3) Add defines: + +Add `DEFINES+=WOLFSSL_USER_SETTINGS WOLFTPM_USER_SETTINGS` in Makefile. + +4) Build settings: + +Add a `user_settings.h` file for wolfSSL/wolfTPM build settings into `config` directory. +A template is provided here in `IDE/Infineon/user_settings.h`. + +5) Ignores: + +The required library ignores are found in the `.cyignore` file in the wolfSSL and wolfTPM root. diff --git a/IDE/Infineon/include.am b/IDE/Infineon/include.am new file mode 100644 index 0000000000..cc240b696b --- /dev/null +++ b/IDE/Infineon/include.am @@ -0,0 +1,7 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST += \ + IDE/Infineon/README.md \ + IDE/Infineon/user_settings.h diff --git a/IDE/Infineon/user_settings.h b/IDE/Infineon/user_settings.h new file mode 100644 index 0000000000..62f89b7c0f --- /dev/null +++ b/IDE/Infineon/user_settings.h @@ -0,0 +1,168 @@ +/* user_settings.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 + */ + +/* Example build settings for Infineon Modus Toolbox */ +/* Enables wolfSSL TLS v1.2-v1.3 and TPM support */ +/* SHA-1, SHA-2, AES CBC/GCM, ECDHE, ECDSA, RSA, HMAC, HKDF */ + +#ifndef WOLF_USER_SETTINGS_TPM_H +#define WOLF_USER_SETTINGS_TPM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Platform / Porting */ +#define NO_FILESYSTEM /* File system disable */ +#define SINGLE_THREADED /* No threading */ +#define WOLFSSL_USER_IO /* user recv/send callbacks for network IO */ +#define NO_WRITEV +#define NO_MAIN_DRIVER +#define WOLFSSL_IGNORE_FILE_WARN /* ignore file include warnings */ +#define WOLFSSL_SMALL_STACK /* limit stack usage */ +#define BENCH_EMBEDDED + +/* TLS (allow TLS v1.3 or v1.2) */ +#define WOLFSSL_TLS13 +//#define WOLFSSL_NO_TLS12 +#define NO_OLD_TLS +#define WOLFSSL_EITHER_SIDE /* allow context to be created for either server or client */ + +#define HAVE_TLS_EXTENSIONS +#define HAVE_SUPPORTED_CURVES +#define HAVE_SERVER_RENEGOTIATION_INFO +#define HAVE_ENCRYPT_THEN_MAC + +#ifdef WOLFSSL_TLS13 + #define HAVE_HKDF + #define WC_RSA_PSS + #define WOLFSSL_PSS_LONG_SALT +#endif + +/* Enable crypto callbacks - for TPM offloading */ +#define WOLF_CRYPTO_CB + +/* Enable SP math all (sp_int.c) with multi-precision support */ +#define WOLFSSL_SP_MATH_ALL + +#if 1 + /* Single Precision math for ECC 256 and RSA 2048 */ + #define WOLFSSL_HAVE_SP_RSA + #define WOLFSSL_HAVE_SP_ECC + #define WOLFSSL_SP_SMALL +#endif + +#if 0 + /* only single precision math */ + #define WOLFSSL_SP_MATH +#endif + +/* Enable hardening (timing resistance) */ +#define TFM_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING + +/* Enable PRNG (SHA2-256) */ +#define HAVE_HASHDRBG + +/* Asymmetric */ +#if 1 /* RSA - needed to encrypt salt */ + #undef NO_RSA + #ifdef USE_LOW_RESOURCE + #define WOLFSSL_RSA_PUBLIC_ONLY + #define WOLFSSL_RSA_VERIFY_INLINE + #define NO_CHECK_PRIVATE_KEY + #endif +#else + #define NO_RSA +#endif + +#if 1 /* ECC - needed for encrypt ECC salt */ + #define HAVE_ECC + #define ECC_USER_CURVES /* default to only SECP256R1 */ +#endif + +#if 0 /* DH - TPM doesn't support it */ + #undef NO_DH + #define HAVE_FFDHE_2048 + #define HAVE_DH_DEFAULT_PARAMS +#else + #define NO_DH +#endif + +/* Symmetric Hash */ +#undef NO_SHA /* allow SHA-1 */ +#undef NO_SHA256 /* allow SHA2-256 */ +#define WOLFSSL_SHA384 +#define WOLFSSL_SHA512 + +/* Symmetric Cipher */ +#define WOLFSSL_AES_CFB +#define HAVE_AES_DECRYPT + +#define HAVE_AES_KEYWRAP +#define WOLFSSL_AES_DIRECT +#define HAVE_AESGCM +#define GCM_TABLE_4BIT + +/* Features */ +#define WOLFSSL_ASN_TEMPLATE + +#define WOLFSSL_CERT_GEN +#define WOLFSSL_CERT_REQ +#define WOLFSSL_CERT_EXT + +#define HAVE_PKCS7 +#define HAVE_X963_KDF +#define WOLFSSL_BASE64_ENCODE + +#if 1 + #define HAVE_SESSION_TICKETS + #define SMALL_SESSION_CACHE +#else + #define NO_SESSION_CACHE +#endif + +/* Disables */ +#define NO_PKCS8 +#define NO_PKCS12 +#define NO_PWDBASED +#define NO_DSA +#define NO_DES3 +#define NO_RC4 +#define NO_PSK +#define NO_MD4 +#define NO_MD5 +#define WOLFSSL_NO_SHAKE128 +#define WOLFSSL_NO_SHAKE256 + +/* Logging */ +#ifdef ENABLE_SECURE_SOCKETS_LOGS + #define DEBUG_WOLFSSL +#else + #define NO_ERROR_STRINGS +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* WOLF_USER_SETTINGS_TPM_H */ diff --git a/IDE/MSVS-2019-AZSPHERE/user_settings.h b/IDE/MSVS-2019-AZSPHERE/user_settings.h index 3c4c03aa54..0dc2354b50 100644 --- a/IDE/MSVS-2019-AZSPHERE/user_settings.h +++ b/IDE/MSVS-2019-AZSPHERE/user_settings.h @@ -85,6 +85,7 @@ /* Filesystem */ #define NO_FILESYSTEM +#define HAVE_NETDB_H /* Debug */ #include diff --git a/IDE/MSVS-2019-AZSPHERE/wolfssl_new_azsphere/CMakeLists.txt b/IDE/MSVS-2019-AZSPHERE/wolfssl_new_azsphere/CMakeLists.txt index 902050c276..18c3633b0e 100644 --- a/IDE/MSVS-2019-AZSPHERE/wolfssl_new_azsphere/CMakeLists.txt +++ b/IDE/MSVS-2019-AZSPHERE/wolfssl_new_azsphere/CMakeLists.txt @@ -41,7 +41,10 @@ list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_asn1.c ) list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_bn.c ) list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_certman.c ) list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_crypto.c ) +list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_load.c ) list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_misc.c ) +list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_p7p12.c ) +list( REMOVE_ITEM SSL_SOURCES ../../../src/ssl_sess.c ) aux_source_directory( ${CRYPTO_SRC_DIR} CRYPTO_SOURCES ) list( REMOVE_ITEM CRYPTO_SOURCES ../../../wolfcrypt/src/evp.c ) list( REMOVE_ITEM CRYPTO_SOURCES ../../../wolfcrypt/src/misc.c ) diff --git a/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/user_settings.h b/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/user_settings.h index 516bbfe8e0..6e8d165b3e 100644 --- a/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/user_settings.h +++ b/IDE/Renesas/e2studio/RX72N/EnvisionKit/wolfssl_demo/user_settings.h @@ -278,3 +278,5 @@ #define XSTRCASECMP(s1,s2) strcmp((s1),(s2)) #define CUSTOM_RAND_GENERATE_BLOCK wc_tsip_GenerateRandBlock +/* use original ASN parsing */ +#define WOLFSSL_ASN_ORIGINAL diff --git a/IDE/Renesas/e2studio/RZN2L/README.md b/IDE/Renesas/e2studio/RZN2L/README.md index 55df4f2c15..c53605b79d 100644 --- a/IDE/Renesas/e2studio/RZN2L/README.md +++ b/IDE/Renesas/e2studio/RZN2L/README.md @@ -10,7 +10,7 @@ They also include benchmark and cryptography tests for the wolfCrypt library. The example project contains both the wolfSSL and wolfCrypt libraries. It is built as a `Renesas RZ/N C/C++ FSP Project` and contains the Renesas RZ configuration. The wolfssl project uses `Renesas Secure IP on RZ` -as hardware acceleration for cyptography. +as hardware acceleration for cryptography. **Limitation** @@ -22,7 +22,7 @@ The example project summary is listed below and is relevant for every project. |Item|Name/Version| |:--|:--| |Board|RZN2L| -|Device|R9A07G084M04GBG| +|Device|R9A07G084M08GBG| |Toolchain|GCC for Renesas RZ| |Toolchain Version|10.3.1.20210824| |FSP Version|1.2.0| @@ -34,7 +34,7 @@ The example project summary is listed below and is relevant for every project. |Board Support Package Common Files|v1.20|| |I/O Port|v1.2.0|| |Arm CMSIS Version 5 - Core (M)|v5.7.0+renesas.1|| -|Board support package for R9A07G084M04GBG|v1.2.0|| +|Board support package for R9A07G084M04GBG|v1.2.0|Note1| |Board support package for RZN2L|v1.2.0|| |Board support package for RZN2L - FSP Data|v1.2.0|| |RSK+RZN2L Board Support Files (RAM execution without flash memory)|v1.2.0|| @@ -50,6 +50,8 @@ The example project summary is listed below and is relevant for every project. |Renesas Secure IP Driver|v1.3.0+fsp.1.2.0|Need to contact Renesas to get RSIP module| |RSIP Engine for RZ/N2L|v1.3.0+fsp.1.2.0|Need to contact Renesas to get RSIP module| +Note1:\ + To use RSIP driver, a device type should be `R9A07G084M04GBG`. However, choosing `R9A07G084M04GBG` won't allow to select `RSK+RZN2L` board. This example uses LED and external flash memory on `RSK + RZN2L` board. Therefore, the example temporary `R9A07G084M04GBG` for the device type. Updating e2studio or fsp could resolve the issue. ## Setup Steps and Build wolfSSL Library @@ -75,7 +77,7 @@ The example project summary is listed below and is relevant for every project. |Thread Symbol|rzn2l_tst_thread| |Thread Name|rzn2l_tst_thread| |Thread Stack size|increase depending on your environment
e.g. 0xA000| -|Thread MemoryAllocation|Dyamic| +|Thread MemoryAllocation|Dynamic| |Common General Use Mutexes|Enabled| |Common General Enable Backward Compatibility|Enabled| |Common Memory Allocation Support Dynamic Allocation|Enabled| @@ -93,16 +95,18 @@ The example project summary is listed below and is relevant for every project. 3.) Prepare UART to logging + Download Sample package from [BACnet Start-Up](https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rz-mpus/bacnet-start-rzn2l-rsk) -+ Copy the following C source files from the project to src/serial_io folder of `test_RZN2L` - + um_serial_io_uart.c - + um_serial_io_task_writer.c - + um_serial_io_cfg.h - + um_common_api.h - + um_common_cfg.h - + um_serial_io.c - + um_serial_io.h - + um_serial_io_api.h - + um_serial_io_internal.h ++ Copy the following C source files from the project to src/serial_io folder of `test_RZN2L`\ +um_serial_io_uart.c\ +um_serial_io_task_writer.c\ +um_serial_io_cfg.h\ +um_common_api.h\ +um_common_cfg.h\ +um_serial_io.c\ +um_serial_io.h\ +um_serial_io_api.h\ +um_serial_io_internal.h + + + Open um_serial_io_task_writer.c and re-name printf to uart_printf 3.) Build `test_RZN2L` project @@ -113,7 +117,7 @@ The example project summary is listed below and is relevant for every project. 2). Select J-Link ARM and R9A07G084M04 -3). Break at Entory point. Change `cpsr` register value from 0xXXXXX1yy to 0xXXXXX1da +3). Break at Entry point. Change `cpsr` register value from 0xXXXXX1yy to 0xXXXXX1da ## Run TLS 1.3 Client 1.) Enable `WOLFSSL_TLS13` macro in `user_settings.h` @@ -472,7 +476,7 @@ Test complete ``` **Note** -`SHA1/224/256/384/512` and `Random generation` of RSIP driver are enabled at the sampele output above while running wolfCrypt test. +`SHA1/224/256/384/512` and `Random generation` of RSIP driver are enabled at the sample output above while running wolfCrypt test. ## Run Benchmark @@ -532,7 +536,8 @@ Benchmark complete End wolfCrypt Benchmark ``` **Note** -`SHA1/224/256/384/512` and `Random generation` of RSIP driver are enabled at the sampele output above. +`SHA1/224/256/384/512` and `Random generation` of RSIP driver are enabled at the sample output above. + ## Support For support inquiries and questions, please email support@wolfssl.com. Feel free to reach out to info@wolfssl.jp as well. diff --git a/IDE/WIN-SRTP-KDF-140-3/README.txt b/IDE/WIN-SRTP-KDF-140-3/README.txt new file mode 100644 index 0000000000..4ef0a14540 --- /dev/null +++ b/IDE/WIN-SRTP-KDF-140-3/README.txt @@ -0,0 +1,118 @@ +# Notes on the wolfssl-fips project + +First, if you did not get the FIPS files with your archive, you must contact +wolfSSL to obtain them. + +The IDE/WIN10/wolfssl-fips.sln solution is for the FIPS 140-3 certificate or later. + +# Building the wolfssl-fips project + +The wolfCrypt FIPS library for Windows is a part of the wolfSSL library. It +must be built as a static library, for the moment. + +The library project is built with Whole Program Optimization disabled. This is +required so that necessary components of the library are not optimized away. +There are two functions added to the library that are used as markers in +memory for the in-core memory check of the code. WPO consolidates them into a +single function. WPO also optimizes away the automatic FIPS entry function. + +Each of the source files inside the FIPS boundary defines their own code and +constant section. The code section names start with ".fipsA$" and the constant +section names start with ".fipsB$". Each subsection has a letter to organize +them in a specific order. This specific ordering puts marker functions and +constants on either end of the boundary so it can be hashed. + + +# In Core Memory Test + +The In Core Memory test calculates a checksum (HMAC-SHA256) of the wolfCrypt +FIPS library code and constant data and compares it with a known value in +the code. + +The following wolfCrypt FIPS project linker settings are required for the DLL Win32 configuration: +1) The [Randomized Base Address setting (ASLR)](https://learn.microsoft.com/en-us/cpp/build/reference/dynamicbase-use-address-space-layout-randomization?view=msvc-170) +needs to be disabled on all builds as the feature throws off the in-core memory calculation causing the test to fail. +2) The [Incremental Link](https://learn.microsoft.com/en-us/cpp/build/reference/incremental-link-incrementally?view=msvc-170) +option need turned off so function pointers go to actual code, not a jump instruction. +3) The [FixedBaseAddress](https://learn.microsoft.com/en-us/cpp/build/reference/fixed-fixed-base-address?view=msvc-170) +option to YES, which disables the support for ASLR. + +The "verifyCore" check value in the source fips_test.c needs to be updated when +building the code. The POS performs this check and the default failure callback +will print out the calculated checksum. When developing your code, copy this +value and paste it back into your code in the verifyCore initializer then +rebuild the code. When statically linking, you may have to recalculate your +check value when changing your application. + +# Build Options + +The default build options should be the proper default set of options: + + * HAVE_FIPS + * HAVE_FIPS_VERSION=5 + * HAVE_FIPS_VERSION_MINOR=1 (Also for FIPS Ready) + * HAVE_THREAD_LS + * WOLFSSL_KEY_GEN + * HAVE_AESGCM + * HAVE_HASHDRBG + * WOLFSSL_SHA384 + * WOLFSSL_SHA512 + * NO_PSK + * NO_RC4 + * NO_DSA + * NO_MD4 + * WOLFSSL_SHA224 + * WOLFSSL_SHA3 + * WC_RSA_PSS + * WC_RSA_NO_PADDING + * HAVE_ECC + * ECC_SHAMIR + * HAVE_ECC_CDH + * ECC_TIMING_RESISTANT + * TFM_TIMING_RESISTANT + * WOLFSSL_AES_COUNTER + * WOLFSSL_AES_DIRECT + * HAVE_AES_ECB + * HAVE_AESCCM + * WOLFSSL_CMAC + * HAVE_HKDF + * WOLFSSL_VALIDATE_ECC_IMPORT + * WOLFSSL_VALIDATE_FFC_IMPORT + * HAVE_FFDHE_Q + * NO_DES + * NO_DES3 + * NO_MD5 + * NO_OLD_TLS + * WOLFSSL_TLS13 + * HAVE_TLS_EXTENSIONS + * HAVE_SUPPORTED_CURVES + * GCM_TABLE_4BIT + * WOLFSSL_NO_SHAKE256 + * WOLFSSL_VALIDATE_ECC_KEYGEN + * WOLFSSL_ECDSA_SET_K + * WOLFSSL_WOLFSSH + * WOLFSSL_PUBLIC_MP + * WC_RNG_SEED_CB + * TFM_ECC256 + * ECC_USER_CURVES + * HAVE_ECC192 + * HAVE_ECC224 + * HAVE_ECC256 + * HAVE_ECC384 + * HAVE_ECC521 + * HAVE_FFDHE_2048 + * HAVE_FFDHE_3072 + * HAVE_FFDHE_4096 + * HAVE_FFDHE_6144 + * HAVE_FFDHE_8192 + * FP_MAX_BITS 16384 + +The "NO" options explicitly disable algorithms that are not allowed in +FIPS mode. + +Additionally one may enable: + + * WOLFSSL_AESNI + * OPENSSL_EXTRA + +These settings are defined in IDE/WIN10/user_settings.h. diff --git a/IDE/WIN-SRTP-KDF-140-3/include.am b/IDE/WIN-SRTP-KDF-140-3/include.am new file mode 100644 index 0000000000..c85379e90e --- /dev/null +++ b/IDE/WIN-SRTP-KDF-140-3/include.am @@ -0,0 +1,11 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST+= IDE/WIN-SRTP-KDF-140-3/README.txt +EXTRA_DIST+= IDE/WIN-SRTP-KDF-140-3/test.vcxproj +EXTRA_DIST+= IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.sln +EXTRA_DIST+= IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.vcxproj +EXTRA_DIST+= IDE/WIN-SRTP-KDF-140-3/user_settings.h +EXTRA_DIST+= IDE/WIN-SRTP-KDF-140-3/resource.h +EXTRA_DIST+= IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.rc diff --git a/IDE/WIN-SRTP-KDF-140-3/resource.h b/IDE/WIN-SRTP-KDF-140-3/resource.h new file mode 100644 index 0000000000..e92769c505 --- /dev/null +++ b/IDE/WIN-SRTP-KDF-140-3/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by wolfssl-fips.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/IDE/WIN-SRTP-KDF-140-3/test.vcxproj b/IDE/WIN-SRTP-KDF-140-3/test.vcxproj new file mode 100644 index 0000000000..a41ff9ac49 --- /dev/null +++ b/IDE/WIN-SRTP-KDF-140-3/test.vcxproj @@ -0,0 +1,277 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + DLL Debug + Win32 + + + DLL Debug + x64 + + + DLL Release + Win32 + + + DLL Release + x64 + + + Release + Win32 + + + Release + x64 + + + + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21} + Win32Proj + + + + Application + v142 + + + Application + v142 + + + Application + v142 + + + Application + v142 + + + Application + v142 + + + Application + v142 + + + Application + v142 + + + Application + v142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>11.0.61030.0 + + + $(SolutionDir)$(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\$(ProjectName)_obj\ + false + + + + Disabled + .\;..\..\;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;HAVE_FIPS;HAVE_FIPS_VERSION=5;HAVE_FIPS_VERSION_MINOR=1;USE_CERT_BUFFERS_2048;USE_CERT_BUFFERS_256;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + MachineX86 + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + false + + + + + Disabled + .\;..\..\;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;HAVE_FIPS;HAVE_FIPS_VERSION=5;HAVE_FIPS_VERSION_MINOR=1;USE_CERT_BUFFERS_2048;USE_CERT_BUFFERS_256;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + + + true + Console + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + + + + + .\;..\..\;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;HAVE_FIPS;HAVE_FIPS_VERSION=5;HAVE_FIPS_VERSION_MINOR=1;USE_CERT_BUFFERS_2048;USE_CERT_BUFFERS_256;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level3 + ProgramDatabase + true + + + true + Console + MachineX86 + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + true + UseLinkTimeCodeGeneration + false + + + + + .\;..\..\;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;HAVE_FIPS;HAVE_FIPS_VERSION=5;HAVE_FIPS_VERSION_MINOR=1;USE_CERT_BUFFERS_2048;USE_CERT_BUFFERS_256;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level3 + ProgramDatabase + true + + + true + Console + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + true + UseLinkTimeCodeGeneration + + + + + Disabled + .\;..\..\;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;HAVE_FIPS;HAVE_FIPS_VERSION=5;HAVE_FIPS_VERSION_MINOR=1;USE_CERT_BUFFERS_2048;USE_CERT_BUFFERS_256;WOLFSSL_USER_SETTINGS;WOLFSSL_DLL;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + false + + + true + Console + MachineX86 + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + + + + + Disabled + .\;..\..\;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;HAVE_FIPS;HAVE_FIPS_VERSION=5;HAVE_FIPS_VERSION_MINOR=1;USE_CERT_BUFFERS_2048;USE_CERT_BUFFERS_256;WOLFSSL_USER_SETTINGS;CYASSL_DLL;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + ProgramDatabase + false + + + true + Console + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + false + + + + + .\;..\..\;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;HAVE_FIPS;HAVE_FIPS_VERSION=5;HAVE_FIPS_VERSION_MINOR=1;USE_CERT_BUFFERS_2048;USE_CERT_BUFFERS_256;WOLFSSL_USER_SETTINGS;WOLFSSL_DLL;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level3 + ProgramDatabase + + + true + Console + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + true + MachineX86 + UseLinkTimeCodeGeneration + true + + + + + .\;..\..\;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;HAVE_FIPS;HAVE_FIPS_VERSION=5;HAVE_FIPS_VERSION_MINOR=1;USE_CERT_BUFFERS_2048;USE_CERT_BUFFERS_256;WOLFSSL_USER_SETTINGS;WOLFSSL_DLL;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level3 + ProgramDatabase + + + true + Console + ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + true + UseLinkTimeCodeGeneration + true + + + + + + + + {73973223-5ee8-41ca-8e88-1d60e89a237b} + false + + + + + + \ No newline at end of file diff --git a/IDE/WIN-SRTP-KDF-140-3/user_settings.h b/IDE/WIN-SRTP-KDF-140-3/user_settings.h new file mode 100644 index 0000000000..3c5127eb7c --- /dev/null +++ b/IDE/WIN-SRTP-KDF-140-3/user_settings.h @@ -0,0 +1,177 @@ +#ifndef _WIN_USER_SETTINGS_H_ +#define _WIN_USER_SETTINGS_H_ + +/* For FIPS 140-2 3389 build set to "#if 1" */ +#if 0 +#undef HAVE_FIPS +#define HAVE_FIPS +#undef HAVE_FIPS_VERSION +#define HAVE_FIPS_VERSION 2 +#undef HAVE_FIPS_VERSION_MINOR +#define HAVE_FIPS_VERSION_MINOR 0 +#endif + +/* Set the following to 1 for WCv5.0-RC12 build. */ +#if 1 +#undef HAVE_FIPS +#define HAVE_FIPS +#undef HAVE_FIPS_VERSION +#define HAVE_FIPS_VERSION 6 +#undef HAVE_FIPS_VERSION_MAJOR +#define HAVE_FIPS_VERSION_MAJOR 6 +#undef HAVE_FIPS_VERSION_MINOR +#define HAVE_FIPS_VERSION_MINOR 0 +#undef HAVE_FIPS_VERSION_PATCH +#define HAVE_FIPS_VERSION_PATCH 0 +#endif + +/* For FIPS Ready, uncomment the following: */ +/* #define WOLFSSL_FIPS_READY */ +#ifdef WOLFSSL_FIPS_READY + #undef HAVE_FIPS + #define HAVE_FIPS + #undef HAVE_FIPS_VERSION + #define HAVE_FIPS_VERSION 5 + #undef HAVE_FIPS_VERSION_MINOR + #define HAVE_FIPS_VERSION_MINOR 3 +#endif + + +/* Verify this is Windows */ +#ifndef _WIN32 +#error This user_settings.h header is only designed for Windows +#endif + +/* Configurations */ +#if defined(HAVE_FIPS) + /* FIPS */ + #define OPENSSL_EXTRA + #define HAVE_THREAD_LS + #define WOLFSSL_KEY_GEN + #define HAVE_AESGCM + #define HAVE_HASHDRBG + #define WOLFSSL_SHA384 + #define WOLFSSL_SHA512 + #define NO_PSK + #define NO_RC4 + #define NO_DSA + #define NO_MD4 + + #if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #define WOLFSSL_SHA224 + #define WOLFSSL_SHA3 + #define WC_RSA_PSS + #define WC_RSA_NO_PADDING + #define HAVE_ECC + #define HAVE_ECC384 + #define HAVE_ECC521 + #define HAVE_SUPPORTED_CURVES + #define HAVE_TLS_EXTENSIONS + #define ECC_SHAMIR + #define HAVE_ECC_CDH + #define ECC_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT + #define WOLFSSL_AES_COUNTER + #define WOLFSSL_AES_DIRECT + #define HAVE_AES_ECB + #define HAVE_AESCCM + #define WOLFSSL_CMAC + #define HAVE_HKDF + #define WOLFSSL_VALIDATE_ECC_IMPORT + #define WOLFSSL_VALIDATE_FFC_IMPORT + #define HAVE_FFDHE_Q + #define HAVE_PUBLIC_FFDHE + #ifdef _WIN64 + #define WOLFSSL_AESNI + #define HAVE_INTEL_RDSEED + #endif + #define FORCE_FAILURE_RDSEED + #endif /* FIPS v2 */ + #if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 5) + #undef WOLFSSL_AESNI /* Comment out if using PAA */ + #undef HAVE_INTEL_RDSEED + #undef FORCE_FAILURE_RDSEED + #undef HAVE_PUBLIC_FFDHE + + #define NO_DES + #define NO_DES3 + #define NO_MD5 + #define NO_OLD_TLS + + #define WOLFSSL_TLS13 + #define HAVE_TLS_EXTENSIONS + #define HAVE_SUPPORTED_CURVES + #define GCM_TABLE_4BIT + #define WOLFSSL_NO_SHAKE256 + #define WOLFSSL_VALIDATE_ECC_KEYGEN + #define WOLFSSL_ECDSA_SET_K + #define WOLFSSL_WOLFSSH + #define WOLFSSL_PUBLIC_MP + #define WC_RNG_SEED_CB + #define TFM_ECC256 + #define ECC_USER_CURVES + #define HAVE_ECC192 + #define HAVE_ECC224 + #define HAVE_ECC256 + #define HAVE_ECC384 + #define HAVE_ECC521 + #define HAVE_FFDHE_2048 + #define HAVE_FFDHE_3072 + #define HAVE_FFDHE_4096 + #define HAVE_FFDHE_6144 + #define HAVE_FFDHE_8192 + #define WOLFSSL_AES_OFB + #define FP_MAX_BITS 16384 + #endif /* FIPS v5 */ + #if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 6) + #define HAVE_ED25519 + #define HAVE_ED448 + #define WOLFSSL_SHAKE256 + #define WOLFSSL_SHAKE128 + #define WOLFSSL_AES_CFB + #define WOLFSSL_AES_XTS + #define HAVE_AES_KEYWRAP + #define WC_SRTP_KDF + #define HAVE_PBKDF2 + #define WOLFCRYPT_FIPS_CORE_HASH_VALUE \ + AA9F70F147FAB898A76F587873AC4E9C7050D6E1F5828046BE871C54EDF2BF1C + #define WOLFSSL_NOSHA512_224 + #define WOLFSSL_NOSHA512_256 + + /* uncomment for FIPS debugging */ + /* #define DEBUG_FIPS_VERBOSE */ + + /* uncomment for whole library debugging */ + /* #define DEBUG_WOLFSSL */ + #endif /* FIPS v6 */ +#else + /* Enables blinding mode, to prevent timing attacks */ + #define WC_RSA_BLINDING + + #if defined(WOLFSSL_LIB) + /* The lib */ + #define OPENSSL_EXTRA + #define WOLFSSL_RIPEMD + #define NO_PSK + #define HAVE_EXTENDED_MASTER + #define WOLFSSL_SNIFFER + #define HAVE_SECURE_RENEGOTIATION + + #define HAVE_AESGCM + #define WOLFSSL_SHA384 + #define WOLFSSL_SHA512 + + #define HAVE_SUPPORTED_CURVES + #define HAVE_TLS_EXTENSIONS + + #define HAVE_ECC + #define ECC_SHAMIR + #define ECC_TIMING_RESISTANT + #else + /* The servers and clients */ + #define OPENSSL_EXTRA + #define NO_PSK + #endif +#endif /* HAVE_FIPS */ + +#endif /* _WIN_USER_SETTINGS_H_ */ diff --git a/IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.rc b/IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.rc new file mode 100644 index 0000000000..956269fb67 --- /dev/null +++ b/IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.rc @@ -0,0 +1,100 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 5,7,0,0 + PRODUCTVERSION 5,7,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x7L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "wolfSSL Inc." + VALUE "FileDescription", "The wolfSSL FIPS embedded SSL library is a lightweight, portable, C-language-based SSL/TLS library targeted at IoT, embedded, and RTOS environments primarily because of its size, speed, and feature set." + VALUE "FileVersion", "5.7.0.0" + VALUE "InternalName", "wolfssl-fips" + VALUE "LegalCopyright", "Copyright (C) 2023" + VALUE "OriginalFilename", "wolfssl-fips.dll" + VALUE "ProductName", "wolfSSL FIPS" + VALUE "ProductVersion", "5.7.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.sln b/IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.sln new file mode 100644 index 0000000000..1609e6d91e --- /dev/null +++ b/IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.sln @@ -0,0 +1,61 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32510.428 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfssl-fips", "wolfssl-fips.vcxproj", "{73973223-5EE8-41CA-8E88-1D60E89A237B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcxproj", "{D04BDF66-664A-4D59-BEAC-8AB2D5809C21}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + DLL Debug|Win32 = DLL Debug|Win32 + DLL Debug|x64 = DLL Debug|x64 + DLL Release|Win32 = DLL Release|Win32 + DLL Release|x64 = DLL Release|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.ActiveCfg = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|Win32.Build.0 = Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.ActiveCfg = Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Debug|x64.Build.0 = Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.DLL Release|x64.Build.0 = DLL Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.ActiveCfg = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|Win32.Build.0 = Release|Win32 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.ActiveCfg = Release|x64 + {73973223-5EE8-41CA-8E88-1D60E89A237B}.Release|x64.Build.0 = Release|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Debug|Win32.ActiveCfg = Debug|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Debug|Win32.Build.0 = Debug|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Debug|x64.ActiveCfg = Debug|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Debug|x64.Build.0 = Debug|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Debug|Win32.Build.0 = DLL Debug|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Debug|x64.ActiveCfg = DLL Debug|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Debug|x64.Build.0 = DLL Debug|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Release|Win32.ActiveCfg = DLL Release|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Release|Win32.Build.0 = DLL Release|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Release|x64.ActiveCfg = DLL Release|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.DLL Release|x64.Build.0 = DLL Release|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Release|Win32.ActiveCfg = Release|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Release|Win32.Build.0 = Release|Win32 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Release|x64.ActiveCfg = Release|x64 + {D04BDF66-664A-4D59-BEAC-8AB2D5809C21}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0CFCC869-45D3-42AD-BA73-29938093A38F} + EndGlobalSection +EndGlobal diff --git a/IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.vcxproj b/IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.vcxproj new file mode 100644 index 0000000000..88980d7ee5 --- /dev/null +++ b/IDE/WIN-SRTP-KDF-140-3/wolfssl-fips.vcxproj @@ -0,0 +1,377 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + DLL Debug + Win32 + + + DLL Debug + x64 + + + DLL Release + Win32 + + + DLL Release + x64 + + + Release + Win32 + + + Release + x64 + + + + {73973223-5EE8-41CA-8E88-1D60E89A237B} + wolfssl-fips + Win32Proj + + + + StaticLibrary + v142 + Unicode + true + + + DynamicLibrary + v142 + Unicode + true + + + StaticLibrary + v142 + Unicode + true + + + DynamicLibrary + v142 + Unicode + true + + + StaticLibrary + v142 + Unicode + + + DynamicLibrary + v142 + Unicode + + + StaticLibrary + v142 + Unicode + + + DynamicLibrary + v142 + Unicode + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\$(ProjectName)_obj\ + + + false + + + false + + + false + + + false + + + + Disabled + ./;../../;%(AdditionalIncludeDirectories) + WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + + + + + Disabled + ./;../../;%(AdditionalIncludeDirectories) + BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + + + ws2_32.lib;%(AdditionalDependencies) + 0x5A000000 + false + false + true + + + + + Disabled + ./;../../;%(AdditionalIncludeDirectories) + WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + + + + + Disabled + ./;../../;%(AdditionalIncludeDirectories) + BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + + + ws2_32.lib;%(AdditionalDependencies) + 0x5A000000 + false + false + true + + + + + MaxSpeed + true + ./;../../;%(AdditionalIncludeDirectories) + WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + Level3 + ProgramDatabase + false + + + + + MaxSpeed + true + ./;../../;%(AdditionalIncludeDirectories) + BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + Level3 + ProgramDatabase + + + ws2_32.lib;%(AdditionalDependencies) + false + 0x5A000000 + true + + + + + MaxSpeed + true + ./;../../;%(AdditionalIncludeDirectories) + WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + Level3 + ProgramDatabase + false + + + + + MaxSpeed + true + ./;../../;%(AdditionalIncludeDirectories) + BUILDING_WOLFSSL;WOLFSSL_DLL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + Level3 + ProgramDatabase + + + ws2_32.lib;%(AdditionalDependencies) + false + + + + + + + + + + + + + + + + + + + + + false + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(IntDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(IntDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + + + false + false + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(IntDir)%(Filename).obj + $(IntDir)%(Filename).obj + false + false + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(IntDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + + + + + + + + + + false + false + false + false + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + ml64.exe /DHAVE_FIPS /DHAVE_FIPS_VERSION=5 /DHAVE_FIPS_VERSION_MINOR=1 /c /Zi /Fo"$(IntDir)%(Filename).obj" %(Identity) + $(IntDir)%(Filename).obj + $(IntDir)%(Filename).obj + $(IntDir)%(Filename).obj + $(IntDir)%(Filename).obj + + + + + + \ No newline at end of file diff --git a/IDE/WIN10/wolfssl-fips.vcxproj b/IDE/WIN10/wolfssl-fips.vcxproj index 5d0122ea57..41d268a878 100644 --- a/IDE/WIN10/wolfssl-fips.vcxproj +++ b/IDE/WIN10/wolfssl-fips.vcxproj @@ -258,10 +258,17 @@ + + + + + + + false false @@ -269,6 +276,9 @@ false + + + diff --git a/IDE/include.am b/IDE/include.am index 0656e8ba78..b394124fd9 100644 --- a/IDE/include.am +++ b/IDE/include.am @@ -7,6 +7,7 @@ include IDE/XCODE-FIPSv2/include.am include IDE/XCODE-FIPSv5/include.am include IDE/WIN/include.am include IDE/WIN10/include.am +include IDE/WIN-SRTP-KDF-140-3/include.am include IDE/WIN-SGX/include.am include IDE/LINUX-SGX/include.am include IDE/WORKBENCH/include.am @@ -60,6 +61,7 @@ include IDE/apple-universal/include.am include IDE/MPLABX16/include.am include IDE/MPLABX16/wolfssl.X/nbproject/include.am include IDE/MPLABX16/wolfcrypt_test.X/nbproject/include.am +include IDE/Infineon/include.am EXTRA_DIST+= IDE/IAR-EWARM IDE/MDK-ARM IDE/MYSQL IDE/LPCXPRESSO IDE/HEXIWEAR IDE/Espressif EXTRA_DIST+= IDE/OPENSTM32/README.md diff --git a/Makefile.am b/Makefile.am index 19e766d5bf..50a072c314 100644 --- a/Makefile.am +++ b/Makefile.am @@ -138,6 +138,7 @@ dist_example_DATA= ACLOCAL_AMFLAGS= -I m4 +EXTRA_DIST+= .cyignore EXTRA_DIST+= wolfssl.vcproj EXTRA_DIST+= wolfssl.vcxproj EXTRA_DIST+= wolfssl64.sln @@ -309,3 +310,8 @@ merge-clean: @find ./ | $(GREP) \.BASE | xargs rm -f @find ./ | $(GREP) \~$$ | xargs rm -f +%.o: %.cu + $(NVCC) -dc $(CUDAFLAGS) -o $@ $< + +.cu.lo: + $(LIBTOOL) --tag=CC --mode=compile $(COMPILE) --compile -o $@ $< -static diff --git a/certs/dh-priv-2048.der b/certs/dh-priv-2048.der new file mode 100644 index 0000000000..f74c641432 Binary files /dev/null and b/certs/dh-priv-2048.der differ diff --git a/certs/dh-priv-2048.pem b/certs/dh-priv-2048.pem new file mode 100644 index 0000000000..3a9fef2f3c --- /dev/null +++ b/certs/dh-priv-2048.pem @@ -0,0 +1,14 @@ +-----BEGIN PRIVATE KEY----- +MIICJgIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBALChCAacCBO6WQY8vDDV9QDB +T0Sn1u9KxiUnHOjSllMKXJHdosKUhL99skSfm9LBisW+clyn55Hm1J9zB4VbZkjH +cPq07gLJPZpK2j3BRj4ZadEXRgejTZ8rlhc5bTCNKvOU03XPoHXm8pIfGnAFqgSD +VzD72naTOFDoJ/1j7jzlt8gJrm9QNY6EzkoA6RJ+WjHXM/whE3bMFjDbDPzFYqc1 +uO+3sKzANvbZyUZI+UCQACsbqmzjGsMLA54bwkbkSE4ic2/DX9Sa1jAHSNaMkKvU +9vHjSNNYS6a5zSm/aB8IS2OGL1xr1rYGZfem3ABna7vDqUGD+8f6yOIefq8AP5MC +AQIEggEEAoIBAGgTxi13nL+WV5P+7N5Pog7yPpAD+2VCLWQh7akd6hZQ2DMlHsUe +ptoAexAcst8vQOI1/Q1CX9ItJmUmLzUFNJSeYBp9kxNmNtSmgu2JUmQDF1GBsUlK +ERt4h2PuXGAaRH39V13QP7KfYnb+7k5vo6z90XaDubLq1OQIaTpM4TbLVZBKoCmx +ozuZjUQdC97adAKHQKBmpyI2AbfWM+Af43vV5uyfq4k4X+Y7k5habXFPRXcNKklk +n6OA/isuvSN6S4i2fVmAG0hguT0utQJq6oScMZmav8izdbfOdOavXILLjRf/2Qv+ ++IMa9qlwxfqcj4oZahATC2Vd9242JWUdOpQ= +-----END PRIVATE KEY----- diff --git a/certs/dh-pub-2048.der b/certs/dh-pub-2048.der new file mode 100644 index 0000000000..017b4af57e Binary files /dev/null and b/certs/dh-pub-2048.der differ diff --git a/certs/dh-pub-2048.pem b/certs/dh-pub-2048.pem new file mode 100644 index 0000000000..48b3e3ff58 --- /dev/null +++ b/certs/dh-pub-2048.pem @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICJTCCARcGCSqGSIb3DQEDATCCAQgCggEBALChCAacCBO6WQY8vDDV9QDBT0Sn +1u9KxiUnHOjSllMKXJHdosKUhL99skSfm9LBisW+clyn55Hm1J9zB4VbZkjHcPq0 +7gLJPZpK2j3BRj4ZadEXRgejTZ8rlhc5bTCNKvOU03XPoHXm8pIfGnAFqgSDVzD7 +2naTOFDoJ/1j7jzlt8gJrm9QNY6EzkoA6RJ+WjHXM/whE3bMFjDbDPzFYqc1uO+3 +sKzANvbZyUZI+UCQACsbqmzjGsMLA54bwkbkSE4ic2/DX9Sa1jAHSNaMkKvU9vHj +SNNYS6a5zSm/aB8IS2OGL1xr1rYGZfem3ABna7vDqUGD+8f6yOIefq8AP5MCAQID +ggEGAAKCAQEAgZ77PUjCE1nV8MPEk9zpTR6k1wYrpQKy3fjMK+kbuHUEw5AaMTK9 +Gi3vpfwpg5ZaZTgTkPgakEcMwEagNDXEjzYOwxK5Ui6FVQ3VaDydVkhZppxpULu4 +H1H2WwWUFTZTZlpCmhVsDWZwzy1RoxEfBnhC78hpLYKLzyASWC1EnCC9oP/U4aI/ +D6i0bK1pXxPGFrML5jRkVpQReCkLI/aOgeTNUAcJC+USxIPSXpdPYl81zsWRgawP +bd2saVqE9DqJVSpoRY9yh1JoFqAagANNQL1x3sohEmMZq3EBbzReyawVW6Cbe5mb +LMtSN/UWqN/NwbYNcVj/GxFuoutVnS5jmw== +-----END PUBLIC KEY----- diff --git a/certs/dsa2048.pem b/certs/dsa2048.pem new file mode 100644 index 0000000000..f21cc19fcc --- /dev/null +++ b/certs/dsa2048.pem @@ -0,0 +1,20 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIDPwIBAAKCAQEAzI7JoNWaJxzaUt/HwOYGpD6KZknQWTNRacScXmSFx/Gr1dli +rP2h4BtX/5bvDJ/IRIfrXJHQRkIJUGojy4lvVelqEamoMqszDVG1eVG0q6IlEY3l +JL7Y8Z1OEm+sRFSAqbSBaE5EDrg5876DCHSixnrXan0KiFeDSNzPXm/uaAz3/wME +kKr3B5j4Z1qDI2ZHYMNDbgORrChmy/DTBcgJl7WuAV6AO51P3j6U/suCsLH8kYsd +iu7GBh83kUjS+GxdYBODp4Gsyo3QagQK6j4iThPxDbtga828XIejZytCoZ/NOVi+ +VbGThM6yEE7kw5+yU2EBKaqWyyBgQh26dUtjwQIVAOelOdRqN16VBjkHdwrroAPr +eIKbAoIBAQCa1ExxL+z6MrKAfmFKa18YdkPDabpBx6cdeQHsrzSHZ08pgKg7h/bo +oejNGxyGOPbRDEYuyODJMCbVLH/BCL/MWoKO1NRJqqL65sGd8NmWsP8MWzOOBt2d +KKnpgEE72HqUIY9W8aK0K4kcdP9+kdwfkROYr8cG0kyQor3aFrplsC1ohzxuJY2Q +x7wNqUMDyb7PhW/bB3uM+LHCSRBpY1Y3xTDS+3Ga6IIHLj6VUPNzzzRb1asCFfLM +11LFKNhBGVVvuF/xmbPH2bNx9C3fIlk1hts5yhtNNZAZazHjyMYJv3ztAbSy9W7a +Y0E85jpyLWVI9gfNkoSLHacxa9bw+9n0AoIBAGZLu7fJSJUNWqYtoX/fH2dt7VJL +FmwXxq74asRX7S+z8CpVq7rK6hfoNXzlMQ1KlfxDb5c8XGesvmd/6U6qSLOSoXZ1 +6gQ0f4czLSS2KZfjBHeTiRPbG5O4LJAaCTsm2VnzKglY3KwltKlFO6I6bGGEv2jU +6pvFKUhgFRA1LEQdtZrurMFo6Ee3QTQ5mvilIOkkxCxYP0xBMDoUbo3qrbqbQ9OY +L4PYFGfo+NVPrOA7v6dUFl5JZCZUpGtpfLqKg9kuZQqiJ++ZmQjXtZ+gAe9+F7+D +ay7dwDk4I2i0dmvlyvd87sBS4t2tWTpCBkWwx8F3BbIMMkBGqtp5dwRx33oCFQCY +7rlRNz51ExMGj5TT5ukAy2Jtmg== +-----END DSA PRIVATE KEY----- diff --git a/certs/include.am b/certs/include.am index de8d2edf08..dd87e3265f 100644 --- a/certs/include.am +++ b/certs/include.am @@ -73,7 +73,12 @@ EXTRA_DIST += \ certs/x942dh2048.der \ certs/x942dh2048.pem \ certs/fpki-cert.der \ - certs/rid-cert.der + certs/rid-cert.der \ + certs/dh-priv-2048.der \ + certs/dh-priv-2048.pem \ + certs/dh-pub-2048.der \ + certs/dh-pub-2048.pem \ + certs/dsa2048.pem EXTRA_DIST += \ certs/ca-key.der \ diff --git a/certs/test/cert-bad-neg-int.der b/certs/test/cert-bad-neg-int.der new file mode 100644 index 0000000000..8e5fc4647b Binary files /dev/null and b/certs/test/cert-bad-neg-int.der differ diff --git a/certs/test/cert-bad-oid.der b/certs/test/cert-bad-oid.der new file mode 100644 index 0000000000..cda316511f Binary files /dev/null and b/certs/test/cert-bad-oid.der differ diff --git a/certs/test/cert-bad-utf8.der b/certs/test/cert-bad-utf8.der new file mode 100644 index 0000000000..54e0889109 Binary files /dev/null and b/certs/test/cert-bad-utf8.der differ diff --git a/certs/test/include.am b/certs/test/include.am index 8f123f35f2..ed03557abe 100644 --- a/certs/test/include.am +++ b/certs/test/include.am @@ -29,7 +29,10 @@ EXTRA_DIST += \ certs/test/cert-ext-joi.cfg \ certs/test/cert-ext-multiple.cfg \ certs/test/cert-ext-multiple.der \ - certs/test/cert-ext-multiple.pem + certs/test/cert-ext-multiple.pem \ + certs/test/cert-bad-neg-int.der \ + certs/test/cert-bad-oid.der \ + certs/test/cert-bad-utf8.der # The certs/server-cert with the last byte (signature byte) changed EXTRA_DIST += \ diff --git a/configure.ac b/configure.ac index df2f74e126..d277a513d4 100644 --- a/configure.ac +++ b/configure.ac @@ -1,11 +1,11 @@ # configure.ac # -# Copyright (C) 2006-2023 wolfSSL Inc. +# Copyright (C) 2006-2024 wolfSSL Inc. # # This file is part of wolfSSL. (formerly known as CyaSSL) # # -AC_COPYRIGHT([Copyright (C) 2006-2023 wolfSSL Inc.]) +AC_COPYRIGHT([Copyright (C) 2006-2024 wolfSSL Inc.]) AC_PREREQ([2.69]) AC_INIT([wolfssl],[5.7.0],[https://github.com/wolfssl/wolfssl/issues],[wolfssl],[https://www.wolfssl.com]) AC_CONFIG_AUX_DIR([build-aux]) @@ -319,6 +319,10 @@ AS_CASE([$ENABLED_WOLFENGINE], ENABLED_WOLFENGINE="yes" ENABLED_FIPS="v5" ], + [fips-v6],[ + ENABLED_WOLFENGINE="yes" + ENABLED_FIPS="v6" + ], [fips-ready],[ ENABLED_WOLFENGINE="yes" ENABLED_FIPS="ready" @@ -345,6 +349,7 @@ AS_CASE([$ENABLED_WOLFENGINE], # dev - FIPS 140-3 settings with in-tree wolfcrypt sources, features freely adjustable # v5-ready - Alias for ready. # v5-dev - Alias for dev. +# v6 - The SRTP-KDF-full-submission # # These options have been retired, but are listed here for historical reference: # v5-RC8 - historical FIPS 140-3 (wolfCrypt WCv5.0-RC8). @@ -365,14 +370,14 @@ AS_CASE([$ENABLED_FIPS], ], [v1|yes|cert2425],[ FIPS_VERSION="v1" - HAVE_FIPS_VERSION=1 + HAVE_FIPS_VERSION_MAJOR=1 ENABLED_FIPS="yes" DEF_SP_MATH="no" DEF_FAST_MATH="yes" ], [v2|cert3389],[ FIPS_VERSION="v2" - HAVE_FIPS_VERSION=2 + HAVE_FIPS_VERSION_MAJOR=2 HAVE_FIPS_VERSION_MINOR=0 ENABLED_FIPS="yes" DEF_SP_MATH="no" @@ -380,7 +385,7 @@ AS_CASE([$ENABLED_FIPS], ], [rand],[ FIPS_VERSION="rand" - HAVE_FIPS_VERSION=2 + HAVE_FIPS_VERSION_MAJOR=2 HAVE_FIPS_VERSION_MINOR=1 ENABLED_FIPS="yes" DEF_SP_MATH="no" @@ -388,38 +393,76 @@ AS_CASE([$ENABLED_FIPS], ], [v5|v5-RC12],[ FIPS_VERSION="v5-RC12" - HAVE_FIPS_VERSION=5 + HAVE_FIPS_VERSION_MAJOR=5 HAVE_FIPS_VERSION_MINOR=2 ENABLED_FIPS="yes" DEF_SP_MATH="no" DEF_FAST_MATH="yes" ], - [ready|v5-ready],[ - FIPS_VERSION="ready" - HAVE_FIPS_VERSION=5 + [v5-ready],[ + FIPS_VERSION="v5-ready" + HAVE_FIPS_VERSION_MAJOR=5 HAVE_FIPS_VERSION_MINOR=3 ENABLED_FIPS="yes" DEF_SP_MATH="no" DEF_FAST_MATH="yes" ], - [dev|v5-dev],[ - FIPS_VERSION="dev" - HAVE_FIPS_VERSION=5 + [v5-dev],[ + FIPS_VERSION="v5-dev" + HAVE_FIPS_VERSION_MAJOR=5 HAVE_FIPS_VERSION_MINOR=3 ENABLED_FIPS="yes" # for dev, DEF_SP_MATH and DEF_FAST_MATH follow non-FIPS defaults (currently sp-math-all) ], + [v6],[ + FIPS_VERSION="v6" + HAVE_FIPS_VERSION=6 + HAVE_FIPS_VERSION_MAJOR=6 + HAVE_FIPS_VERSION_MINOR=0 + HAVE_FIPS_VERSION_PATCH=0 + ENABLED_FIPS="yes" + DEF_SP_MATH="yes" + DEF_FAST_MATH="no" + ], + # Should always remain one ahead of the latest so as not to be confused with + # the latest + [ready|v6-ready],[ + FIPS_VERSION="ready" + HAVE_FIPS_VERSION=7 + HAVE_FIPS_VERSION_MAJOR=7 + HAVE_FIPS_VERSION_MINOR=0 + HAVE_FIPS_VERSION_PATCH=0 + ENABLED_FIPS="yes" + DEF_SP_MATH="yes" + DEF_FAST_MATH="no" + ], + [dev|v6-dev],[ + FIPS_VERSION="dev" + HAVE_FIPS_VERSION_MAJOR=7 + HAVE_FIPS_VERSION_MINOR=0 + HAVE_FIPS_VERSION_PATCH=0 + ENABLED_FIPS="yes" + # for dev, DEF_SP_MATH and DEF_FAST_MATH follow non-FIPS defaults (currently sp-math-all) + ], [ - AC_MSG_ERROR([Invalid value for --enable-fips "$ENABLED_FIPS" (main options: v1, v2, v5, ready, dev, rand, no, disabled)]) + AC_MSG_ERROR([Invalid value for --enable-fips "$ENABLED_FIPS" (main options: v1, v2, v5, v6, ready, dev, rand, no, disabled)]) ]) +if test -z "$HAVE_FIPS_VERSION_MAJOR" +then + HAVE_FIPS_VERSION_MAJOR=0 +fi if test -z "$HAVE_FIPS_VERSION_MINOR" then HAVE_FIPS_VERSION_MINOR=0 fi +if test -z "$HAVE_FIPS_VERSION_PATCH" +then + HAVE_FIPS_VERSION_PATCH=0 +fi if test -z "$HAVE_FIPS_VERSION" then - HAVE_FIPS_VERSION=0 + HAVE_FIPS_VERSION="$HAVE_FIPS_VERSION_MAJOR" fi if test "$ENABLED_FIPS" != "no" @@ -766,6 +809,8 @@ then test "$enable_camellia" = "" && enable_camellia=yes test "$enable_ripemd" = "" && enable_ripemd=yes test "$enable_sha224" = "" && enable_sha224=yes + test "$enable_sha512" = "" && enable_sha512=yes + test "$enable_sha3" = "" && enable_sha3=yes test "$enable_shake128" = "" && enable_shake128=yes test "$enable_shake256" = "" && enable_shake256=yes test "$enable_sessioncerts" = "" && enable_sessioncerts=yes @@ -799,7 +844,6 @@ then test "$enable_base64encode" = "" && enable_base64encode=yes test "$enable_base16" = "" && enable_base16=yes test "$enable_arc4" = "" && enable_arc4=yes - test "$enable_des3" = "" && enable_des3=yes test "$enable_blake2" = "" && enable_blake2=yes test "$enable_blake2s" = "" && enable_blake2s=yes test "$enable_md2" = "" && enable_md2=yes @@ -824,12 +868,7 @@ then test "$enable_earlydata" = "" && enable_earlydata=yes test "$enable_ech" = "" && enable_ech=yes test "$enable_srtp" = "" && enable_srtp=yes - - if test "$ENABLED_32BIT" != "yes" - then - test "$enable_sha512" = "" && enable_sha512=yes - test "$enable_sha3" = "" && enable_sha3=yes - fi + test "$enable_rpk" = "" && enable_rpk=yes if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" then @@ -842,8 +881,10 @@ then if test "$ENABLED_SP_MATH" = "no" then test "$enable_dsa" = "" && test "$enable_sha" != "no" && enable_dsa=yes - test "$enable_ecccustcurves" = "" && enable_ecccustcurves=yes - test "$enable_brainpool" = "" && enable_brainpool=yes + if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -le 5; then + test "$enable_ecccustcurves" = "" && enable_ecccustcurves=yes + test "$enable_brainpool" = "" && enable_brainpool=yes + fi test "$enable_srp" = "" && enable_srp=yes # linuxkm is incompatible with opensslextra and its dependents. if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" @@ -865,7 +906,9 @@ then test "$enable_openvpn" = "" && enable_openvpn=yes test "$enable_asio" = "" && enable_asio=yes test "$enable_libwebsockets" = "" && enable_libwebsockets=yes - test "$enable_qt" = "" && enable_qt=yes + if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -le 5; then + test "$enable_qt" = "" && enable_qt=yes + fi fi fi @@ -877,13 +920,10 @@ then test "$enable_pkcs7" = "" && enable_pkcs7=yes test "$enable_nullcipher" = "" && enable_nullcipher=yes test "$enable_mcast" = "" && enable_mcast=yes - if test "$ENABLED_32BIT" != "yes" - then - test "$enable_ed25519" = "" && enable_ed25519=yes - test "$enable_ed25519_stream" = "" && test "$enable_ed25519" != "no" && enable_ed25519_stream=yes - test "$enable_ed448" = "" && enable_ed448=yes - test "$enable_ed448_stream" = "" && test "$enable_ed448" != "no" && enable_ed448_stream=yes - fi + test "$enable_ed25519" = "" && enable_ed25519=yes + test "$enable_ed25519_stream" = "" && test "$enable_ed25519" != "no" && enable_ed25519_stream=yes + test "$enable_ed448" = "" && enable_ed448=yes + test "$enable_ed448_stream" = "" && test "$enable_ed448" != "no" && enable_ed448_stream=yes if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" then @@ -897,11 +937,15 @@ then fi fi - if test "$ENABLED_FIPS" = "no" || test "$FIPS_VERSION" = "dev"; then + if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -ge 6 || test "$FIPS_VERSION" = "v5-dev"; then test "$enable_aesxts" = "" && enable_aesxts=yes test "$enable_aessiv" = "" && enable_aessiv=yes fi + if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -le 5; then + test "$enable_des3" = "" && enable_des3=yes + fi + # Enable DH const table speedups (eliminates `-lm` math lib dependency) AM_CFLAGS="$AM_CFLAGS -DHAVE_FFDHE_2048 -DHAVE_FFDHE_3072" DEFAULT_MAX_CLASSIC_ASYM_KEY_BITS=4096 @@ -955,6 +999,8 @@ then test "$enable_camellia" = "" && enable_camellia=yes test "$enable_ripemd" = "" && enable_ripemd=yes test "$enable_sha224" = "" && enable_sha224=yes + test "$enable_sha512" = "" && enable_sha512=yes + test "$enable_sha3" = "" && enable_sha3=yes test "$enable_shake128" = "" && enable_shake128=yes test "$enable_shake256" = "" && enable_shake256=yes test "$enable_sessioncerts" = "" && enable_sessioncerts=yes @@ -988,7 +1034,6 @@ then test "$enable_base64encode" = "" && enable_base64encode=yes test "$enable_base16" = "" && enable_base16=yes test "$enable_arc4" = "" && enable_arc4=yes - test "$enable_des3" = "" && enable_des3=yes test "$enable_blake2" = "" && enable_blake2=yes test "$enable_blake2s" = "" && enable_blake2s=yes test "$enable_md2" = "" && enable_md2=yes @@ -998,12 +1043,6 @@ then test "$enable_ssh" = "" && test "$enable_hmac" != "no" && enable_ssh=yes test "$enable_srtp_kdf" = "" && enable_srtp_kdf=yes - if test "$ENABLED_32BIT" != "yes" - then - test "$enable_sha512" = "" && enable_sha512=yes - test "$enable_sha3" = "" && enable_sha3=yes - fi - if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" then test "$enable_compkey" = "" && enable_compkey=yes @@ -1012,8 +1051,10 @@ then if test "$ENABLED_SP_MATH" = "no" then test "$enable_dsa" = "" && test "$enable_sha" != "no" && enable_dsa=yes - test "$enable_ecccustcurves" = "" && enable_ecccustcurves=yes - test "$enable_brainpool" = "" && enable_brainpool=yes + if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -le 5; then + test "$enable_ecccustcurves" = "" && enable_ecccustcurves=yes + test "$enable_brainpool" = "" && enable_brainpool=yes + fi test "$enable_srp" = "" && enable_srp=yes fi @@ -1023,13 +1064,10 @@ then test "$enable_xchacha" = "" && test "$enable_chacha" != "no" && enable_xchacha=yes test "$enable_pkcs7" = "" && enable_pkcs7=yes test "$enable_nullcipher" = "" && enable_nullcipher=yes - if test "$ENABLED_32BIT" != "yes" - then - test "$enable_ed25519" = "" && enable_ed25519=yes - test "$enable_ed25519_stream" = "" && test "$enable_ed25519" != "no" && enable_ed25519_stream=yes - test "$enable_ed448" = "" && enable_ed448=yes - test "$enable_ed448_stream" = "" && test "$enable_ed448" != "no" && enable_ed448_stream=yes - fi + test "$enable_ed25519" = "" && enable_ed25519=yes + test "$enable_ed25519_stream" = "" && test "$enable_ed25519" != "no" && enable_ed25519_stream=yes + test "$enable_ed448" = "" && enable_ed448=yes + test "$enable_ed448_stream" = "" && test "$enable_ed448" != "no" && enable_ed448_stream=yes if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" then @@ -1038,11 +1076,15 @@ then fi fi - if test "$ENABLED_FIPS" = "no" || test "$FIPS_VERSION" = "dev"; then + if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -ge 6 || test "$FIPS_VERSION" = "v5-dev"; then test "$enable_aesxts" = "" && enable_aesxts=yes test "$enable_aessiv" = "" && enable_aessiv=yes fi + if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -le 5; then + test "$enable_des3" = "" && enable_des3=yes + fi + # Enable AES Decrypt, AES ECB, Alt Names, DER Load AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_DECRYPT -DHAVE_AES_ECB -DWOLFSSL_ALT_NAMES -DWOLFSSL_DER_LOAD" @@ -1874,9 +1916,9 @@ AC_ARG_ENABLE([opensslcoexist], if test "x$ENABLED_OPENSSLCOEXIST" = "xyes" || test "$ENABLED_WOLFENGINE" = "yes" then - # make sure old names are disabled - enable_oldnames=no - + # make sure old names are disabled (except RNG) + AM_CFLAGS="$AM_CFLAGS -DNO_OLD_WC_NAMES -DNO_OLD_SSL_NAMES" + AM_CFLAGS="$AM_CFLAGS -DNO_OLD_SHA_NAMES -DNO_OLD_MD5_NAME" AM_CFLAGS="$AM_CFLAGS -DOPENSSL_COEXIST" fi @@ -2952,7 +2994,7 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AESNI" if test "$ENABLED_LINUXKM_DEFAULTS" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWC_AES_C_DYNAMIC_FALLBACK" + AM_CFLAGS="$AM_CFLAGS -DWC_C_DYNAMIC_FALLBACK" fi if test "$CC" != "icc" then @@ -3377,7 +3419,8 @@ fi # set sha3 default SHA3_DEFAULT=no -if (test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" || test "$host_cpu" = "amd64") && test "$ENABLED_32BIT" = "no" +if (test "$host_cpu" = "x86_64" || test "$host_cpu" = "aarch64" || + test "$host_cpu" = "amd64") then if test "x$ENABLED_FIPS" = "xno" || test "$HAVE_FIPS_VERSION" -ge 2 then @@ -3419,7 +3462,7 @@ AC_ARG_ENABLE([sha512], ) # options that don't require sha512 -if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" || test "$ENABLED_32BIT" = "yes" || test "$ENABLED_16BIT" = "yes" +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" || test "$ENABLED_16BIT" = "yes" then ENABLED_SHA512="no" fi @@ -3445,7 +3488,7 @@ AC_ARG_ENABLE([sha384], ) # options that don't require sha384 -if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" || test "$ENABLED_32BIT" = "yes" || test "$ENABLED_16BIT" = "yes" +if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes" || test "$ENABLED_16BIT" = "yes" then ENABLED_SHA384="no" fi @@ -3503,7 +3546,7 @@ fi # KEY GENERATION AC_ARG_ENABLE([keygen], - [AS_HELP_STRING([--enable-keygen],[Enable key generation (default: disabled)])], + [AS_HELP_STRING([--enable-keygen],[Enable key generation (only applies to RSA key generation) (default: disabled)])], [ ENABLED_KEYGEN=$enableval ], [ ENABLED_KEYGEN=no ] ) @@ -3626,15 +3669,6 @@ AC_ARG_ENABLE([srtp-kdf], [ ENABLED_SRTP_KDF=$enableval ], [ ENABLED_SRTP_KDF=no ] ) -if test "$ENABLED_SRTP" = "yes" -then - ENABLED_SRTP_KDF="yes" -fi -if test "$ENABLED_SRTP_KDF" = "yes" -then - AM_CFLAGS="$AM_CFLAGS -DWC_SRTP_KDF -DHAVE_AES_ECB -DWOLFSSL_AES_DIRECT" -fi - # DSA AC_ARG_ENABLE([dsa], @@ -3736,27 +3770,6 @@ then ENABLED_ECCCUSTCURVES="all" fi -if test "$ENABLED_ECCCUSTCURVES" != "no" -then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES" - - # For distro, all or ecccustcurves=all builds, enable all curve types - if test "$ENABLED_DISTRO" = "yes" || test "$ENABLED_ALL" = "yes" || test "$ENABLED_ECCCUSTCURVES" = "all" - then - # Enable ECC SECPR2, SECPR3, BRAINPOOL and KOBLITZ curves - AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ" - - # Enable ECC Cofactor support - AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_CDH" - - # If fastmath enabled and on x86 use speedups - if test "x$ENABLED_FASTMATH" = "xyes" && test "$host_cpu" = "x86_64" -o "$host_cpu" = "amd64" - then - AM_CFLAGS="$AM_CFLAGS -DTFM_ECC192 -DTFM_ECC224 -DTFM_ECC256 -DTFM_ECC384 -DTFM_ECC521" - fi - fi -fi - # ECC Minimum Key Size ENABLED_ECCMINSZ=224 AC_ARG_WITH([eccminsz], @@ -3840,6 +3853,17 @@ then ENABLED_CURVE25519=yes fi + if test "$ENABLED_CURVE25519" = "noasm" + then + AM_CFLAGS="$AM_CFLAGS -DNO_CURVED25519_X64" + fi + + if test "$ENABLED_CURVE25519" = "yes" && test "$ENABLED_LINUXKM_DEFAULTS" = "yes" + then + ENABLED_CURVE25519=noasm + AM_CFLAGS="$AM_CFLAGS -DNO_CURVED25519_X64" + fi + AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE25519" AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_CURVE25519" ENABLED_FEMATH=yes @@ -3876,25 +3900,6 @@ AC_ARG_ENABLE([curve448], [ ENABLED_CURVE448=no ] ) -if test "$ENABLED_CURVE448" != "no" -then - if test "$ENABLED_CURVE448" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" - then - AM_CFLAGS="$AM_CFLAGS -DCURVE448_SMALL" - ENABLED_CURVE448_SMALL=yes - ENABLED_CURVE448=yes - fi - - if test "$ENABLED_CURVE448" = "no128bit" || test "$ENABLED_32BIT" = "yes" - then - AM_CFLAGS="$AM_CFLAGS -DNO_CURVED448_128BIT" - ENABLED_CURVE448=yes - fi - - AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE448" - ENABLED_FE448=yes -fi - # ED448 AC_ARG_ENABLE([ed448], [AS_HELP_STRING([--enable-ed448],[Enable ED448 (default: disabled)])], @@ -3907,38 +3912,6 @@ AC_ARG_ENABLE([ed448-stream], [ ENABLED_ED448_STREAM=no ] ) -if test "$ENABLED_ED448" != "no" && test "$ENABLED_32BIT" = "no" -then - if test "$ENABLED_ED448" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" - then - AM_CFLAGS="$AM_CFLAGS -DED448_SMALL" - ENABLED_ED448_SMALL=yes - ENABLED_CURVE448_SMALL=yes - ENABLED_ED448=yes - fi - - if test "$ENABLED_SHA512" = "no" - then - AC_MSG_ERROR([cannot enable ed448 without enabling sha512.]) - fi - if test "$HAVE_FIPS_VERSION" = 2 - then - AC_MSG_ERROR([cannot enable ed448 w/ dependency shake256 in FIPSv2 mode]) - fi - ENABLED_FE448=yes - ENABLED_GE448=yes - AM_CFLAGS="$AM_CFLAGS -DHAVE_ED448" - - # EdDSA448 requires SHAKE256 which requires SHA-3 - if test "$ENABLED_SHA3" = "no" - then - ENABLED_SHA3=yes - fi - ENABLED_SHAKE256=yes - - ENABLED_CERTS=yes -fi - if test "$ENABLED_ED448_STREAM" != "no" then if test "$ENABLED_ED448" = "no" @@ -4805,6 +4778,13 @@ then ENABLED_DES3="yes" fi +# DES3 TLS suites +AC_ARG_ENABLE([des3-tls-suites], + [AS_HELP_STRING([--enable-des3-tls-suites],[Enable DES3 TLS cipher suites (default: disabled)])], + [ ENABLED_DES3_TLS_SUITES=$enableval ], + [ ENABLED_DES3_TLS_SUITES=no ] + ) + # ARC4 if (test "$ENABLED_OPENSSH" = "yes" && test "x$ENABLED_FIPS" = "xno") || \ test "$ENABLED_WPAS" = "yes" || test "$ENABLED_KRB" = "yes" @@ -4926,15 +4906,208 @@ then AM_CFLAGS="$AM_CFLAGS -DWC_RC2" fi +# CUDA +AC_ARG_ENABLE([cuda], + [AS_HELP_STRING([--enable-cuda],[Enable NVidia CUDA support (default: disabled)])], + [ ENABLED_CUDA=$enableval ], + [ ENABLED_CUDA=no ] + ) + +if test "$ENABLED_CUDA" = "yes" +then + CC=nvcc + AM_CFLAGS="$AM_CFLAGS -DWC_CUDA -DHAVE_CUDA" +fi + +# Certificate Service Support (CFLAG sections later) keep above FIPS section +AC_ARG_ENABLE([certservice], + [AS_HELP_STRING([--enable-certservice],[Enable cert service (default: disabled)])], + [ ENABLED_CERT_SERVICE=$enableval ], + [ ENABLED_CERT_SERVICE=no ] + ) + +# PWDBASED (CFLAG sections later) keep above FIPS section +AC_ARG_ENABLE([pwdbased], + [AS_HELP_STRING([--enable-pwdbased],[Enable PWDBASED (default: disabled)])], + [ ENABLED_PWDBASED=$enableval ], + [ ENABLED_PWDBASED=no ] + ) + +# MemUse Entropy +# wolfEntropy Software Jitter SP800-90B certifiable entropy source +AC_ARG_ENABLE([wolfEntropy], + [AS_HELP_STRING([--enable-wolfEntropy],[Enable memuse entropy support (default: disabled)])], + [ ENABLED_ENTROPY_MEMUSE=$enableval ], + [ ENABLED_ENTROPY_MEMUSE=no ] + ) +AC_ARG_ENABLE([entropy-memuse], + [AS_HELP_STRING([--enable-entropy-memuse],[Enable memuse entropy support (default: disabled)])], + [ ENABLED_ENTROPY_MEMUSE=$enableval ], + [ ENABLED_ENTROPY_MEMUSE=no ] + ) + +# AES key wrap +AC_ARG_ENABLE([aeskeywrap], + [AS_HELP_STRING([--enable-aeskeywrap],[Enable AES key wrap support (default: disabled)])], + [ ENABLED_AESKEYWRAP=$enableval ], + [ ENABLED_AESKEYWRAP=no ] + ) # FIPS feature and macro setup AS_CASE([$FIPS_VERSION], - [v5*|ready|dev], [ # FIPS 140-3 + [v6|ready|dev],[ # FIPS 140-3 SRTP-KDF + AM_CFLAGS="$AM_CFLAGS \ + -DHAVE_FIPS \ + -DHAVE_FIPS_VERSION=$HAVE_FIPS_VERSION \ + -DHAVE_FIPS_VERSION_MAJOR=$HAVE_FIPS_VERSION_MAJOR \ + -DHAVE_FIPS_VERSION_MINOR=$HAVE_FIPS_VERSION_MINOR \ + -DHAVE_FIPS_VERSION_PATCH=$HAVE_FIPS_VERSION_PATCH \ + -DHAVE_ECC_CDH \ + -DWC_RSA_NO_PADDING \ + -DECC_USER_CURVES \ + -DHAVE_ECC384 \ + -DHAVE_ECC521 \ + -DWOLFSSL_VALIDATE_FFC_IMPORT \ + -DHAVE_FFDHE_Q \ + -DHAVE_FFDHE_3072 \ + -DHAVE_FFDHE_4096 \ + -DHAVE_FFDHE_6144 \ + -DHAVE_FFDHE_8192" + + # KCAPI API does not support custom k for sign, don't force enable ECC key sizes and do not use seed callback + AS_IF([test "x$ENABLED_KCAPI_ECC" = "xno"], + [AM_CFLAGS="$AM_CFLAGS \ + -DWC_RNG_SEED_CB \ + -DWOLFSSL_ECDSA_SET_K \ + -DWOLFSSL_VALIDATE_ECC_IMPORT \ + -DWOLFSSL_VALIDATE_ECC_KEYGEN \ + -DHAVE_ECC192 \ + -DHAVE_ECC224 \ + -DHAVE_ECC256"]) + + DEFAULT_MAX_CLASSIC_ASYM_KEY_BITS=8192 +# optimizations section + +# protocol section + AS_IF([test "$ENABLED_WOLFSSH" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_ssh" != "no")], + [enable_ssh="yes"]) + + AS_IF([test "$ENABLED_HKDF" != "yes"], + [ENABLED_HKDF="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF"]) + + AS_IF([test "x$ENABLED_PWDBASED" = "xno"], + [ENABLED_PWDBASED="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_PBKDF2 -DHAVE_AESGCM"]) + + AS_IF([test "x$ENABLED_SRTP" = "xno"], + [ENABLED_SRTP="yes"]) + AS_IF([test "x$ENABLED_SRTP_KDF" = "xno"], + [ENABLED_SRTP_KDF="yes"]) + +# public key section + AS_IF([test "$ENABLED_KEYGEN" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_keygen" != "no")], + [ENABLED_KEYGEN="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN"]) + +# AS_IF([test "$ENABLED_COMPKEY" = "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_compkey" != "yes")], +# [ENABLED_COMPKEY="yes"]) + + AS_IF([test "$ENABLED_RSAPSS" != "yes"], + [ENABLED_RSAPSS="yes"; AM_CFLAGS="$AM_CFLAGS -DWC_RSA_PSS"]) + + AS_IF([test "$ENABLED_ECC" != "yes"], + [ENABLED_ECC="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + AS_IF([test "$ENABLED_ECC_SHAMIR" = "yes"], + [AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR"])]) + + AS_IF([test "x$ENABLED_ED25519" != "xyes"], + [ENABLED_ED25519="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_ED25519 -DHAVE_ED25519_KEY_IMPORT"]) + AS_IF([test "$ENABLED_CURVE25519" = "no"], + [ENABLED_CURVE25519="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE25519"]) + + AS_IF([test "x$ENABLED_ED448" != "xyes"], + [ENABLED_ED448="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_ED448 -DHAVE_ED448_KEY_IMPORT"]) + AS_IF([test "x$ENABLED_CURVE448" != "xyes"], + [ENABLED_CURVE448="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE448"]) + + AS_IF([test "x$ENABLED_ED25519_STREAM" != "xyes"], + [ENABLED_ED25519_STREAM="yes"]) + AS_IF([test "x$ENABLED_ED448_STREAM" != "xyes"], + [ENABLED_ED448_STREAM="yes"]) + + AS_IF([test "x$ENABLED_ECCCUSTCURVES" != "xno" && test "$FIPS_VERSION" != "dev"], + [ENABLED_ECCCUSTCURVES="no"]) + +# Hashing section + AS_IF([test "x$ENABLED_SHA3" != "xyes"], + [ENABLED_SHA3="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3"]) + + AS_IF([test "$ENABLED_SHA224" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_sha224" != "no")], + [ENABLED_SHA224="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA224"]) + + AS_IF([test "$ENABLED_SHA512" = "no"], + [ENABLED_SHA512="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384"]) + + # SHA512-224 and SHA512-256 are SHA-2 algorithms not in our FIPS algorithm list + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA512_224 -DWOLFSSL_NOSHA512_256" + + # Shake128 because we're testing SHAKE256 + AS_IF([test "x$ENABLED_SHAKE128" = "xno"], + [ENABLED_SHAKE128="yes"]) + + # Shake256 mandated for ED448 + AS_IF([test "x$ENABLED_SHAKE256" = "xno"], + [ENABLED_SHAKE256="yes"]) + +# Aes section + AS_IF([test "$ENABLED_AESCCM" != "yes"], + [ENABLED_AESCCM="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM"]) + + AS_IF([test "$ENABLED_AESCTR" != "yes"], + [ENABLED_AESCTR="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_COUNTER"]) + + AS_IF([test "$ENABLED_CMAC" != "yes"], + [ENABLED_CMAC="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CMAC"]) + + AS_IF([test "$ENABLED_AESGCM" = "no"], + [ENABLED_AESGCM="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM"; AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_AESGCM"]) + + # AES-GCM streaming is part of the v6 FIPS suite, but isn't implemented + # for armasm on arm-v7 or earlier (see armasm setup above). + AS_IF([test "$ENABLED_AESGCM_STREAM" != "yes" && ! (test "$ENABLED_ARMASM" = "yes" && test "$ENABLED_ARMASM_CRYPTO" = "no")], + [ENABLED_AESGCM_STREAM="yes"]) + + AS_IF([test "x$ENABLED_AESOFB" = "xno"], + [ENABLED_AESOFB="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_OFB"]) + + AS_IF([test "x$ENABLED_AESCFB" = "xno"], + [ENABLED_AESCFB="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_CFB"]) + + AS_IF([test "x$ENABLED_AESXTS" = "xno"], + [ENABLED_AESXTS="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_XTS"]) + AS_IF([test "x$ENABLED_AESXTS" = "xyes" && test "x$ENABLED_AESNI" = "xyes"], + [AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_AES_XTS"]) + + AS_IF([(test "$ENABLED_AESCCM" = "yes" && test "$HAVE_AESCCM_PORT" != "yes") || + (test "$ENABLED_AESCTR" = "yes" && test "$HAVE_AESCTR_PORT" != "yes") || + (test "$ENABLED_AESGCM" = "yes" && test "$HAVE_AESGCM_PORT" != "yes") || + (test "$ENABLED_AESOFB" = "yes" && test "$HAVE_AESOFB_PORT" != "yes")], + [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT -DHAVE_AES_ECB"]) + + AS_IF([test "x$ENABLED_AESKEYWRAP" != "xyes"], + [ENABLED_AESKEYWRAP="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_KEYWRAP"]) + +# Old TLS requires MD5 + HMAC, which is not allowed under FIPS 140-3 + AS_IF([test "$ENABLED_OLD_TLS" != "no"], + [ENABLED_OLD_TLS="no"; AM_CFLAGS="$AM_CFLAGS -DNO_OLD_TLS"]) + + ], + [v5*], [ # FIPS 140-3 AM_CFLAGS="$AM_CFLAGS \ -DHAVE_FIPS \ -DHAVE_FIPS_VERSION=$HAVE_FIPS_VERSION \ + -DHAVE_FIPS_VERSION_MAJOR=$HAVE_FIPS_VERSION_MAJOR \ -DHAVE_FIPS_VERSION_MINOR=$HAVE_FIPS_VERSION_MINOR \ + -DHAVE_FIPS_VERSION_PATCH=$HAVE_FIPS_VERSION_PATCH \ -DHAVE_ECC_CDH \ -DWC_RSA_NO_PADDING \ -DECC_USER_CURVES \ @@ -4962,63 +5135,63 @@ AS_CASE([$FIPS_VERSION], # force various features to FIPS 140-3 defaults, unless overridden with dev: - AS_IF([test "$ENABLED_KEYGEN" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_keygen" != "no")], + AS_IF([test "$ENABLED_KEYGEN" != "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_keygen" != "no")], [ENABLED_KEYGEN="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN"]) - AS_IF([test "$ENABLED_COMPKEY" = "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_compkey" != "yes")], + AS_IF([test "$ENABLED_COMPKEY" = "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_compkey" != "yes")], [ENABLED_COMPKEY="no"]) - AS_IF([test "$ENABLED_SHA224" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_sha224" != "no")], + AS_IF([test "$ENABLED_SHA224" != "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_sha224" != "no")], [ENABLED_SHA224="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA224"]) - AS_IF([test "$ENABLED_WOLFSSH" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_ssh" != "no")], + AS_IF([test "$ENABLED_WOLFSSH" != "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_ssh" != "no")], [enable_ssh="yes"]) - # Shake128 is a SHA-3 algorithm not in our FIPS algorithm list - AS_IF([test "$ENABLED_SHAKE128" != "no" && (test "$FIPS_VERSION" != "dev" || test "$enable_shake128" != "yes")], + # Shake128 is a SHA-3 algorithm outside the v5 FIPS algorithm list + AS_IF([test "$ENABLED_SHAKE128" != "no" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_shake128" != "yes")], [ENABLED_SHAKE128=no; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_SHAKE128"]) - # Shake256 is a SHA-3 algorithm not in our FIPS algorithm list - AS_IF([test "$ENABLED_SHAKE256" != "no" && (test "$FIPS_VERSION" != "dev" || test "$enable_shake256" != "yes")], + # Shake256 is a SHA-3 algorithm outside the v5 FIPS algorithm list + AS_IF([test "$ENABLED_SHAKE256" != "no" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_shake256" != "yes")], [ENABLED_SHAKE256=no; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_SHAKE256"]) - # SHA512-224 and SHA512-256 are SHA-2 algorithms not in our FIPS algorithm list + # SHA512-224 and SHA512-256 are SHA-2 algorithms outside the v5 FIPS algorithm list AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA512_224 -DWOLFSSL_NOSHA512_256" - AS_IF([test "$ENABLED_AESCCM" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_aesccm" != "no")], + AS_IF([test "$ENABLED_AESCCM" != "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_aesccm" != "no")], [ENABLED_AESCCM="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM"]) - AS_IF([test "$ENABLED_AESXTS" = "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_aesxts" != "yes")], + AS_IF([test "$ENABLED_AESXTS" = "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_aesxts" != "yes")], [ENABLED_AESXTS="no"]) - AS_IF([test "$ENABLED_RSAPSS" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_rsapss" != "no")], + AS_IF([test "$ENABLED_RSAPSS" != "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_rsapss" != "no")], [ENABLED_RSAPSS="yes"; AM_CFLAGS="$AM_CFLAGS -DWC_RSA_PSS"]) - AS_IF([test "$ENABLED_ECC" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_ecc" != "no")], + AS_IF([test "$ENABLED_ECC" != "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_ecc" != "no")], [ENABLED_ECC="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" - AS_IF([test "$ENABLED_ECC_SHAMIR" = "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_eccshamir" != "no")], + AS_IF([test "$ENABLED_ECC_SHAMIR" = "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_eccshamir" != "no")], [AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR"])]) - AS_IF([test "$ENABLED_AESCTR" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_aesctr" != "no")], + AS_IF([test "$ENABLED_AESCTR" != "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_aesctr" != "no")], [ENABLED_AESCTR="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_COUNTER"]) - AS_IF([test "$ENABLED_CMAC" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_cmac" != "no")], + AS_IF([test "$ENABLED_CMAC" != "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_cmac" != "no")], [ENABLED_CMAC="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CMAC"]) - AS_IF([test "$ENABLED_HKDF" != "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_hkdf" != "no")], + AS_IF([test "$ENABLED_HKDF" != "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_hkdf" != "no")], [ENABLED_HKDF="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF"]) AS_IF([test "$ENABLED_INTELASM" = "yes"], [AM_CFLAGS="$AM_CFLAGS -DFORCE_FAILURE_RDSEED"]) - AS_IF([test "$ENABLED_SHA512" = "no" && (test "$FIPS_VERSION" != "dev" || test "$enable_sha512" != "no")], + AS_IF([test "$ENABLED_SHA512" = "no" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_sha512" != "no")], [ENABLED_SHA512="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384"]) - AS_IF([test "$ENABLED_AESGCM" = "no" && (test "$FIPS_VERSION" != "dev" || test "$enable_aesgcm" != "no")], + AS_IF([test "$ENABLED_AESGCM" = "no" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_aesgcm" != "no")], [ENABLED_AESGCM="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM"; AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_AESGCM"]) - # AES-GCM streaming isn't part of the current FIPS suite. - AS_IF([test "$ENABLED_AESGCM_STREAM" = "yes" && (test "$FIPS_VERSION" != "dev" || test "$enable_aesgcm_stream" != "yes")], + # AES-GCM streaming isn't part of the v5 FIPS suite. + AS_IF([test "$ENABLED_AESGCM_STREAM" = "yes" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_aesgcm_stream" != "yes")], [ENABLED_AESGCM_STREAM="no"]) # Old TLS requires MD5 + HMAC, which is not allowed under FIPS 140-3 @@ -5026,7 +5199,7 @@ AS_CASE([$FIPS_VERSION], [ENABLED_OLD_TLS="no"; AM_CFLAGS="$AM_CFLAGS -DNO_OLD_TLS"]) AS_IF([test $HAVE_FIPS_VERSION_MINOR -ge 2], - [AS_IF([test "x$ENABLED_AESOFB" = "xno" && (test "$FIPS_VERSION" != "dev" || test "$enable_aesofb" != "no")], + [AS_IF([test "x$ENABLED_AESOFB" = "xno" && (test "$FIPS_VERSION" != "v5-dev" || test "$enable_aesofb" != "no")], [ENABLED_AESOFB="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_OFB"])]) AS_IF([(test "$ENABLED_AESCCM" = "yes" && test "$HAVE_AESCCM_PORT" != "yes") || @@ -5041,7 +5214,9 @@ AS_CASE([$FIPS_VERSION], AM_CFLAGS="$AM_CFLAGS \ -DHAVE_FIPS \ -DHAVE_FIPS_VERSION=$HAVE_FIPS_VERSION \ + -DHAVE_FIPS_VERSION_MAJOR=$HAVE_FIPS_VERSION_MAJOR \ -DHAVE_FIPS_VERSION_MINOR=$HAVE_FIPS_VERSION_MINOR \ + -DHAVE_FIPS_VERSION_PATCH=$HAVE_FIPS_VERSION_PATCH \ -DWOLFSSL_KEY_GEN \ -DWOLFSSL_SHA224 \ -DWOLFSSL_AES_DIRECT \ @@ -5092,11 +5267,22 @@ AS_CASE([$FIPS_VERSION], ], ["rand"],[ - AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_FIPS_RAND -DHAVE_FIPS -DHAVE_FIPS_VERSION=$HAVE_FIPS_VERSION -DHAVE_FIPS_VERSION_MINOR=$HAVE_FIPS_VERSION_MINOR" + AM_CFLAGS="$AM_CFLAGS \ + -DWOLFCRYPT_FIPS_RAND \ + -DHAVE_FIPS \ + -DHAVE_FIPS_VERSION=$HAVE_FIPS_VERSION \ + -DHAVE_FIPS_VERSION_MAJOR=$HAVE_FIPS_VERSION_MAJOR \ + -DHAVE_FIPS_VERSION_MINOR=$HAVE_FIPS_VERSION_MINOR \ + -DHAVE_FIPS_VERSION_PATCH=$HAVE_FIPS_VERSION_PATCH" ], ["v1"],[ # FIPS 140-2, Cert 2425 - AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS" + AM_CFLAGS="$AM_CFLAGS \ + -DHAVE_FIPS \ + -DHAVE_FIPS_VERSION=$HAVE_FIPS_VERSION \ + -DHAVE_FIPS_VERSION_MAJOR=$HAVE_FIPS_VERSION_MAJOR \ + -DHAVE_FIPS_VERSION_MINOR=$HAVE_FIPS_VERSION_MINOR \ + -DHAVE_FIPS_VERSION_PATCH=$HAVE_FIPS_VERSION_PATCH" AS_IF([test "x$ENABLED_SHA512" = "xno"], [ENABLED_SHA512="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384"]) AS_IF([test "x$ENABLED_AESGCM" = "xno"], @@ -5107,7 +5293,7 @@ AS_CASE([$FIPS_VERSION], AS_IF([test "x$ENABLED_FIPS" = "xyes" && test "x$thread_ls_on" = "xno" && test "$ENABLE_LINUXKM" = "no"], [AC_MSG_ERROR([FIPS requires Thread Local Storage])]) -AS_IF([(test "$ENABLED_NULL_CIPHER" = "yes" || test "$ENABLED_LEANPSK" = "yes") && test "$ENABLED_FIPS" != "no" && test "$FIPS_VERSION" != "dev"], +AS_IF([(test "$ENABLED_NULL_CIPHER" = "yes" || test "$ENABLED_LEANPSK" = "yes") && test "$ENABLED_FIPS" != "no" && test "$FIPS_VERSION" != "dev" && test "$FIPS_VERSION" != "v5-dev"], [AC_MSG_ERROR([FIPS is incompatible with nullcipher])]) # SELFTEST @@ -5138,7 +5324,6 @@ AS_CASE([$SELFTEST_VERSION], AM_CFLAGS="$AM_CFLAGS -DHAVE_SELFTEST -DHAVE_PUBLIC_FFDHE" ]) - AS_IF([test "x$ENABLED_AESXTS" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_XTS -DWOLFSSL_AES_DIRECT"]) AS_IF([test "x$ENABLED_AESXTS" = "xyes" && test "x$ENABLED_INTELASM" = "xyes"], @@ -5146,18 +5331,103 @@ AS_IF([test "x$ENABLED_AESXTS" = "xyes" && test "x$ENABLED_INTELASM" = "xyes"], AS_IF([test "x$ENABLED_AESXTS" = "xyes" && test "x$ENABLED_AESNI" = "xyes"], [AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_AES_XTS"]) +# ECC Custom Curves +if test "$ENABLED_ECCCUSTCURVES" != "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES" + + # For distro, all or ecccustcurves=all builds, enable all curve types + if test "$ENABLED_DISTRO" = "yes" || test "$ENABLED_ALL" = "yes" || test "$ENABLED_ECCCUSTCURVES" = "all" + then + # Enable ECC SECPR2, SECPR3, BRAINPOOL and KOBLITZ curves + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ" + + # Enable ECC Cofactor support + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_CDH" + + # If fastmath enabled and on x86 use speedups + if test "x$ENABLED_FASTMATH" = "xyes" && test "$host_cpu" = "x86_64" -o "$host_cpu" = "amd64" + then + AM_CFLAGS="$AM_CFLAGS -DTFM_ECC192 -DTFM_ECC224 -DTFM_ECC256 -DTFM_ECC384 -DTFM_ECC521" + fi + fi +fi + +# Curve448 +if test "$ENABLED_CURVE448" != "no" +then + if test "$ENABLED_CURVE448" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DCURVE448_SMALL" + ENABLED_CURVE448_SMALL=yes + ENABLED_CURVE448=yes + fi + + if test "$ENABLED_CURVE448" = "no128bit" || test "$ENABLED_32BIT" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DNO_CURVED448_128BIT" + ENABLED_CURVE448=yes + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_CURVE448" + ENABLED_FE448=yes +fi + +# Ed448 +if test "$ENABLED_ED448" != "no" +then + if test "$ENABLED_ED448" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" + then + AM_CFLAGS="$AM_CFLAGS -DED448_SMALL" + ENABLED_ED448_SMALL=yes + ENABLED_CURVE448_SMALL=yes + ENABLED_ED448=yes + fi + + if test "$ENABLED_SHA512" = "no" + then + AC_MSG_ERROR([cannot enable ed448 without enabling sha512.]) + fi + if test "x$HAVE_FIPS_VERSION" = "x2" + then + AC_MSG_ERROR([cannot enable ed448 w/ dependency shake256 in FIPSv2 mode]) + fi + ENABLED_FE448=yes + ENABLED_GE448=yes + AM_CFLAGS="$AM_CFLAGS -DHAVE_ED448" + + # EdDSA448 requires SHAKE256 which requires SHA-3 + if test "$ENABLED_SHA3" = "no" + then + ENABLED_SHA3=yes + fi + ENABLED_SHAKE256=yes + + ENABLED_CERTS=yes +fi + +# SRTP-KDF +if test "$ENABLED_SRTP" = "yes" +then + ENABLED_SRTP_KDF="yes" +fi +if test "$ENABLED_SRTP_KDF" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWC_SRTP_KDF -DHAVE_AES_ECB -DWOLFSSL_AES_DIRECT" +fi # Set SHA-3 flags -if test "$ENABLED_SHA3" != "no" && test "$ENABLED_32BIT" = "no" +if test "$ENABLED_SHA3" != "no" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3" fi # Set SHAKE128 flags -# FIPS does not support SHAKE 128 -AS_IF([test "x$ENABLED_FIPS" = "xyes"],[ENABLED_SHAKE128="no"]) +# FIPS traditionally does not support SHAKE 128, v6 does +AS_IF([test "x$ENABLED_FIPS" = "xyes" && test $HAVE_FIPS_VERSION -lt 6], + [ENABLED_SHAKE128="no"]) -if test "$ENABLED_SHAKE128" != "no" && test "$ENABLED_32BIT" = "no" +if test "$ENABLED_SHAKE128" != "no" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHAKE128" if test "$ENABLED_SHA3" = "no" @@ -5169,10 +5439,11 @@ else fi # Set SHAKE256 flags -# FIPS does not support SHAKE 256 -AS_IF([test "x$ENABLED_FIPS" = "xyes"],[ENABLED_SHAKE256="no"]) +# FIPS traditionally does not support SHAKE 256, v6 does +AS_IF([test "x$ENABLED_FIPS" = "xyes" && test $HAVE_FIPS_VERSION -lt 6], + [ENABLED_SHAKE256="no"]) -if test "$ENABLED_SHAKE256" != "no" && test "$ENABLED_32BIT" = "no" +if test "$ENABLED_SHAKE256" != "no" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHAKE256" if test "$ENABLED_SHA3" = "no" @@ -5280,14 +5551,7 @@ else fi fi - -# MemUse Entropy -AC_ARG_ENABLE([entropy-memuse], - [AS_HELP_STRING([--enable-entropy-memuse],[Enable memuse entropy support (default: disabled)])], - [ ENABLED_ENTROPY_MEMUSE=$enableval ], - [ ENABLED_ENTROPY_MEMUSE=no ] - ) - +# MemUse Entropy (AKA wolfEntropy) if test "x$ENABLED_ENTROPY_MEMUSE" != "xno" then AM_CFLAGS="$AM_CFLAGS -DHAVE_ENTROPY_MEMUSE" @@ -5749,7 +6013,7 @@ fi AC_ARG_ENABLE([ticket-nonce-malloc], [AS_HELP_STRING([--enable-ticket-nonce-malloc], [Enable dynamic allocation of ticket nonces (default: disabled)])], [ ENABLED_TICKET_NONCE_MALLOC=$enableval ], - [ ENABLED_TICKET_NONCE_MALLOC=no ] + [ ENABLED_TICKET_NONCE_MALLOC=no_implicit ] ) if test "$ENABLED_TICKET_NONCE_MALLOC" = "yes" @@ -5795,7 +6059,7 @@ then ENABLED_ENCRYPT_THEN_MAC=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_ALPN -DHAVE_TRUSTED_CA" # Check the ECC supported curves prereq - AS_IF([test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_CURVE25519" = "xyes" || test "x$ENABLED_CURVE448" = "xyes" || test "x$ENABLED_TLS13" = "xyes"], + AS_IF([test "x$ENABLED_ECC" != "xno" || test "$ENABLED_CURVE25519" != "no" || test "x$ENABLED_CURVE448" = "xyes" || test "x$ENABLED_TLS13" = "xyes"], [ENABLED_SUPPORTED_CURVES=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) fi @@ -6061,13 +6325,7 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_IO_POOL -DXMALLOC_USER" fi - # Certificate Service Support -AC_ARG_ENABLE([certservice], - [AS_HELP_STRING([--enable-certservice],[Enable cert service (default: disabled)])], - [ ENABLED_CERT_SERVICE=$enableval ], - [ ENABLED_CERT_SERVICE=no ] - ) if test "$ENABLED_CERT_SERVICE" = "yes" then # Requires ecc,certgen, and opensslextra make sure on @@ -6634,7 +6892,7 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC" # Check the ECC supported curves prereq - AS_IF([test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_CURVE25519" = "xyes"], + AS_IF([test "x$ENABLED_ECC" != "xno" || test "$ENABLED_CURVE25519" != "no"], [ENABLED_SUPPORTED_CURVES=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) fi @@ -6760,6 +7018,13 @@ then AM_CFLAGS="$AM_CFLAGS -DNO_SESSION_CACHE_REF" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DES_ECB" + + # support longer session ticket nonce + if test "$ENABLED_TICKET_NONCE_MALLOC" = "no_implicit" + then + ENABLED_TICKET_NONCE_MALLOC="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TICKET_NONCE_MALLOC" + fi fi if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "no" \ @@ -6952,13 +7217,6 @@ then fi # PWDBASED has to come after certservice since we want it on w/o explicit on -# PWDBASED -AC_ARG_ENABLE([pwdbased], - [AS_HELP_STRING([--enable-pwdbased],[Enable PWDBASED (default: disabled)])], - [ ENABLED_PWDBASED=$enableval ], - [ ENABLED_PWDBASED=no ] - ) - if test "$ENABLED_PWDBASED" = "no" then if test "$ENABLED_OPENSSLEXTRA" = "yes" || test "$ENABLED_OPENSSLALL" = "yes" || \ @@ -7978,14 +8236,8 @@ then fi -# AES key wrap -AC_ARG_ENABLE([aeskeywrap], - [AS_HELP_STRING([--enable-aeskeywrap],[Enable AES key wrap support (default: disabled)])], - [ ENABLED_AESKEYWRAP=$enableval ], - [ ENABLED_AESKEYWRAP=no ] - ) - -if test "$ENABLED_WPAS" != "no" && test "$ENABLED_FIPS" = "no" +if test "$ENABLED_WPAS" != "no" && + ( test "$ENABLED_FIPS" = "no" || test "x$FIPS_VERSION" = "xv6" ) then ENABLED_AESKEYWRAP="yes" fi @@ -8211,6 +8463,13 @@ AC_ARG_ENABLE([dual-alg-certs], AS_IF([ test "$ENABLED_DUAL_ALG_CERTS" != "no" && test "$ENABLED_EXPERIMENTAL" != "yes" ],[ AC_MSG_ERROR([dual-alg-certs requires --enable-experimental.]) ]) +# Adds functionality to support Raw Public Key (RPK) RFC7250 +AC_ARG_ENABLE([rpk], + [AS_HELP_STRING([--enable-rpk],[Enable support for Raw Public Key (RPK) RFC7250 (default: disabled)])], + [ ENABLED_RPK=$enableval ], + [ ENABLED_RPK=no ] + ) + # check if should run the trusted peer certs test # (for now checking both C_FLAGS and C_EXTRA_FLAGS) AS_CASE(["$CFLAGS $CPPFLAGS"],[*'WOLFSSL_TRUST_PEER_CERT'*],[ENABLED_TRUSTED_PEER_CERT=yes]) @@ -8426,7 +8685,7 @@ then ENABLED_OPENSSLEXTRA="yes" fi -if test "$ENABLED_ED25519" != "no" && test "$ENABLED_32BIT" = "no" +if test "$ENABLED_ED25519" != "no" then if test "$ENABLED_ED25519" = "small" || test "$ENABLED_LOWRESOURCE" = "yes" then @@ -8579,6 +8838,9 @@ AS_IF([test "x$ENABLED_SYS_CA_CERTS" = "xyes"], AS_IF([test "x$ENABLED_DUAL_ALG_CERTS" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DUAL_ALG_CERTS"]) +AS_IF([test "x$ENABLED_RPK" = "xyes"], + [AM_CFLAGS="$AM_CFLAGS -DHAVE_RPK"]) + AS_IF([test "x$ENABLED_ALTNAMES" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALT_NAMES"]) @@ -8594,9 +8856,9 @@ AS_IF([test "x$ENABLED_CERTGEN" = "xyes"], AS_IF([test "x$ENABLED_CERTEXT" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT"]) -AS_IF([test "x$ENABLED_ED25519" = "xyes" && test "x$ENABLED_32BIT" = "xno"], +AS_IF([test "x$ENABLED_ED25519" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DHAVE_ED25519"]) -AS_IF([test "x$ENABLED_ED25519" = "xyes" && test "x$ENABLED_32BIT" = "xno"], +AS_IF([test "x$ENABLED_ED25519" = "xyes"], [AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_ED25519"]) AS_IF([test "x$ENABLED_ED25519_SMALL" = "xyes"], @@ -8711,6 +8973,14 @@ else fi fi +if test "x$ENABLED_DES3_TLS_SUITES" = "xno" +then + AM_CFLAGS="$AM_CFLAGS -DNO_DES3_TLS_SUITES" +else + AS_IF([test "x$ENABLED_DES3" = "xno"], + [AC_MSG_ERROR([DES3 TLS suites require DES3])]) +fi + if test "$ENABLED_AESGCM" != "no" then if test "$ENABLED_AESGCM" = "word" @@ -8909,7 +9179,10 @@ fi # For distro disable custom build options that interfere with symbol generation if test "$GCC" = "yes" && test "$ENABLED_DISTRO" = "no" then - AM_CFLAGS="$AM_CFLAGS -Wall -Wno-unused" + if test "$ENABLED_CUDA" != "yes" + then + AM_CFLAGS="$AM_CFLAGS -Wall -Wno-unused" + fi if test "$ax_enable_debug" = "no" then AS_IF([test "x$ENABLED_OPTFLAGS" = "xyes"], [ @@ -9086,7 +9359,8 @@ AM_CONDITIONAL([BUILD_ED25519],[test "x$ENABLED_ED25519" = "xyes" || test "x$ENA AM_CONDITIONAL([BUILD_ED25519_SMALL],[test "x$ENABLED_ED25519_SMALL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_FEMATH], [test "x$ENABLED_FEMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_GEMATH], [test "x$ENABLED_GEMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) -AM_CONDITIONAL([BUILD_CURVE25519],[test "x$ENABLED_CURVE25519" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CURVE25519],[test "$ENABLED_CURVE25519" != "no" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_CURVE25519_INTELASM],[test "$ENABLED_CURVE25519" != "noasm" && test "$ENABLED_INTELASM" = "yes"]) AM_CONDITIONAL([BUILD_CURVE25519_SMALL],[test "x$ENABLED_CURVE25519_SMALL" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_ED448],[test "x$ENABLED_ED448" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_ED448_SMALL],[test "x$ENABLED_ED448_SMALL" = "xyes"]) @@ -9114,6 +9388,7 @@ AM_CONDITIONAL([BUILD_FIPS_V1],[test "$HAVE_FIPS_VERSION" = 1]) AM_CONDITIONAL([BUILD_FIPS_V2],[test "$HAVE_FIPS_VERSION" = 2 && test "$HAVE_FIPS_VERSION_MINOR" = 0]) AM_CONDITIONAL([BUILD_FIPS_RAND],[test "$HAVE_FIPS_VERSION" = 2 && test "$HAVE_FIPS_VERSION_MINOR" = 1]) AM_CONDITIONAL([BUILD_FIPS_V5],[test "$HAVE_FIPS_VERSION" = 5]) +AM_CONDITIONAL([BUILD_FIPS_V6],[test $HAVE_FIPS_VERSION -ge 6]) AM_CONDITIONAL([BUILD_FIPS_CURRENT],[test "$HAVE_FIPS_VERSION" -ge 2 ]) # BUILD_FIPS_CURRENT is for builds after cert 2425. AM_CONDITIONAL([BUILD_SIPHASH],[test "x$ENABLED_SIPHASH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) @@ -9193,6 +9468,7 @@ AM_CONDITIONAL([BUILD_LINUXKM],[test "$ENABLED_LINUXKM" = "yes"]) AM_CONDITIONAL([BUILD_NO_LIBRARY],[test "$ENABLED_NO_LIBRARY" = "yes"]) AM_CONDITIONAL([BUILD_BENCHMARK],[test "$ENABLED_BENCHMARK" = "yes"]) AM_CONDITIONAL([BUILD_RC2],[test "x$ENABLED_RC2" = "xyes"]) +AM_CONDITIONAL([BUILD_CUDA],[test "x$ENABLED_CUDA" = "xyes"]) AM_CONDITIONAL([BUILD_CAAM],[test "x$ENABLED_CAAM" != "xno"]) AM_CONDITIONAL([BUILD_QNXCAAM],[test "x$ENABLED_CAAM_QNX" = "xyes"]) AM_CONDITIONAL([BUILD_IOTSAFE],[test "x$ENABLED_IOTSAFE" = "xyes"]) @@ -9309,7 +9585,7 @@ rm -f $OPTION_FILE echo "/* wolfssl options.h" > $OPTION_FILE echo " * generated from configure options" >> $OPTION_FILE echo " *" >> $OPTION_FILE -echo " * Copyright (C) 2006-2023 wolfSSL Inc." >> $OPTION_FILE +echo " * Copyright (C) 2006-2024 wolfSSL Inc." >> $OPTION_FILE echo " *" >> $OPTION_FILE echo " * This file is part of wolfSSL. (formerly known as CyaSSL)" >> $OPTION_FILE echo " *" >> $OPTION_FILE @@ -9512,9 +9788,12 @@ echo " * AES-XTS: $ENABLED_AESXTS" echo " * AES-SIV: $ENABLED_AESSIV" echo " * AES-EAX: $ENABLED_AESEAX" echo " * AES Bitspliced: $ENABLED_AESBS" +echo " * AES Key Wrap: $ENABLED_AESKEYWRAP" echo " * ARIA: $ENABLED_ARIA" echo " * DES3: $ENABLED_DES3" +echo " * DES3 TLS Suites: $ENABLED_DES3_TLS_SUITES" echo " * Camellia: $ENABLED_CAMELLIA" +echo " * CUDA: $ENABLED_CUDA" echo " * SM4-ECB: $ENABLED_SM4_ECB" echo " * SM4-CBC: $ENABLED_SM4_CBC" echo " * SM4-CTR: $ENABLED_SM4_CTR" @@ -9545,7 +9824,8 @@ echo " * certgencache: $ENABLED_certgencache" echo " * CHACHA: $ENABLED_CHACHA" echo " * XCHACHA: $ENABLED_XCHACHA" echo " * Hash DRBG: $ENABLED_HASHDRBG" -echo " * MmemUse Entropy: $ENABLED_ENTROPY_MEMUSE" +echo " * MmemUse Entropy:" +echo " * (AKA: wolfEntropy): $ENABLED_ENTROPY_MEMUSE" echo " * PWDBASED: $ENABLED_PWDBASED" echo " * Encrypted keys: $ENABLED_ENCKEYS" echo " * scrypt: $ENABLED_SCRYPT" @@ -9626,6 +9906,7 @@ echo " * TLS v1.0 (Old): $ENABLED_TLSV10" echo " * TLS v1.1 (Old): $ENABLED_OLD_TLS" echo " * TLS v1.2: $ENABLED_TLSV12" echo " * TLS v1.3: $ENABLED_TLS13" +echo " * RPK: $ENABLED_RPK" echo " * Post-handshake Auth: $ENABLED_TLS13_POST_AUTH" echo " * Early Data: $ENABLED_TLS13_EARLY_DATA" echo " * QUIC: $ENABLED_QUIC" @@ -9693,7 +9974,6 @@ fi echo " * ARM ASM: $ENABLED_ARMASM" echo " * ARM ASM SHA512/SHA3 Crypto $ENABLED_ARMASM_SHA3" echo " * ARM ASM SM3/SM4 Crypto $ENABLED_ARMASM_CRYPTO_SM4" -echo " * AES Key Wrap: $ENABLED_AESKEYWRAP" echo " * Write duplicate: $ENABLED_WRITEDUP" echo " * Xilinx Hardware Acc.: $ENABLED_XILINX" echo " * Inline Code: $ENABLED_INLINE" diff --git a/examples/asn1/asn1.c b/examples/asn1/asn1.c index 57d38d1157..383547133e 100644 --- a/examples/asn1/asn1.c +++ b/examples/asn1/asn1.c @@ -133,6 +133,7 @@ static int PrintDer(FILE* fp) return ret; } +#ifndef NO_CODING /* Print ASN.1 of a file containing Base64 encoding of BER/DER data. * * @param [in] fp File pointer to read from. @@ -279,6 +280,7 @@ static int PrintPem(FILE* fp, int pem_skip) return ret; } +#endif /* Usage lines to show. */ const char* usage[] = { @@ -288,7 +290,9 @@ const char* usage[] = { "Options:", " -?, --help display this help and exit", " -b, --branch draw branches before tag name", +#ifndef NO_CODING " -B, --base64 file contents are Base64 encoded", +#endif " -d, --dump show all ASN.1 item data as a hex dump", " -h, --headers show all ASN.1 item headers as a hex dump", " -i, --indent indent tag name with depth", @@ -297,7 +301,9 @@ const char* usage[] = { " -N, --no-dump-text do not show data as a hex dump text", " -o, --offset OFFSET start decoding from offset", " -O, --oid show wolfSSL OID value in text", +#ifndef NO_CODING " -p, --pem file contents are PEM", +#endif " -s, --skip-pem NUM number of PEM blocks to skip", }; /* Number of usage lines. */ @@ -342,11 +348,13 @@ int main(int argc, char* argv[]) (strcmp(argv[0], "--branch") == 0)) { wc_Asn1PrintOptions_Set(&opts, ASN1_PRINT_OPT_DRAW_BRANCH, 1); } +#ifndef NO_CODING /* File is Base64 encoded data. */ else if ((strcmp(argv[0], "-b64") == 0) || (strcmp(argv[0], "--base64") == 0)) { file_format = FORMAT_BASE64; } +#endif /* Dump all ASN.1 item data. */ else if ((strcmp(argv[0], "-d") == 0) || (strcmp(argv[0], "--dump") == 0)) { @@ -403,11 +411,13 @@ int main(int argc, char* argv[]) (strcmp(argv[0], "--oid") == 0)) { wc_Asn1PrintOptions_Set(&opts, ASN1_PRINT_OPT_SHOW_OID, 1); } +#ifndef NO_CODING /* File contains PEM blocks. */ else if ((strcmp(argv[0], "-p") == 0) || (strcmp(argv[0], "--pem") == 0)) { file_format = FORMAT_PEM; } +#endif /* Skip a number of PEM blocks. */ else if ((strcmp(argv[0], "-s") == 0) || (strcmp(argv[0], "--skip-pem") == 0)) { @@ -458,12 +468,16 @@ int main(int argc, char* argv[]) if (file_format == FORMAT_DER) { ret = PrintDer(fp); } +#ifndef NO_CODING else if (file_format == FORMAT_BASE64) { ret = PrintBase64(fp); } +#endif +#ifndef NO_CODING else if (file_format == FORMAT_PEM) { ret = PrintPem(fp, pem_skip); } +#endif if (ret != 0) { fprintf(stderr, "%s\n", wc_GetErrorString(ret)); diff --git a/examples/client/client.c b/examples/client/client.c index 020e0f55de..7c2aa674d4 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1103,7 +1103,7 @@ static int ClientWriteRead(WOLFSSL* ssl, const char* msg, int msgSz, /* 4. add the same message into Japanese section */ /* (will be translated later) */ /* 5. add printf() into suitable position of Usage() */ -static const char* client_usage_msg[][75] = { +static const char* client_usage_msg[][78] = { /* English */ { " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ @@ -1318,9 +1318,13 @@ static const char* client_usage_msg[][75] = { #ifndef NO_PSK "--openssl-psk Use TLS 1.3 PSK callback compatible with OpenSSL\n", /* 74 */ #endif +#ifdef HAVE_RPK + "--rpk Use RPK for the defined certificates\n", /* 75 */ +#endif + "--files-are-der Specified files are in DER, not PEM format\n", /* 76 */ "\n" "For simpler wolfSSL TLS client examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 75 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 77 */ NULL, }, #ifndef NO_MULTIBYTE_PRINT @@ -1542,10 +1546,14 @@ static const char* client_usage_msg[][75] = { #ifndef NO_PSK "--openssl-psk Use TLS 1.3 PSK callback compatible with OpenSSL\n", /* 74 */ #endif +#ifdef HAVE_RPK + "--rpk Use RPK for the defined certificates\n", /* 75 */ +#endif + "--files-are-der Specified files are in DER, not PEM format\n", /* 76 */ "\n" "より簡単なwolfSSL TLS クライアントの例については" "下記にアクセスしてください\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 75 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 77 */ NULL, }, #endif @@ -1763,9 +1771,9 @@ static void Usage(void) printf("%s", msg[++msgid]); /* Examples repo link */ #ifdef HAVE_PQC printf("%s", msg[++msgid]); /* --pqc */ - printf("%s", msg[++msgid]); /* --pqc options */ - printf("%s", msg[++msgid]); /* more --pqc options */ - printf("%s", msg[++msgid]); /* more --pqc options */ +#endif +#ifdef WOLFSSL_SRTP + printf("%s", msg[++msgid]); /* dtls-srtp */ #endif #ifdef WOLFSSL_SYS_CA_CERTS printf("%s", msg[++msgid]); /* --sys-ca-certs */ @@ -1773,9 +1781,14 @@ static void Usage(void) #ifdef HAVE_SUPPORTED_CURVES printf("%s", msg[++msgid]); /* --onlyPskDheKe */ #endif -#ifdef WOLFSSL_SRTP - printf("%s", msg[++msgid]); /* dtls-srtp */ +#ifndef NO_PSK + printf("%s", msg[++msgid]); /* --openssl-psk */ +#endif +#ifdef HAVE_RPK + printf("%s", msg[++msgid]); /* --rpk */ #endif + printf("%s", msg[++msgid]); /* --files-are-der */ + printf("%s", msg[++msgid]); /* Documentation Hint */ } #ifdef WOLFSSL_SRTP @@ -1919,6 +1932,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { "openssl-psk", 0, 265 }, #endif { "quieter", 0, 266 }, +#ifdef HAVE_RPK + { "rpk", 0, 267 }, +#endif /* HAVE_RPK */ + { "files-are-der", 0, 268 }, { 0, 0, 0 } }; #endif @@ -2059,6 +2076,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int useDtlsCID = 0; char dtlsCID[DTLS_CID_BUFFER_SIZE] = { 0 }; #endif /* WOLFSSL_DTLS_CID */ +#ifdef HAVE_RPK + int useRPK = 0; +#endif /* HAVE_RPK */ + int fileFormat = WOLFSSL_FILETYPE_PEM; char buffer[WOLFSSL_MAX_ERROR_SZ]; @@ -2082,6 +2103,17 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) WOLFSSL_HEAP_HINT *heap = NULL; #endif +#ifdef WOLFSSL_DUAL_ALG_CERTS + /* Set our preference for verfication to be for both the native and + * alternative chains. Ultimately, its the server's choice. This will be + * used in the call to wolfSSL_UseCKS(). */ + byte cks_order[3] = { + WOLFSSL_CKS_SIGSPEC_BOTH, + WOLFSSL_CKS_SIGSPEC_ALTERNATIVE, + WOLFSSL_CKS_SIGSPEC_NATIVE, + }; +#endif /* WOLFSSL_DUAL_ALG_CERTS */ + ((func_args*)args)->return_code = -1; /* error state */ #ifndef NO_RSA @@ -2134,6 +2166,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)usePqc; (void)pqcAlg; (void)opensslPsk; + (void)fileFormat; StackTrap(); /* Reinitialize the global myVerifyAction. */ @@ -2756,6 +2789,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) case 266: quieter = 1; break; + case 267: +#ifdef HAVE_RPK + useRPK = 1; +#endif /* HAVE_RPK */ + break; + case 268: + fileFormat = WOLFSSL_FILETYPE_ASN1; + break; default: Usage(); XEXIT_T(MY_EX_USAGE); @@ -3129,6 +3170,21 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif +#ifdef HAVE_RPK + if (useRPK) { + char ctype[] = {WOLFSSL_CERT_TYPE_RPK}; + char stype[] = {WOLFSSL_CERT_TYPE_RPK}; + + wolfSSL_CTX_set_client_cert_type(ctx, ctype, sizeof(ctype)/sizeof(ctype[0])); + wolfSSL_CTX_set_server_cert_type(ctx, stype, sizeof(stype)/sizeof(stype[0])); + usePsk = 0; + #ifdef HAVE_CRL + disableCRL = 1; + #endif + doPeerCheck = 0; + } +#endif /* HAVE_RPK */ + if (usePsk) { #ifndef NO_PSK const char *defaultCipherList = cipherList; @@ -3261,7 +3317,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) err_sys("can't load client cert buffer"); #elif !defined(TEST_LOAD_BUFFER) - if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) + if (wolfSSL_CTX_use_certificate_chain_file_format(ctx, ourCert, fileFormat) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't load client cert file, check file and run from" @@ -3285,7 +3341,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) sizeof_client_key_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) err_sys("can't load client private key buffer"); #elif !defined(TEST_LOAD_BUFFER) - if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, WOLFSSL_FILETYPE_PEM) + if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, fileFormat) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't load client private key file, check file and run " @@ -3559,20 +3615,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #ifdef WOLFSSL_DUAL_ALG_CERTS - /* Set our preference for verfication to be for both the native and - * alternative chains. Ultimately, its the server's choice. - */ - { - byte cks_order[3] = { - WOLFSSL_CKS_SIGSPEC_BOTH, - WOLFSSL_CKS_SIGSPEC_ALTERNATIVE, - WOLFSSL_CKS_SIGSPEC_NATIVE, - }; - - if (!wolfSSL_UseCKS(ssl, cks_order, sizeof(cks_order))) { - wolfSSL_CTX_free(ctx); ctx = NULL; - err_sys("unable to set the CKS order."); - } + if (!wolfSSL_UseCKS(ssl, cks_order, sizeof(cks_order))) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("unable to set the CKS order."); } #endif /* WOLFSSL_DUAL_ALG_CERTS */ @@ -3593,7 +3638,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err_sys("can't load client cert buffer"); } #elif !defined(TEST_LOAD_BUFFER) - if (wolfSSL_use_certificate_chain_file(ssl, ourCert) + if (wolfSSL_use_certificate_chain_file_format(ssl, ourCert, fileFormat) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't load client cert file, check file and run from" @@ -3614,7 +3659,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) sizeof_client_key_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) err_sys("can't load client private key buffer"); #elif !defined(TEST_LOAD_BUFFER) - if (wolfSSL_use_PrivateKey_file(ssl, ourKey, WOLFSSL_FILETYPE_PEM) + if (wolfSSL_use_PrivateKey_file(ssl, ourKey, fileFormat) != WOLFSSL_SUCCESS) { wolfSSL_CTX_free(ctx); ctx = NULL; err_sys("can't load client private key file, check file and run " diff --git a/examples/configs/user_settings_wolftpm.h b/examples/configs/user_settings_wolftpm.h index 6797211303..20da890b30 100644 --- a/examples/configs/user_settings_wolftpm.h +++ b/examples/configs/user_settings_wolftpm.h @@ -131,7 +131,7 @@ extern "C" { #else #define NO_RSA #endif -#ifndef USE_LOW_RESOURCE /* ECC */ +#if 1 /* ECC - needed for encrypt ECC salt */ #define HAVE_ECC #define ECC_USER_CURVES /* default to only SECP256R1 */ #endif diff --git a/examples/server/server.c b/examples/server/server.c index 50b6d0a889..6f0faf3385 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -513,14 +513,19 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, #define SIZE_FMT "%zu" #define SIZE_TYPE size_t #endif - printf( - "wolfSSL Server Benchmark " SIZE_FMT " bytes\n" - "\tRX %8.3f ms (%8.3f MBps)\n" - "\tTX %8.3f ms (%8.3f MBps)\n", - (SIZE_TYPE)throughput, - rx_time * 1000, throughput / rx_time / 1024 / 1024, - tx_time * 1000, throughput / tx_time / 1024 / 1024 - ); + if (rx_time > 0.0 && tx_time > 0.0) { + printf( + "wolfSSL Server Benchmark " SIZE_FMT " bytes\n" + "\tRX %8.3f ms (%8.3f MBps)\n" + "\tTX %8.3f ms (%8.3f MBps)\n", + (SIZE_TYPE)throughput, + rx_time * 1000, throughput / rx_time / 1024 / 1024, + tx_time * 1000, throughput / tx_time / 1024 / 1024 + ); + } + else { + printf("Invalid rx_time: %f or tx_time: %f\n", rx_time, tx_time); + } } return 0; diff --git a/linuxkm/Kbuild b/linuxkm/Kbuild index 29e8092ab6..701c3ad0a9 100644 --- a/linuxkm/Kbuild +++ b/linuxkm/Kbuild @@ -114,6 +114,16 @@ $(obj)/wolfcrypt/src/aes_xts_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU $(obj)/wolfcrypt/src/aes_xts_asm.o: OBJECT_FILES_NON_STANDARD := y $(obj)/wolfcrypt/src/sp_x86_64_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE) $(obj)/wolfcrypt/src/sp_x86_64_asm.o: OBJECT_FILES_NON_STANDARD := y +$(obj)/wolfcrypt/src/sha256_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE) +$(obj)/wolfcrypt/src/sha256_asm.o: OBJECT_FILES_NON_STANDARD := y +$(obj)/wolfcrypt/src/sha512_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE) +$(obj)/wolfcrypt/src/sha512_asm.o: OBJECT_FILES_NON_STANDARD := y +$(obj)/wolfcrypt/src/sha3_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE) +$(obj)/wolfcrypt/src/sha3_asm.o: OBJECT_FILES_NON_STANDARD := y +$(obj)/wolfcrypt/src/chacha_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE) +$(obj)/wolfcrypt/src/chacha_asm.o: OBJECT_FILES_NON_STANDARD := y +$(obj)/wolfcrypt/src/poly1305_asm.o: asflags-y = $(WOLFSSL_ASFLAGS) $(ASFLAGS_FPU_DISABLE_SIMD_ENABLE) +$(obj)/wolfcrypt/src/poly1305_asm.o: OBJECT_FILES_NON_STANDARD := y ifeq "$(ENABLED_LINUXKM_PIE)" "yes" diff --git a/linuxkm/linuxkm_memory.c b/linuxkm/linuxkm_memory.c index 81a7dfab36..19dd70a84a 100644 --- a/linuxkm/linuxkm_memory.c +++ b/linuxkm/linuxkm_memory.c @@ -73,6 +73,13 @@ void *lkm_realloc(void *ptr, size_t newsize) { #if defined(WOLFSSL_LINUXKM_USE_SAVE_VECTOR_REGISTERS) && defined(CONFIG_X86) +/* kernel 4.19 -- the most recent LTS before 5.4 -- lacks the necessary safety + * checks in __kernel_fpu_begin(), and lacks TIF_NEED_FPU_LOAD. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)) + #error WOLFSSL_LINUXKM_USE_SAVE_VECTOR_REGISTERS on x86 requires kernel 5.4.0 or higher. +#endif + static unsigned int wc_linuxkm_fpu_states_n_tracked = 0; struct wc_thread_fpu_count_ent { @@ -83,6 +90,10 @@ struct wc_thread_fpu_count_ent *wc_linuxkm_fpu_states = NULL; #ifdef WOLFSSL_COMMERCIAL_LICENSE +#ifndef LINUXKM_FPU_STATES_FOLLOW_THREADS + #error WOLFSSL_COMMERCIAL_LICENSE requires LINUXKM_FPU_STATES_FOLLOW_THREADS +#endif + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wnested-externs" @@ -105,6 +116,10 @@ static union wc_linuxkm_fpu_savebuf { WARN_UNUSED_RESULT int allocate_wolfcrypt_linuxkm_fpu_states(void) { if (wc_linuxkm_fpu_states != NULL) { +#ifdef HAVE_FIPS + /* see note below in wc_linuxkm_fpu_state_assoc_unlikely(). */ + return 0; +#else static int warned_for_repeat_alloc = 0; if (! warned_for_repeat_alloc) { pr_err("attempt at repeat allocation" @@ -112,12 +127,17 @@ WARN_UNUSED_RESULT int allocate_wolfcrypt_linuxkm_fpu_states(void) warned_for_repeat_alloc = 1; } return BAD_STATE_E; +#endif } +#ifdef LINUXKM_FPU_STATES_FOLLOW_THREADS if (nr_cpu_ids >= 16) wc_linuxkm_fpu_states_n_tracked = nr_cpu_ids * 2; else wc_linuxkm_fpu_states_n_tracked = 32; +#else + wc_linuxkm_fpu_states_n_tracked = nr_cpu_ids; +#endif wc_linuxkm_fpu_states = (struct wc_thread_fpu_count_ent *)malloc( @@ -198,7 +218,8 @@ void free_wolfcrypt_linuxkm_fpu_states(void) { wc_linuxkm_fpu_states = NULL; } -/* lock-(mostly)-free thread-local storage facility for tracking recursive fpu +#ifdef LINUXKM_FPU_STATES_FOLLOW_THREADS +/* legacy thread-local storage facility for tracking recursive fpu * pushing/popping */ static struct wc_thread_fpu_count_ent *wc_linuxkm_fpu_state_assoc(int create_p) { @@ -209,12 +230,23 @@ static struct wc_thread_fpu_count_ent *wc_linuxkm_fpu_state_assoc(int create_p) static int _warned_on_null = 0; if (wc_linuxkm_fpu_states == NULL) { - if (_warned_on_null == 0) { - pr_err("wc_linuxkm_fpu_state_assoc called by pid %d" - " before allocate_wolfcrypt_linuxkm_fpu_states.\n", my_pid); - _warned_on_null = 1; +#ifdef HAVE_FIPS + /* FIPS needs to use SHA256 for the core verify HMAC, before + * reaching the regular wolfCrypt_Init() logic. to break the + * dependency loop on intelasm builds, we allocate here. + * this is not thread-safe and doesn't need to be. + */ + int ret = allocate_wolfcrypt_linuxkm_fpu_states(); + if (ret != 0) +#endif + { + if (_warned_on_null == 0) { + pr_err("wc_linuxkm_fpu_state_assoc called by pid %d" + " before allocate_wolfcrypt_linuxkm_fpu_states.\n", my_pid); + _warned_on_null = 1; + } + return NULL; } - return NULL; } } @@ -249,6 +281,139 @@ static struct wc_thread_fpu_count_ent *wc_linuxkm_fpu_state_assoc(int create_p) } } +#else /* !LINUXKM_FPU_STATES_FOLLOW_THREADS */ + +/* lock-free O(1)-lookup CPU-local storage facility for tracking recursive fpu + * pushing/popping. + * + * caller must have already called kernel_fpu_begin() or preempt_disable() + * before entering this or the streamlined inline version of it below. + */ +static struct wc_thread_fpu_count_ent *wc_linuxkm_fpu_state_assoc_unlikely(int create_p) { + int my_cpu = raw_smp_processor_id(); + pid_t my_pid = task_pid_nr(current), slot_pid; + struct wc_thread_fpu_count_ent *slot; + + { + static int _warned_on_null = 0; + if (wc_linuxkm_fpu_states == NULL) + { +#ifdef HAVE_FIPS + /* FIPS needs to use SHA256 for the core verify HMAC, before + * reaching the regular wolfCrypt_Init() logic. to break the + * dependency loop on intelasm builds, we allocate here. + * this is not thread-safe and doesn't need to be. + */ + int ret = allocate_wolfcrypt_linuxkm_fpu_states(); + if (ret != 0) +#endif + { + if (_warned_on_null == 0) { + pr_err("wc_linuxkm_fpu_state_assoc called by pid %d" + " before allocate_wolfcrypt_linuxkm_fpu_states.\n", my_pid); + _warned_on_null = 1; + } + return NULL; + } + } + } + + slot = &wc_linuxkm_fpu_states[my_cpu]; + slot_pid = __atomic_load_n(&slot->pid, __ATOMIC_CONSUME); + if (slot_pid == my_pid) { + if (create_p) { + static int _warned_on_redundant_create_p = 0; + if (_warned_on_redundant_create_p < 10) { + pr_err("wc_linuxkm_fpu_state_assoc called with create_p=1 by" + " pid %d on cpu %d with cpu slot already reserved by" + " said pid.\n", my_pid, my_cpu); + ++_warned_on_redundant_create_p; + } + } + return slot; + } + if (create_p) { + if (slot_pid == 0) { + __atomic_store_n(&slot->pid, my_pid, __ATOMIC_RELEASE); + return slot; + } else { + /* if the slot is already occupied, that can be benign due to a + * migration, but it will require fixup by the thread that owns the + * slot, which will happen when it releases its lock, or sooner (see + * below). + */ + static int _warned_on_mismatched_pid = 0; + if (_warned_on_mismatched_pid < 10) { + pr_warn("wc_linuxkm_fpu_state_assoc called by pid %d on cpu %d" + " but cpu slot already reserved by pid %d.\n", + my_pid, my_cpu, slot_pid); + ++_warned_on_mismatched_pid; + } + return NULL; + } + } else { + /* check for migration. this can happen despite our best efforts if any + * I/O occured while locked, e.g. kernel messages like "uninitialized + * urandom read". since we're locked now, we can safely migrate the + * entry in wc_linuxkm_fpu_states[], freeing up the slot on the previous + * cpu. + */ + unsigned int cpu_i; + for (cpu_i = 0; cpu_i < wc_linuxkm_fpu_states_n_tracked; ++cpu_i) { + if (__atomic_load_n( + &wc_linuxkm_fpu_states[cpu_i].pid, + __ATOMIC_CONSUME) + == my_pid) + { + wc_linuxkm_fpu_states[my_cpu] = wc_linuxkm_fpu_states[cpu_i]; + __atomic_store_n(&wc_linuxkm_fpu_states[cpu_i].fpu_state, 0, + __ATOMIC_RELEASE); + __atomic_store_n(&wc_linuxkm_fpu_states[cpu_i].pid, 0, + __ATOMIC_RELEASE); + return &wc_linuxkm_fpu_states[my_cpu]; + } + } + return NULL; + } +} + +static inline struct wc_thread_fpu_count_ent *wc_linuxkm_fpu_state_assoc( + int create_p) +{ + int my_cpu = raw_smp_processor_id(); /* my_cpu is only trustworthy if we're + * already nonpreemptible -- we'll + * determine that soon enough by + * checking if the pid matches or, + * failing that, if create_p. + */ + pid_t my_pid = task_pid_nr(current), slot_pid; + struct wc_thread_fpu_count_ent *slot; + + if (unlikely(wc_linuxkm_fpu_states == NULL)) + return wc_linuxkm_fpu_state_assoc_unlikely(create_p); + + slot = &wc_linuxkm_fpu_states[my_cpu]; + slot_pid = __atomic_load_n(&slot->pid, __ATOMIC_CONSUME); + if (slot_pid == my_pid) { + if (unlikely(create_p)) + return wc_linuxkm_fpu_state_assoc_unlikely(create_p); + else + return slot; + } + if (likely(create_p)) { + if (likely(slot_pid == 0)) { + __atomic_store_n(&slot->pid, my_pid, __ATOMIC_RELEASE); + return slot; + } else { + return wc_linuxkm_fpu_state_assoc_unlikely(create_p); + } + } else { + return wc_linuxkm_fpu_state_assoc_unlikely(create_p); + } +} + +#endif /* !LINUXKM_FPU_STATES_FOLLOW_THREADS */ + #ifdef WOLFSSL_COMMERCIAL_LICENSE static struct fpstate *wc_linuxkm_fpstate_buf_from_fpu_state( struct wc_thread_fpu_count_ent *state) @@ -258,7 +423,9 @@ static struct fpstate *wc_linuxkm_fpstate_buf_from_fpu_state( } #endif -static void wc_linuxkm_fpu_state_release(struct wc_thread_fpu_count_ent *ent) { +static void wc_linuxkm_fpu_state_release_unlikely( + struct wc_thread_fpu_count_ent *ent) +{ if (ent->fpu_state != 0) { static int warned_nonzero_fpu_state = 0; if (! warned_nonzero_fpu_state) { @@ -271,16 +438,46 @@ static void wc_linuxkm_fpu_state_release(struct wc_thread_fpu_count_ent *ent) { __atomic_store_n(&ent->pid, 0, __ATOMIC_RELEASE); } +static inline void wc_linuxkm_fpu_state_release( + struct wc_thread_fpu_count_ent *ent) +{ + if (unlikely(ent->fpu_state != 0)) + return wc_linuxkm_fpu_state_release_unlikely(ent); + __atomic_store_n(&ent->pid, 0, __ATOMIC_RELEASE); +} + +WARN_UNUSED_RESULT int can_save_vector_registers_x86(void) +{ + if (irq_fpu_usable()) + return 1; + else if (in_nmi() || (hardirq_count() > 0) || (softirq_count() > 0)) + return 0; + else if (test_thread_flag(TIF_NEED_FPU_LOAD)) + return 1; + return 0; +} + WARN_UNUSED_RESULT int save_vector_registers_x86(void) { +#ifdef LINUXKM_FPU_STATES_FOLLOW_THREADS struct wc_thread_fpu_count_ent *pstate = wc_linuxkm_fpu_state_assoc(1); - if (pstate == NULL) - return MEMORY_E; +#else + struct wc_thread_fpu_count_ent *pstate = wc_linuxkm_fpu_state_assoc(0); +#endif /* allow for nested calls */ - if (pstate->fpu_state != 0U) { - if ((pstate->fpu_state & WC_FPU_COUNT_MASK) - == WC_FPU_COUNT_MASK) +#ifdef LINUXKM_FPU_STATES_FOLLOW_THREADS + if (pstate == NULL) + return MEMORY_E; +#endif + if ( +#ifndef LINUXKM_FPU_STATES_FOLLOW_THREADS + (pstate != NULL) && +#endif + (pstate->fpu_state != 0U)) + { + if (unlikely((pstate->fpu_state & WC_FPU_COUNT_MASK) + == WC_FPU_COUNT_MASK)) { pr_err("save_vector_registers_x86 recursion register overflow for " "pid %d.\n", pstate->pid); @@ -291,38 +488,87 @@ WARN_UNUSED_RESULT int save_vector_registers_x86(void) } } - if (irq_fpu_usable()) { + if (irq_fpu_usable() +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)) + /* work around a kernel bug -- see linux commit 59f5ede3bc0f0. + * what we really want here is this_cpu_read(in_kernel_fpu), but + * in_kernel_fpu is an unexported static array. + */ + && !test_thread_flag(TIF_NEED_FPU_LOAD) +#endif + ) + { #ifdef WOLFSSL_COMMERCIAL_LICENSE struct fpstate *fpstate = wc_linuxkm_fpstate_buf_from_fpu_state(pstate); fpregs_lock(); fpstate->xfeatures = ~0UL; os_xsave(fpstate); #else /* !WOLFSSL_COMMERCIAL_LICENSE */ -#if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) + #if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) /* inhibit migration, which gums up the algorithm in * kernel_fpu_{begin,end}(). */ migrate_disable(); -#endif + #endif kernel_fpu_begin(); + +#ifndef LINUXKM_FPU_STATES_FOLLOW_THREADS + pstate = wc_linuxkm_fpu_state_assoc(1); + if (pstate == NULL) { + kernel_fpu_end(); + #if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) && \ + !defined(WOLFSSL_COMMERCIAL_LICENSE) + migrate_enable(); + #endif + return BAD_STATE_E; + } +#endif + #endif /* !WOLFSSL_COMMERCIAL_LICENSE */ - /* set msb 0 to trigger kernel_fpu_end() at cleanup. */ + /* set msb to 0 to trigger kernel_fpu_end() at cleanup. */ pstate->fpu_state = 1U; } else if (in_nmi() || (hardirq_count() > 0) || (softirq_count() > 0)) { static int warned_fpu_forbidden = 0; if (! warned_fpu_forbidden) pr_err("save_vector_registers_x86 called from IRQ handler.\n"); +#ifdef LINUXKM_FPU_STATES_FOLLOW_THREADS wc_linuxkm_fpu_state_release(pstate); +#endif + return BAD_STATE_E; + } else if (!test_thread_flag(TIF_NEED_FPU_LOAD)) { + static int warned_fpu_forbidden = 0; + if (! warned_fpu_forbidden) + pr_err("save_vector_registers_x86 called with !irq_fpu_usable from" + " thread without previous FPU save.\n"); +#ifdef LINUXKM_FPU_STATES_FOLLOW_THREADS + wc_linuxkm_fpu_state_release(pstate); +#endif return BAD_STATE_E; } else { + /* assume already safely in_kernel_fpu from caller, but recursively + * preempt_disable() to be extra-safe. + */ + preempt_disable(); #if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \ (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) && \ !defined(WOLFSSL_COMMERCIAL_LICENSE) migrate_disable(); #endif - /* assume already safely in_kernel_fpu. */ - /* set msb 1 to inhibit kernel_fpu_end() at cleanup. */ +#ifndef LINUXKM_FPU_STATES_FOLLOW_THREADS + pstate = wc_linuxkm_fpu_state_assoc(1); + if (pstate == NULL) { + #if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \ + (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) && \ + !defined(WOLFSSL_COMMERCIAL_LICENSE) + migrate_enable(); + #endif + preempt_enable(); + return BAD_STATE_E; + } +#endif + /* set msb to 1 to inhibit kernel_fpu_end() at cleanup. */ pstate->fpu_state = WC_FPU_SAVED_MASK + 1U; } @@ -333,9 +579,10 @@ WARN_UNUSED_RESULT int save_vector_registers_x86(void) void restore_vector_registers_x86(void) { struct wc_thread_fpu_count_ent *pstate = wc_linuxkm_fpu_state_assoc(0); - if (pstate == NULL) { - pr_err("restore_vector_registers_x86 called by pid %d " - "with no saved state.\n", task_pid_nr(current)); + if (unlikely(pstate == NULL)) { + pr_err("restore_vector_registers_x86 called by pid %d on CPU %d " + "with no saved state.\n", task_pid_nr(current), + raw_smp_processor_id()); return; } @@ -349,17 +596,27 @@ void restore_vector_registers_x86(void) os_xrstor(fpstate, fpstate->xfeatures); fpregs_unlock(); #else + #ifndef LINUXKM_FPU_STATES_FOLLOW_THREADS + wc_linuxkm_fpu_state_release(pstate); + #endif kernel_fpu_end(); #endif - } else + } else { pstate->fpu_state = 0U; + #ifndef LINUXKM_FPU_STATES_FOLLOW_THREADS + wc_linuxkm_fpu_state_release(pstate); + #endif + preempt_enable(); + } #if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_COUNT) && \ (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) && \ !defined(WOLFSSL_COMMERCIAL_LICENSE) migrate_enable(); #endif +#ifdef LINUXKM_FPU_STATES_FOLLOW_THREADS wc_linuxkm_fpu_state_release(pstate); +#endif return; } diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index 3553eb8bc5..12dfbde266 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -338,6 +338,13 @@ #else #include #endif + #ifndef CAN_SAVE_VECTOR_REGISTERS + #ifdef DEBUG_VECTOR_REGISTER_ACCESS_FUZZING + #define CAN_SAVE_VECTOR_REGISTERS() (can_save_vector_registers_x86() && (SAVE_VECTOR_REGISTERS2_fuzzer() == 0)) + #else + #define CAN_SAVE_VECTOR_REGISTERS() can_save_vector_registers_x86() + #endif + #endif #ifndef SAVE_VECTOR_REGISTERS #define SAVE_VECTOR_REGISTERS(fail_clause) { \ int _svr_ret = save_vector_registers_x86(); \ @@ -369,6 +376,9 @@ #ifndef SAVE_VECTOR_REGISTERS2 #define SAVE_VECTOR_REGISTERS2() save_vector_registers_arm() #endif + #ifndef CAN_SAVE_VECTOR_REGISTERS + #define CAN_SAVE_VECTOR_REGISTERS() can_save_vector_registers_arm() + #endif #ifndef RESTORE_VECTOR_REGISTERS #define RESTORE_VECTOR_REGISTERS() restore_vector_registers_arm() #endif @@ -393,6 +403,25 @@ #ifdef HAVE_FIPS extern int wolfCrypt_FIPS_first(void); extern int wolfCrypt_FIPS_last(void); + #if FIPS_VERSION3_GE(6,0,0) + extern int wolfCrypt_FIPS_AES_sanity(void); + extern int wolfCrypt_FIPS_CMAC_sanity(void); + extern int wolfCrypt_FIPS_DH_sanity(void); + extern int wolfCrypt_FIPS_ECC_sanity(void); + extern int wolfCrypt_FIPS_ED25519_sanity(void); + extern int wolfCrypt_FIPS_ED448_sanity(void); + extern int wolfCrypt_FIPS_HMAC_sanity(void); + extern int wolfCrypt_FIPS_KDF_sanity(void); + extern int wolfCrypt_FIPS_PBKDF_sanity(void); + extern int wolfCrypt_FIPS_DRBG_sanity(void); + extern int wolfCrypt_FIPS_RSA_sanity(void); + extern int wolfCrypt_FIPS_SHA_sanity(void); + extern int wolfCrypt_FIPS_SHA256_sanity(void); + extern int wolfCrypt_FIPS_SHA512_sanity(void); + extern int wolfCrypt_FIPS_SHA3_sanity(void); + extern int wolfCrypt_FIPS_FT_sanity(void); + extern int wc_RunAllCast_fips(void); + #endif #endif #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) @@ -553,6 +582,25 @@ #ifdef HAVE_FIPS typeof(wolfCrypt_FIPS_first) *wolfCrypt_FIPS_first; typeof(wolfCrypt_FIPS_last) *wolfCrypt_FIPS_last; + #if FIPS_VERSION3_GE(6,0,0) + typeof(wolfCrypt_FIPS_AES_sanity) *wolfCrypt_FIPS_AES_sanity; + typeof(wolfCrypt_FIPS_CMAC_sanity) *wolfCrypt_FIPS_CMAC_sanity; + typeof(wolfCrypt_FIPS_DH_sanity) *wolfCrypt_FIPS_DH_sanity; + typeof(wolfCrypt_FIPS_ECC_sanity) *wolfCrypt_FIPS_ECC_sanity; + typeof(wolfCrypt_FIPS_ED25519_sanity) *wolfCrypt_FIPS_ED25519_sanity; + typeof(wolfCrypt_FIPS_ED448_sanity) *wolfCrypt_FIPS_ED448_sanity; + typeof(wolfCrypt_FIPS_HMAC_sanity) *wolfCrypt_FIPS_HMAC_sanity; + typeof(wolfCrypt_FIPS_KDF_sanity) *wolfCrypt_FIPS_KDF_sanity; + typeof(wolfCrypt_FIPS_PBKDF_sanity) *wolfCrypt_FIPS_PBKDF_sanity; + typeof(wolfCrypt_FIPS_DRBG_sanity) *wolfCrypt_FIPS_DRBG_sanity; + typeof(wolfCrypt_FIPS_RSA_sanity) *wolfCrypt_FIPS_RSA_sanity; + typeof(wolfCrypt_FIPS_SHA_sanity) *wolfCrypt_FIPS_SHA_sanity; + typeof(wolfCrypt_FIPS_SHA256_sanity) *wolfCrypt_FIPS_SHA256_sanity; + typeof(wolfCrypt_FIPS_SHA512_sanity) *wolfCrypt_FIPS_SHA512_sanity; + typeof(wolfCrypt_FIPS_SHA3_sanity) *wolfCrypt_FIPS_SHA3_sanity; + typeof(wolfCrypt_FIPS_FT_sanity) *wolfCrypt_FIPS_FT_sanity; + typeof(wc_RunAllCast_fips) *wc_RunAllCast_fips; + #endif #endif #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) @@ -720,6 +768,7 @@ extern __must_check int allocate_wolfcrypt_linuxkm_fpu_states(void); extern void free_wolfcrypt_linuxkm_fpu_states(void); + extern __must_check int can_save_vector_registers_x86(void); extern __must_check int save_vector_registers_x86(void); extern void restore_vector_registers_x86(void); diff --git a/linuxkm/lkcapi_glue.c b/linuxkm/lkcapi_glue.c index 7fe91afee3..4e474227ce 100644 --- a/linuxkm/lkcapi_glue.c +++ b/linuxkm/lkcapi_glue.c @@ -1818,7 +1818,7 @@ static int aes_xts_128_test(void) goto out; } -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); ret = wc_AesXtsEncrypt(aes, buf, p2, sizeof(p2), i2, sizeof(i2)); WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(0); @@ -1843,7 +1843,7 @@ static int aes_xts_128_test(void) goto out; } -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); ret = wc_AesXtsEncrypt(aes, buf, p1, sizeof(p1), i1, sizeof(i1)); WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(0); @@ -1865,7 +1865,7 @@ static int aes_xts_128_test(void) goto out; } -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); XMEMSET(cipher, 0, AES_XTS_128_TEST_BUF_SIZ); ret = wc_AesXtsEncrypt(aes, cipher, pp, sizeof(pp), i1, sizeof(i1)); @@ -1891,7 +1891,7 @@ static int aes_xts_128_test(void) goto out; } -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); XMEMSET(buf, 0, AES_XTS_128_TEST_BUF_SIZ); ret = wc_AesXtsDecrypt(aes, buf, cipher, sizeof(pp), i1, sizeof(i1)); @@ -1914,7 +1914,7 @@ static int aes_xts_128_test(void) goto out; } -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); XMEMSET(buf, 0, AES_XTS_128_TEST_BUF_SIZ); ret = wc_AesXtsDecrypt(aes, buf, c1, sizeof(c1), i1, sizeof(i1)); diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 6030480eee..74086513b8 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -232,7 +232,7 @@ static int wolfssl_init(void) fipsEntry(); ret = wolfCrypt_GetStatus_fips(); if (ret != 0) { - pr_err("wolfCrypt_GetStatus_fips() failed: %s\n", wc_GetErrorString(ret)); + pr_err("wolfCrypt_GetStatus_fips() failed with code %d: %s\n", ret, wc_GetErrorString(ret)); if (ret == IN_CORE_FIPS_E) { const char *newhash = wolfCrypt_GetCoreHash_fips(); pr_err("Update verifyCore[] in fips_test.c with new hash \"%s\" and rebuild.\n", @@ -545,6 +545,42 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) { wolfCrypt_FIPS_first; wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_last = wolfCrypt_FIPS_last; + #if FIPS_VERSION3_GE(6,0,0) + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_AES_sanity = + wolfCrypt_FIPS_AES_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_CMAC_sanity = + wolfCrypt_FIPS_CMAC_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_DH_sanity = + wolfCrypt_FIPS_DH_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_ECC_sanity = + wolfCrypt_FIPS_ECC_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_ED25519_sanity = + wolfCrypt_FIPS_ED25519_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_ED448_sanity = + wolfCrypt_FIPS_ED448_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_HMAC_sanity = + wolfCrypt_FIPS_HMAC_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_KDF_sanity = + wolfCrypt_FIPS_KDF_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_PBKDF_sanity = + wolfCrypt_FIPS_PBKDF_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_DRBG_sanity = + wolfCrypt_FIPS_DRBG_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_RSA_sanity = + wolfCrypt_FIPS_RSA_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_SHA_sanity = + wolfCrypt_FIPS_SHA_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_SHA256_sanity = + wolfCrypt_FIPS_SHA256_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_SHA512_sanity = + wolfCrypt_FIPS_SHA512_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_SHA3_sanity = + wolfCrypt_FIPS_SHA3_sanity; + wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_FT_sanity = + wolfCrypt_FIPS_FT_sanity; + wolfssl_linuxkm_pie_redirect_table.wc_RunAllCast_fips = + wc_RunAllCast_fips; + #endif #endif #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) diff --git a/scripts/aria-cmake-build-test.sh b/scripts/aria-cmake-build-test.sh index 1a6258fc48..0454fbb381 100644 --- a/scripts/aria-cmake-build-test.sh +++ b/scripts/aria-cmake-build-test.sh @@ -115,8 +115,7 @@ build_aria_test() { # View the available ciphers with: echo "checking wolfsl client ssl version numbers SSLv3(0) - TLS1.3(4):" - ./examples/client/client -V - if [ $? -eq 0 ]; then + if ./examples/client/client -V; then echo "Confirmed ./examples/client/client operational." else echo "ERROR ./examples/client/client error = $?" diff --git a/scripts/benchmark_compare.sh b/scripts/benchmark_compare.sh new file mode 100755 index 0000000000..b4ae1d603f --- /dev/null +++ b/scripts/benchmark_compare.sh @@ -0,0 +1,164 @@ +#!/bin/bash +# This script is designed to compare the output of wolfcrypt/benchmark test +# application. If the file has an extension ".csv", then it will parse the +# comma separated format, otherwise it will use the standard output format. The +# green colored output field is the better result. +# Usage: benchmark_compare.sh +# You can define a few variables to set options: +# THRESHOLD - set the threshold for equality between two results +# OUTPUT_CSV - set to "1" to print CSV + +FIRST_FILE=$1 +SECOND_FILE=$2 +THRESHOLD=${THRESHOLD:-"10"} +OUTPUT_CSV=${OUTPUT_CSV:-"0"} + +declare -A symStats +declare -A asymStats + +function getAlgo() { # getAlgo + if [ "$asCSV" = 1 ]; then + declare -a fields + IFS=',' read -ra fields <<< "$line" + if [ "$mode" = 1 ]; then + echo "${fields[0]}" + else + if [ "${fields[2]}" = "" ]; then + echo "${fields[0]}" + else + echo "${fields[0]}-${fields[2]}" + fi + fi + else + if [ "$mode" = 1 ]; then + echo "$line" | sed 's/ *[0-9]* MiB.*//g' + else + if [[ $line == "scrypt"* ]]; then + echo "scrypt" + else + echo "$line" | sed 's/ *[0-9]* ops.*//g' | sed 's/ \+[0-9]\+ \+/-/g' + fi + fi + fi +} + +function getValue() { # getValue + if [ "$asCSV" = 1 ]; then + declare -a fields + IFS=',' read -ra fields <<< "$line" + if [ "$mode" = 1 ]; then + echo "${fields[1]}" + else + echo "${fields[4]}" + fi + else + if [ "$mode" = 1 ]; then + echo "$line" | sed 's/.*seconds, *//g' | sed 's/ *MiB\/s.*//g' + else + echo "$line" | sed 's/.* ms, *//g' | sed 's/ ops\/sec.*//g' + fi + fi +} + +asCSV=0 +mode=0 +while IFS= read -r line; do + if [[ $FIRST_FILE == *".csv" ]]; then + asCSV=1 + if [[ $line == *"Symmetric Ciphers"* ]]; then + mode=1 + read + read + elif [[ $line == *"Asymmetric Ciphers"* ]]; then + mode=2 + read + read + elif [[ $line == "" ]]; then + mode=0 + fi + else + asCSV=0 + if [[ $line == *"MiB/s"* ]]; then + mode=1 + elif [[ $line == *"ops/sec"* ]]; then + mode=2 + else + mode=0 + fi + fi + if [ "$mode" -ne 0 ]; then + ALGO=`getAlgo "$asCSV" "$mode" "$line"` + VALUE=`getValue "$asCSV" "$mode" "$line"` + + if [ "$mode" = "1" ]; then + symStats["${ALGO}"]=${VALUE} + elif [ "$mode" = "2" ]; then + asymStats["${ALGO}"]=${VALUE} + fi + fi +done < ${FIRST_FILE} + +RED='\033[0;31m' +GRN='\033[0;32m' +NC='\033[0m' # No Color +function printData() { # printData + ALGO=$1 + VAL1=$2 + VAL2=$3 + if (( $(echo "sqrt( (${VAL1} - ${VAL2})^2 ) < ${THRESHOLD}" | bc -l) )); then + # take absolute value and check if less than a threshold + echo "${ALGO},${GRN}${VAL1}${NC},=,${GRN}${VAL2}${NC}\n" + elif (( $(echo "${VAL1} > ${VAL2}" | bc -l) )); then + echo "${ALGO},${GRN}${VAL1}${NC},>,${VAL2}\n" + else + echo "${ALGO},${VAL1},<,${GRN}${VAL2}${NC}\n" + fi +} + +asCSV=0 +mode=0 +while IFS= read -r line; do + if [[ $SECOND_FILE == *".csv" ]]; then + asCSV=1 + if [[ $line == *"Symmetric Ciphers"* ]]; then + RES+="ALGO,${FIRST_FILE},diff(MB/s),${SECOND_FILE}\n" + mode=1 + read + read + elif [[ $line == *"Asymmetric Ciphers"* ]]; then + RES+="\nALGO,${FIRST_FILE},diff(ops/sec),${SECOND_FILE}\n" + mode=2 + read + read + elif [[ $line == "" ]]; then + mode=0 + fi + else + asCSV=0 + if [[ $line == *"MiB/s"* ]]; then + mode=1 + elif [[ $line == *"ops/sec"* ]]; then + mode=2 + else + mode=0 + fi + fi + if [ "$mode" -ne 0 ]; then + if [[ $line == *","* ]]; then + ALGO=`getAlgo "$asCSV" "$mode" "$line"` + VALUE=`getValue "$asCSV" "$mode" "$line"` + + if [ "$mode" = "1" ]; then + RES+=`printData "${ALGO}" "${symStats["${ALGO}"]}" "${VALUE}"` + elif [ "$mode" = "2" ]; then + RES+=`printData "${ALGO}" "${asymStats["${ALGO}"]}" "${VALUE}"` + fi + fi + fi +done < ${SECOND_FILE} + +if [ "${OUTPUT_CSV}" = "1" ]; then + echo -e "$RES" +else + echo -e "$RES" | column -t -s ',' -L +fi diff --git a/scripts/dtls.test b/scripts/dtls.test index 2bf36d197b..8229d31bdd 100755 --- a/scripts/dtls.test +++ b/scripts/dtls.test @@ -25,17 +25,21 @@ if [ "${AM_BWRAPPED-}" != "yes" ]; then fi fi +kill_server() { + for i in $(jobs -pr); do + if [ "$i" != "$TCPDUMP_PID" ]; then + kill -9 $i + fi + done + # empty print to show which backgrounded processes were killed + sleep 0.2 && echo +} + cleanup () { echo echo "Cleaning up..." - if [ ! -z "$UDP_PROXY_PID" ];then - echo "Killing udp_proxy $UDP_PROXY_PID" - kill $UDP_PROXY_PID - fi - if [ ! -z "$SERVER_PID" ];then - echo "Killing server $SERVER_PID" - kill $SERVER_PID - fi + kill_server + if [ ! -z "$TCPDUMP_PID" ];then echo "Killing tcpdump $TCPDUMP_PID" sleep 1 @@ -69,9 +73,8 @@ run_test() { # usage: run_test "" "" "" " echo "" | nc -u 127.0.0.1 $SERVER_PORT # This is a marker for the PCAP file echo -e "\n${1}\n" stdbuf -oL -eL $WOLFSSL_ROOT/examples/server/server -u -p$SERVER_PORT $DTLS_VERSION $3 2>&1 | prepend "[server] " & - SERVER_PID=$(($! - 1)) + sleep 0.2 stdbuf -oL -eL $UDP_PROXY_BIN -p $PROXY_PORT -s 127.0.0.1:$SERVER_PORT $UDP_PROXY_EXTRA_ARGS $2 2>&1 | prepend "[udp-proxy] " & - UDP_PROXY_PID=$(($! - 1)) sleep 0.2 # Wrap this command in a timeout so that a deadlock won't bring down the entire test timeout -s KILL 1m stdbuf -oL -eL $WOLFSSL_ROOT/examples/client/client -u -p$PROXY_PORT $DTLS_VERSION $4 2>&1 | prepend "[client] " @@ -79,10 +82,7 @@ run_test() { # usage: run_test "" "" "" " echo "***Test failed***" ((NUM_TESTS_FAILED++)) fi - kill $SERVER_PID >&/dev/null # make sure the server is no longer running - SERVER_PID= - kill $UDP_PROXY_PID - UDP_PROXY_PID= + kill_server } test_dropping_packets () { diff --git a/scripts/dtlscid.test b/scripts/dtlscid.test index ff05181e92..f38bf4307e 100755 --- a/scripts/dtlscid.test +++ b/scripts/dtlscid.test @@ -1,6 +1,7 @@ #!/bin/bash -set -e +# dtlscid.test +# Copyright wolfSSL 2022-2024 # if we can, isolate the network namespace to eliminate port collisions. if [[ -n "$NETWORK_UNSHARE_HELPER" ]]; then diff --git a/scripts/include.am b/scripts/include.am index eab99c611e..f4f925a080 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -128,5 +128,6 @@ dist_noinst_SCRIPTS+= scripts/dtlscid.test endif EXTRA_DIST += scripts/bench/bench_functions.sh +EXTRA_DIST += scripts/benchmark_compare.sh EXTRA_DIST += scripts/user_settings_asm.sh diff --git a/src/conf.c b/src/conf.c index cfc6085a48..d177da5c71 100644 --- a/src/conf.c +++ b/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/include.am b/src/include.am index b89618b0eb..efc96f245a 100644 --- a/src/include.am +++ b/src/include.am @@ -21,7 +21,10 @@ EXTRA_DIST += src/ssl_asn1.c EXTRA_DIST += src/ssl_bn.c EXTRA_DIST += src/ssl_certman.c EXTRA_DIST += src/ssl_crypto.c +EXTRA_DIST += src/ssl_load.c EXTRA_DIST += src/ssl_misc.c +EXTRA_DIST += src/ssl_p7p12.c +EXTRA_DIST += src/ssl_sess.c EXTRA_DIST += src/x509.c EXTRA_DIST += src/x509_str.c @@ -59,6 +62,9 @@ endif if BUILD_AES src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes.c +if BUILD_CUDA +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/cuda/aes-cuda.cu +endif BUILD_CUDA endif if BUILD_AESNI @@ -151,6 +157,9 @@ endif if BUILD_AES src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes.c +if BUILD_CUDA +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/cuda/aes-cuda.cu +endif BUILD_CUDA if BUILD_ARMASM src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-aes.c endif BUILD_ARMASM @@ -278,6 +287,221 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fips.c \ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfcrypt_last.c endif BUILD_FIPS_V5 +if BUILD_FIPS_V6 +# FIPS 140-3 SRTP-KDF first file +src_libwolfssl@LIBSUFFIX@_la_SOURCES += \ + wolfcrypt/src/wolfcrypt_first.c + +src_libwolfssl@LIBSUFFIX@_la_SOURCES += \ + wolfcrypt/src/hmac.c \ + wolfcrypt/src/random.c + +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/kdf.c + +if BUILD_RSA +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/rsa.c +endif + +if BUILD_ECC +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ecc.c +endif + +if BUILD_AES +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes.c +if BUILD_ARMASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-aes.c +endif BUILD_ARMASM +if BUILD_ARMASM_NEON +if !BUILD_ARMASM_CRYPTO +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-aes-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-aes-asm.S +endif !BUILD_ARMASM_INLINE +endif !BUILD_ARMASM_CRYPTO +else +if BUILD_ARMASM +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-aes-asm_c.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-aes-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-aes-asm.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-aes-asm.S +endif !BUILD_ARMASM_INLINE +endif BUILD_ARMASM +endif !BUILD_ARMASM_NEON +endif BUILD_AES + +if BUILD_AESNI +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes_asm.S +if BUILD_X86_ASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes_gcm_x86_asm.S +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes_gcm_asm.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes_xts_asm.S +endif +endif + +if BUILD_SHA +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha.c +endif + +if BUILD_ARMASM_NEON +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha256.c +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha256-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha256-asm.S +endif !BUILD_ARMASM_INLINE +else +if BUILD_ARMASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha256.c +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha256-asm_c.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha256-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha256-asm.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha256-asm.S +endif !BUILD_ARMASM_INLINE +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha256.c +if BUILD_INTELASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha256_asm.S +endif BUILD_INTELASM +endif !BUILD_ARMASM +endif !BUILD_ARMASM_NEON + +if BUILD_SHA512 +if BUILD_ARMASM_NEON +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512.c +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512-asm_c.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512-asm.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +endif !BUILD_ARMASM_INLINE +else +if BUILD_ARMASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512.c +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm_c.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha512-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha512-asm.S +endif !BUILD_ARMASM_INLINE +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha512.c +if BUILD_INTELASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha512_asm.S +endif BUILD_INTELASM +endif !BUILD_ARMASM +endif !BUILD_ARMASM_NEON +endif BUILD_SHA512 + +if BUILD_SHA3 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha3.c +if BUILD_ARMASM_NEON +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha3-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha3-asm.S +endif !BUILD_ARMASM_INLINE +endif BUILD_ARMASM_NEON +if BUILD_INTELASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha3_asm.S +endif +endif + +if BUILD_DH +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/dh.c +endif + +if BUILD_CMAC +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/cmac.c +endif + +if BUILD_CURVE448 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/curve448.c +endif + +if BUILD_ED448 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ed448.c +endif + +if BUILD_CURVE25519 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/curve25519.c +endif + +if BUILD_ED25519 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ed25519.c +endif + +if BUILD_ARMASM +if BUILD_ARMASM_NEON +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519_c.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S +endif !BUILD_ARMASM_INLINE +else +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519_c.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-curve25519_c.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-curve25519.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S +endif !BUILD_ARMASM_INLINE +endif !BUILD_ARMASM_NEON +endif BUILD_ARMASM + +if BUILD_PWDBASED +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/pwdbased.c +endif BUILD_PWDBASED + +if BUILD_SP +if BUILD_SP_C32 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_c32.c +endif +if BUILD_SP_C64 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_c64.c +endif + +if BUILD_SP_X86_64 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_x86_64.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_x86_64_asm.S +endif +if !BUILD_FIPS_V2 +if BUILD_SP_ARM32 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_arm32.c +endif +endif +if BUILD_SP_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_armthumb.c +endif +if !BUILD_FIPS_V2 +if BUILD_SP_ARM64 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_arm64.c +endif +endif +if BUILD_SP_ARM_CORTEX +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_cortexm.c +endif +endif BUILD_SP + +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fips.c \ + wolfcrypt/src/fips_test.c + +# fips last file +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfcrypt_last.c +endif BUILD_FIPS_V6 + + endif BUILD_FIPS # For wolfRand, exclude everything else. @@ -309,9 +533,11 @@ endif !BUILD_DO178 if !BUILD_FIPS_RAND if !BUILD_FIPS_V5 +if !BUILD_FIPS_V6 if BUILD_KDF src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/kdf.c endif +endif !BUILD_FIPS_V6 endif !BUILD_FIPS_V5 if !BUILD_FIPS_CURRENT @@ -380,6 +606,7 @@ if BUILD_RC2 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/rc2.c endif +if !BUILD_FIPS_V6 if BUILD_SP if BUILD_SP_C32 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_c32.c @@ -409,6 +636,8 @@ if BUILD_SP_ARM_CORTEX src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_cortexm.c endif endif BUILD_SP +endif !BUILD_FIPS_V6 + if BUILD_SP_INT src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_int.c endif @@ -416,6 +645,9 @@ endif if !BUILD_FIPS_CURRENT if BUILD_AES src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes.c +if BUILD_CUDA +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/cuda/aes-cuda.cu +endif BUILD_CUDA if BUILD_ARMASM src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-aes.c endif BUILD_ARMASM @@ -641,10 +873,15 @@ if BUILD_MD5 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/md5.c endif +if !BUILD_FIPS_V6 if BUILD_PWDBASED src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/pwdbased.c +endif BUILD_PWDBASED +endif !BUILD_FIPS_V6 + +if BUILD_PKCS12 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/pkcs12.c -endif +endif BUILD_PKCS12 if BUILD_DSA src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/dsa.c @@ -744,6 +981,7 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_xmss.c src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_xmss_impl.c endif +if !BUILD_FIPS_V6 if BUILD_CURVE25519 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/curve25519.c endif @@ -751,17 +989,19 @@ endif if BUILD_ED25519 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ed25519.c endif +endif !BUILD_FIPS_V6 if BUILD_FEMATH if BUILD_CURVE25519_SMALL src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fe_low_mem.c else -if BUILD_INTELASM +if BUILD_CURVE25519_INTELASM if !BUILD_X86_ASM src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fe_x25519_asm.S endif !BUILD_X86_ASM else if BUILD_ARMASM +if !BUILD_FIPS_V6 if BUILD_ARMASM_NEON if BUILD_ARMASM_INLINE src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519_c.c @@ -781,10 +1021,11 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-curve25519 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S endif !BUILD_ARMASM_INLINE endif !BUILD_ARMASM_NEON +endif !BUILD_FIPS_V6 else src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fe_operations.c endif !BUILD_ARMASM -endif !BUILD_INTELASM +endif !BUILD_CURVE25519_INTELASM endif !BUILD_CURVE25519_SMALL endif BUILD_FEMATH @@ -794,18 +1035,19 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ge_low_mem.c else src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ge_operations.c if !BUILD_FEMATH -if BUILD_INTELASM +if BUILD_CURVE25519_INTELASM if !BUILD_X86_ASM src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fe_x25519_asm.S endif !BUILD_X86_ASM else +if !BUILD_FIPS_V6 if BUILD_ARMASM if BUILD_ARMASM_NEON if BUILD_ARMASM_INLINE src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519_c.c else src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S -endif +endif !BUILD_ARMASM_INLINE else if BUILD_ARMASM_INLINE src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-curve25519_c.c @@ -813,16 +1055,18 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519_ else src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-curve25519.S src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S -endif -endif +endif !BUILD_ARMASM_INLINE +endif !BUILD_ARMASM_NEON else src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fe_operations.c -endif -endif -endif -endif -endif +endif !BUILD_ARMASM +endif !BUILD_FIPS_V6 +endif !BUILD_CURVE25519_INTELASM +endif !BUILD_FEMATH +endif !BUILD_ED25519_SMALL +endif BUILD_GEMATH +if !BUILD_FIPS_V6 if BUILD_CURVE448 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/curve448.c endif @@ -830,6 +1074,7 @@ endif if BUILD_ED448 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ed448.c endif +endif !BUILD_FIPS_V6 if BUILD_FE448 src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fe_448.c diff --git a/src/internal.c b/src/internal.c index d889f33705..02e34dbc23 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2251,6 +2251,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 @@ -4333,11 +4336,15 @@ void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) #endif #ifdef HAVE_PQC 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 +4354,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; @@ -6761,9 +6768,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) 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; + ssl->buffers.altKey = ctx->altPrivateKey; + 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) && \ @@ -7573,6 +7583,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; @@ -9686,7 +9699,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 +9786,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) @@ -10561,8 +10584,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 +10595,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) @@ -11243,7 +11273,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); } @@ -12432,7 +12468,8 @@ void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType) 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,7 +12479,7 @@ 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 @@ -12963,23 +13000,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 */ @@ -13930,39 +13984,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) @@ -14288,7 +14309,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); } @@ -17181,9 +17220,6 @@ int SendFatalAlertOnly(WOLFSSL *ssl, int error) case COMPRESSION_ERROR: why = decode_error; break; - case MATCH_SUITE_ERROR: - why = illegal_parameter; - break; case VERIFY_FINISHED_ERROR: case SIG_VERIFY_E: why = decrypt_error; @@ -17196,6 +17232,7 @@ int SendFatalAlertOnly(WOLFSSL *ssl, int error) case ECC_OUT_OF_RANGE_E: why = bad_record_mac; break; + case MATCH_SUITE_ERROR: case VERSION_ERROR: default: why = handshake_failure; @@ -23076,6 +23113,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 +23125,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 +23162,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) { @@ -23203,12 +23267,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)) @@ -27676,7 +27746,7 @@ 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 keySz; @@ -27691,7 +27761,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx) #endif ) { - *length = (word16)GetPrivateKeySigSize(ssl); + *length = GetPrivateKeySigSize(ssl); return 0; } else @@ -27709,9 +27779,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 +27811,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)ssl->buffers.keySz; + *length = ssl->buffers.keySz; } #else ret = NOT_COMPILED_IN; @@ -27764,13 +27837,14 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)wc_ecc_sig_size_calc(ssl->buffers.keySz); + *length = wc_ecc_sig_size_calc(ssl->buffers.keySz); } #else ret = NOT_COMPILED_IN; #endif } - 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)) { #if defined(HAVE_PQC) && defined(HAVE_FALCON) if (ssl->buffers.keyLabel) { ret = wc_falcon_init_label((falcon_key*)ssl->hsKey, @@ -27783,6 +27857,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,13 +27872,15 @@ 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) { + 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_PQC) && defined(HAVE_DILITHIUM) if (ssl->buffers.keyLabel) { ret = wc_dilithium_init_label((dilithium_key*)ssl->hsKey, @@ -27809,6 +27893,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 +27911,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 +27965,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)keySz; + *length = keySz; goto exit_dpk; } @@ -27930,7 +28025,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsKey); + *length = wc_ecc_sig_size((ecc_key*)ssl->hsKey); goto exit_dpk; } @@ -28104,13 +28199,14 @@ 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; } @@ -28175,13 +28271,14 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) 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; } @@ -28201,12 +28298,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 keySz; + word32 idx; /* make sure alt private key exists */ if (ssl->buffers.altKey == NULL || ssl->buffers.altKey->buffer == NULL) { @@ -28214,8 +28314,279 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length) ERROR_OUT(NO_PRIVATE_KEY, exit_dapk); } +#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_PQC) && 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_PQC) && 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_PQC) +#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 +28601,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 +28628,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 +28667,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,8 +28676,18 @@ 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, @@ -28295,16 +28696,24 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length) 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 */ +#endif /* HAVE_PQC */ + + (void)idx; + (void)keySz; + (void)length; exit_dapk: if (ret != 0) { @@ -28313,7 +28722,7 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length) 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 +28793,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 +28803,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 +28891,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) { @@ -28818,6 +29232,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) */ @@ -30434,14 +30851,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); } @@ -32285,7 +32702,7 @@ typedef struct ScvArgs { word32 sigSz; int sendSz; int inputSz; - word16 length; + word32 length; byte sigAlgo; } ScvArgs; @@ -32504,7 +32921,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 +32931,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 +33110,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; @@ -33377,7 +33794,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; @@ -34111,7 +34528,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,7 +34546,7 @@ 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; ret = DecodePrivateKey(ssl, &keySz); @@ -34144,7 +34561,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 +34577,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 +34780,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; @@ -38611,7 +39028,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); @@ -38731,7 +39148,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); diff --git a/src/pk.c b/src/pk.c index d7d32dd528..8842a89a76 100644 --- a/src/pk.c +++ b/src/pk.c @@ -25,7 +25,7 @@ #include - #include +#include #ifndef WC_NO_RNG #include #endif @@ -49,14 +49,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 +159,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 +171,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 +220,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 +266,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 +277,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 +302,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 +313,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 +327,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, *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 +874,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 +906,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 @@ -1787,7 +1926,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 +1971,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; } @@ -5577,99 +5716,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, 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 */ @@ -7455,7 +7610,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) { @@ -7681,7 +7836,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; } @@ -12076,12 +12231,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 +12328,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 +12455,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 +12484,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 +12687,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 +13259,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 +13277,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); @@ -13869,5 +14045,2234 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outLen, * 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 siganture 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 siganture 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 = min(sz, 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 arguement. + * @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 arguement. + * @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 arguement. + * @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 arguement. + * @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 arguement. + * @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 = 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 foramt 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 foramt 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 success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +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 = 1; + } + + /* Encode into a buffer. */ + if ((!err) && (pem_write_data(name, header, data, len, &pem, &pemLen) != + 0)) { + pemLen = 0; + err = 1; + } + + /* Write PEM into BIO. */ + if ((!err) && (wolfSSL_BIO_write(bio, pem, pemLen) != (int)pemLen)) { + pemLen = 0; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return pemLen; +} +#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 foramt 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 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, 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 = 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 Pasword 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) != 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 = (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(*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, 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, *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 Pasword 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 Pasword 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, 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/quic.c b/src/quic.c index 66f866a484..756d023068 100644 --- a/src/quic.c +++ b/src/quic.c @@ -990,11 +990,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 +1013,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 +1037,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 +1088,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 @@ -1098,30 +1113,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) diff --git a/src/ssl.c b/src/ssl.c index ea66e429eb..c2b4f82058 100644 --- a/src/ssl.c +++ b/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 */ @@ -122,6 +123,9 @@ #if defined(HAVE_DILITHIUM) #include #endif /* HAVE_DILITHIUM */ + #if defined(HAVE_SPHINCS) + #include + #endif /* HAVE_SPHINCS */ #endif /* HAVE_PQC */ #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) #ifdef HAVE_OCSP @@ -137,12 +141,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 +158,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 +194,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 +289,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 +391,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 @@ -457,9 +441,12 @@ const WOLF_EC_NIST_NAME kNistCurves[] = { {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}, + {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 @@ -1067,209 +1054,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 +1128,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 +1399,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; @@ -2218,10 +2007,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 */ @@ -2465,7 +2256,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 +2508,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 +2542,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 +2568,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 +2582,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 +2606,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; } @@ -2922,7 +2684,8 @@ 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); } @@ -2983,138 +2746,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 +2766,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) @@ -3906,7 +3461,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"); @@ -4339,7 +3895,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); @@ -5709,7 +5266,8 @@ 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; @@ -5919,8 +5477,19 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) } #ifdef WOLFSSL_DUAL_ALG_CERTS - signer->sapkiDer = cert->sapkiDer; - signer->sapkiLen = cert->sapkiLen; + if (cert->extSapkiSet && cert->sapkiLen > 0) { + /* Allocated space for alternative public key. */ + signer->sapkiDer = (byte*)XMALLOC(cert->sapkiLen, cm->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 (cert->subjectCNStored) { @@ -6018,204 +5587,19 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) #endif /* !NO_CERTS */ -#ifndef NO_SESSION_CACHE +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB) +static int wolfSSL_RAND_InitMutex(void); +#endif - /* 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 - -#if defined(OPENSSL_EXTRA) && defined(HAVE_ATEXIT) -static void AtExitCleanup(void) -{ - if (initRefCount > 0) { - initRefCount = 1; - (void)wolfSSL_Cleanup(); - } -} -#endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_ATEXIT) +static void AtExitCleanup(void) +{ + if (initRefCount > 0) { + initRefCount = 1; + (void)wolfSSL_Cleanup(); + } +} +#endif WOLFSSL_ABI int wolfSSL_Init(void) @@ -6244,13 +5628,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 +5724,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 +5738,18697 @@ 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 - /* 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; - - 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; - } + return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type); +} - /* 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 */ - } - } - FreeDer(&part); +int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff, + long sz, int type) +{ + WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer"); - if (ret == ASN_NO_PEM_HEADER && gotOne) { - WOLFSSL_MSG("We got one good cert, so stuff at end ok"); - break; - } + if (ssl == NULL || ssl->ctx == NULL) + 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"); + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type); +} - /* 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 - } - } +#endif /* HAVE_CRL */ - if (dynamicBuffer) - XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); +#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); } - - 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_DisableOCSP(WOLFSSL* ssl) { - int ret; - - (void)devId; + WOLFSSL_ENTER("wolfSSL_DisableOCSP"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerDisableOCSP(SSL_CM(ssl)); + } + 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; - } +int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl)); } -#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 + 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)); } - 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_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; +} - *keyFormat = RSAk; - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - ssl->options.haveStaticECC = 0; - *resetSuites = 1; - } +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); } - - return ret; + 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_EnableOCSP(WOLFSSL_CTX* ctx, int options) { - int ret; + WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP"); + if (ctx) + return wolfSSL_CertManagerEnableOCSP(ctx->cm, options); + else + return BAD_FUNC_ARG; +} - /* make sure RSA key can be used */ -#ifdef WOLFSSL_SMALL_STACK - RsaKey* key; -#else - RsaKey key[1]; -#endif -#ifdef WOLFSSL_SMALL_STACK - key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA); - if (key == NULL) - return MEMORY_E; -#endif +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 = 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"); - } - - if (ssl) { - ssl->buffers.keyType = rsa_sa_algo; - ssl->buffers.keySz = *keySz; - } - else { - ctx->privateKeyType = rsa_sa_algo; - ctx->privateKeySz = *keySz; - } - *keyFormat = RSAk; +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 (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - ssl->options.haveStaticECC = 0; - *resetSuites = 1; - } - } - wc_FreeRsaKey(key); - } +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; +} -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_RSA); -#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; +} - return ret; +int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling"); + if (ctx) + return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm); + 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) +int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX* ctx) { - 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_CTX_EnableOCSPMustStaple"); + if (ctx) + return wolfSSL_CertManagerEnableOCSPMustStaple(ctx->cm); + 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; -#endif +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 */ - 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; - } +#endif /* HAVE_OCSP */ - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - else if (*keyFormat == 0) { - ret = 0; /* continue trying other algorithms */ - } +#ifdef HAVE_CRL - wc_ecc_free(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_ECC); -#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 /* 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) +#ifndef NO_FILESYSTEM +int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor) { - int ret; - /* make sure Ed25519 key can be used */ -#ifdef WOLFSSL_SMALL_STACK - ed25519_key* key; -#else - ed25519_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 = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, - DYNAMIC_TYPE_ED25519); - 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 - 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; - } +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); + } + else + return BAD_FUNC_ARG; +} - *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; +#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; +} #endif - if (ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - } - } - else if (*keyFormat == 0) { - ret = 0; /* continue trying other algorithms */ - } - wc_ed25519_free(key); - } +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; +} -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_ED25519); -#endif - return ret; + +int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL"); + if (ctx) + return wolfSSL_CertManagerDisableCRL(ctx->cm); + 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) + +#ifndef NO_FILESYSTEM +int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, + int type, int monitor) { - int ret; - /* make sure Ed448 key can be used */ -#ifdef WOLFSSL_SMALL_STACK - ed448_key* key = NULL; -#else - ed448_key key[1]; -#endif + WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL"); + if (ctx) + return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor); + else + return BAD_FUNC_ARG; +} -#ifdef WOLFSSL_SMALL_STACK - key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448); - if (key == NULL) - return MEMORY_E; +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; +} #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); - } -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_ED448); -#endif - return ret; +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; } -#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) +#ifdef HAVE_CRL_IO +int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb) { - 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; - } - 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; - } - } + WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb"); + if (ctx) + return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb); + else + return BAD_FUNC_ARG; +} +#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; - } - } - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - else if (*keyFormat == 0) { - ret = 0; /* continue trying other algorithms */ - } +#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"); - wc_falcon_free(key); + if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) { + WOLFSSL_MSG("Bad depth argument, too large or less than 0"); + return; } - XFREE(key, heap, DYNAMIC_TYPE_FALCON); - return ret; + + ctx->verifyDepth = (byte)depth; } -#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) + +/* get cert chaining depth using ssl struct */ +long wolfSSL_get_verify_depth(WOLFSSL* ssl) { - 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; - } - ret = wc_dilithium_init(key); - if (ret == 0) { - 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. */ - wc_dilithium_free(key); - ret = ALGO_ID_E; - } + if(ssl == NULL) { + return BAD_FUNC_ARG; } +#ifndef OPENSSL_EXTRA + return MAX_CHAIN_DEPTH; +#else + return ssl->options.verifyDepth; +#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 if (*keyFormat == 0) { - ret = 0; /* continue trying other algorithms */ - } - wc_dilithium_free(key); +/* get cert chaining depth using ctx struct */ +long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; } - XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM); - - return ret; +#ifndef OPENSSL_EXTRA + return MAX_CHAIN_DEPTH; +#else + return ctx->verifyDepth; +#endif } -#endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ -static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, - void* heap, int devId, int type) +#ifndef NO_CHECK_PRIVATE_KEY + +#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; - (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; + if (privKey == NULL) { + return MISSING_KEY; + } #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); -#else - ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keySz, idx, resetSuites, - keyFormat, heap, devId); -#endif - if (ret != 0) - return ret; + if (keyOID == RSAk) { + type = DYNAMIC_TYPE_RSA; + } +#ifdef WC_RSA_PSS + if (keyOID == RSAPSSk) { + type = DYNAMIC_TYPE_RSA; } #endif +#endif #ifdef HAVE_ECC - if ((*keyFormat == 0) || (*keyFormat == ECDSAk) - #ifdef WOLFSSL_SM2 - || (*keyFormat == SM2k) - #endif - ) { - ret = ProcessBufferTryDecodeEcc(ctx, ssl, der, keySz, idx, resetSuites, - keyFormat, heap, devId); - if (ret != 0) - return ret; + if (keyOID == ECDSAk) { + type = DYNAMIC_TYPE_ECC; } -#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; +#endif +#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + if ((keyOID == DILITHIUM_LEVEL2k) || + (keyOID == DILITHIUM_LEVEL3k) || + (keyOID == DILITHIUM_LEVEL5k)) { + type = DYNAMIC_TYPE_DILITHIUM; } -#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; +#endif +#if defined(HAVE_PQC) && defined(HAVE_FALCON) + if ((keyOID == FALCON_LEVEL1k) || + (keyOID == FALCON_LEVEL5k)) { + type = DYNAMIC_TYPE_FALCON; } -#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; +#endif + + ret = CreateDevPrivateKey(&pkey, privKey, privSz, type, label, id, + heap, devId); + #ifdef WOLF_CRYPTO_CB + if (ret == 0) { + #ifndef NO_RSA + if (keyOID == RSAk + #ifdef WC_RSA_PSS + || keyOID == RSAPSSk + #endif + ) { + ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, pubKey, pubSz); + } + #endif + #ifdef HAVE_ECC + if (keyOID == ECDSAk) { + ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, pubKey, pubSz); + } + #endif + #if defined(HAVE_PQC) && 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); + } + #endif + #if defined(HAVE_PQC) && defined(HAVE_FALCON) + if ((keyOID == FALCON_LEVEL1k) || + (keyOID == FALCON_LEVEL5k)) { + ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey, + WC_PQC_SIG_TYPE_FALCON, + pubKey, pubSz); + } + #endif } -#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; + #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); + } + #endif + #ifdef HAVE_ECC + if (keyOID == ECDSAk) { + wc_ecc_free((ecc_key*)pkey); + } + #endif + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + if ((keyOID == DILITHIUM_LEVEL2k) || + (keyOID == DILITHIUM_LEVEL3k) || + (keyOID == DILITHIUM_LEVEL5k)) { + wc_dilithium_free((dilithium_key*)pkey); } + #endif + #if defined(HAVE_PQC) && defined(HAVE_FALCON) + if ((keyOID == FALCON_LEVEL1k) || + (keyOID == FALCON_LEVEL5k)) { + wc_falcon_free((falcon_key*)pkey); + } + #endif + XFREE(pkey, heap, type); } -#endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ + return ret; } +#endif /* WOLF_PRIVATE_KEY_ID */ -/* 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; -#endif +/* 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) +{ #ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; + DecodedCert* der = NULL; #else - EncryptedInfo info[1]; + DecodedCert der[1]; #endif + word32 size; + byte* buff; + int ret = WOLFSSL_FAILURE; - (void)devId; - (void)idx; - (void)keySz; - - if (used) - *used = sz; /* used bytes default to sz, PEM chain may shorten*/ - - /* check args */ - if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM) - return WOLFSSL_BAD_FILETYPE; - - if (ctx == NULL && ssl == NULL) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("check_cert_key"); - /* This API does not handle CHAIN_CERT_TYPE */ - if (type == CHAIN_CERT_TYPE) - return BAD_FUNC_ARG; + if (cert == NULL || key == NULL) { + return WOLFSSL_FAILURE; + } #ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap, - DYNAMIC_TYPE_ENCRYPTEDINFO); - if (info == NULL) + der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, DYNAMIC_TYPE_DCERT); + if (der == NULL) return MEMORY_E; #endif - 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; + 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, heap, DYNAMIC_TYPE_DCERT); + #endif + return WOLFSSL_FAILURE; } -#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; - #endif + 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 != CRYPTOCB_UNAVAILABLE) { + ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; + } } 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 */ + /* fall through if unavailable */ + ret = CRYPTOCB_UNAVAILABLE; + } + + if (ret == CRYPTOCB_UNAVAILABLE) +#endif /* WOLF_PRIVATE_KEY_ID */ + { + ret = wc_CheckPrivateKeyCert(buff, size, der, 0); + ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; + } + +#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 { - ret = ASN_PARSE_E; + size = altKey->length; + buff = altKey->buffer; } - - info->consumed = length; - - 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; +#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); } - ret = 0; /* failures should be ignored */ } - #endif + 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 != 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, 1); + ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; } } +#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; +} - if (used) { - *used = info->consumed; +/* 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; } - /* 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; - } - } +#ifdef WOLFSSL_DUAL_ALG_CERTS + return check_cert_key(ctx->certificate, ctx->privateKey, ctx->altPrivateKey, + ctx->heap, ctx->privateKeyDevId, ctx->privateKeyLabel, + ctx->privateKeyId, ctx->altPrivateKeyDevId, ctx->altPrivateKeyLabel, + ctx->altPrivateKeyId); +#else + return check_cert_key(ctx->certificate, ctx->privateKey, NULL, ctx->heap, + ctx->privateKeyDevId, ctx->privateKeyLabel, ctx->privateKeyId, + INVALID_DEVID, 0, 0); +#endif +} +#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) +{ + const unsigned char *key; + int type; + + WOLFSSL_ENTER("wolfSSL_CTX_get0_privatekey"); + + if (ctx == NULL || ctx->privateKey == NULL || + ctx->privateKey->buffer == NULL) { + WOLFSSL_MSG("Bad parameter or key not set"); + return NULL; + } + + 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; } - /* info is only used for private key with DER or PEM, so free now */ - if (ret < 0 || type != PRIVATEKEY_TYPE) { + key = ctx->privateKey->buffer; + + if (ctx->privateKeyPKey != NULL) + return ctx->privateKeyPKey; + else + return wolfSSL_d2i_PrivateKey(type, + (WOLFSSL_EVP_PKEY**)&ctx->privateKeyPKey, &key, + (long)ctx->privateKey->length); +} +#endif + +#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(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + 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 { + isRsaKey = + (wc_RsaPublicKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0); } + wc_FreeRsaKey(rsa); +#ifdef WOLFSSL_SMALL_STACK + XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); +#endif - /* check for error */ - if (ret < 0) { - FreeDer(&der); - done = 1; + if (!isRsaKey) { + return -1; } - if (done == 1) { - /* No operation, just skip the next section */ + if (*out != NULL) { + pkey = *out; } - /* Handle DER owner */ - else if (type == CA_TYPE) { - if (ctx == NULL) { - WOLFSSL_MSG("Need context for CA load"); - FreeDer(&der); - return BAD_FUNC_ARG; + else { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("RSA wolfSSL_EVP_PKEY_new error"); + return 0; } - /* verify CA unless user set to no verify */ - ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify); - done = 1; } -#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"); - } - done = 1; + + 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) { + ret = 0; } -#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; + if (ret == 1) { + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_RSA; + + 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; } } - 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) { + *out = pkey; } -#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 == 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(ecc, NULL, DYNAMIC_TYPE_ECC); + #endif + return 0; + } + + if (priv) { + isEccKey = + (wc_EccPrivateKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0); } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ else { - FreeDer(&der); - return WOLFSSL_BAD_CERTTYPE; + 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; } - 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("ECC wolfSSL_EVP_PKEY_new error"); + return 0; + } + } - ForceZero(password, passwordSz); - } + 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) { + ret = 0; + } + if (ret == 1) { + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_EC; - #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->ownEcc = 1; + pkey->ecc = wolfSSL_EC_KEY_new(); + if (pkey->ecc == NULL) { + ret = 0; } - #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ + } + 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) { - #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 == 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 - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); - #endif - WOLFSSL_ERROR(WOLFSSL_BAD_FILE); - return WOLFSSL_BAD_FILE; - } + XMEMSET(dsa, 0, sizeof(DsaKey)); + + if (wc_InitDsaKey(dsa) != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); #endif + return 0; + } - (void)devId; + if (priv) { + isDsaKey = + (wc_DsaPrivateKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0); } - 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 + else { + isDsaKey = + (wc_DsaPublicKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0); + } + wc_FreeDsaKey(dsa); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); +#endif - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, - DYNAMIC_TYPE_DCERT); - if (cert == NULL) - return MEMORY_E; - #endif - - WOLFSSL_MSG("Checking cert signature type"); - InitDecodedCert_ex(cert, der->buffer, der->length, heap, devId); - - 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; - } -#if defined(HAVE_RPK) - if (ssl) { - ssl->options.rpkState.isRPKLoaded = 0; - if (cert->isRPK) { - ssl->options.rpkState.isRPKLoaded = 1; - } - } - else if (ctx) { - ctx->rpkState.isRPKLoaded = 0; - if (cert->isRPK) { - ctx->rpkState.isRPKLoaded = 1; - } - } -#endif /* HAVE_RPK */ + /* test if DSA key */ + if (!isDsaKey) { + return -1; + } - if (ssl) { - if (ssl->options.side == WOLFSSL_SERVER_END) - resetSuites = 1; - } - else if (ctx && ctx->method->side == WOLFSSL_SERVER_END) { - resetSuites = 1; - } - if (ssl && ssl->ctx->haveECDSAsig) { - WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off"); - ssl->options.haveECDSAsig = 0; /* may turn back on next */ + if (*out != NULL) { + pkey = *out; + } + else { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("DSA wolfSSL_EVP_PKEY_new error"); + return 0; } + } - 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; - } + 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) { + ret = 0; + } + if (ret == 1) { + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_DSA; - #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 - } - 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 + pkey->ownDsa = 1; + pkey->dsa = wolfSSL_DSA_new(); + if (pkey->dsa == NULL) { + ret = 0; } - #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 ((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 (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 */ + if ((ret == 0) && (*out == NULL)) { + wolfSSL_EVP_PKEY_free(pkey); + } + return ret; +} +#endif /* NO_DSA */ - default: - WOLFSSL_MSG("No key size check done on certificate"); - break; /* do no check if not a case for the key */ - } +#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 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 + XMEMSET(dh, 0, sizeof(DhKey)); - FreeDecodedCert(cert); + if (wc_InitDhKey(dh) != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, heap, DYNAMIC_TYPE_DCERT); + XFREE(dh, NULL, DYNAMIC_TYPE_DH); #endif - - if (ret != 0) { - done = 1; - } + return 0; } - 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 */ + isDhKey = (wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz) == 0); + wc_FreeDhKey(dh); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dh, NULL, DYNAMIC_TYPE_DH); +#endif - return ret; + /* test if DH key */ + if (!isDhKey) { + return -1; } - - if (ssl && resetSuites) { - word16 havePSK = 0; - word16 haveRSA = 0; - - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (ssl->options.havePSK) { - havePSK = 1; + if (*out != NULL) { + pkey = *out; + } + else { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("DH 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); + 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; } - else if (ctx && resetSuites) { - word16 havePSK = 0; - word16 haveRSA = 0; + if (ret == 1) { + XMEMCPY(pkey->pkey.ptr, mem, memSz); + pkey->type = EVP_PKEY_DH; - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (ctx->havePSK) { - havePSK = 1; + pkey->ownDh = 1; + pkey->dh = wolfSSL_DH_new(); + if (pkey->dh == NULL) { + ret = 0; } - #endif - #ifndef NO_RSA - haveRSA = 1; - #endif - keySz = ctx->privateKeySz; + } - 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); + 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; } - return WOLFSSL_SUCCESS; + 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) */ - -/* 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) +#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) { - 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; + 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)); - ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl, - &consumed, 0, verify); + /* test if DH-public key */ + if (wc_InitDhKey(dh) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dh, NULL, DYNAMIC_TYPE_DH); +#endif + return 0; + } - if (ret == MEMORY_E) { - return ret; - } - 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; - } + ret = wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz); + wc_FreeDhKey(dh); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dh, NULL, DYNAMIC_TYPE_DH); #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; - } - } - else { - WOLFSSL_MSG(" Processed a CA"); - gotOne = 1; - } - used += consumed; + if (ret != 0) { + return -1; } - if (gotOne) { - WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK"); - return WOLFSSL_SUCCESS; + if (*out != NULL) { + pkey = *out; + } + else { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + return 0; + } } - return ret; -} - -#ifdef HAVE_CRL + 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; + } + } -int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, - long sz, int type) -{ - WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer"); + if (ret == 1) { + key = (DhKey*)pkey->dh->internal; - if (ctx == NULL) - return BAD_FUNC_ARG; + keyIdx = 0; + if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) { + ret = 0; + } + } - return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type); -} + if (ret == 1) { + elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB; + if (priv) { + elements |= ELEMENT_PRV; + } + if (SetDhExternal_ex(pkey->dh, elements) != 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 && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ -int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff, - long sz, int type) +#ifdef HAVE_PQC +#ifdef HAVE_FALCON +static int d2iTryFalconKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, + long memSz, int priv) { - WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer"); + 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 (ssl == NULL || ssl->ctx == NULL) - return BAD_FUNC_ARG; + if (wc_falcon_init(falcon) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON); + #endif + return 0; + } - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type); -} + /* 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)); -#endif /* HAVE_CRL */ + 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); +#ifdef WOLFSSL_SMALL_STACK + XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON); +#endif -#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 (!isFalcon) { + return -1; } - 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)); + if (*out != NULL) { + pkey = *out; } - else - return BAD_FUNC_ARG; -} + 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; + } + } + pkey->type = EVP_PKEY_FALCON; + pkey->pkey.ptr = NULL; + pkey->pkey_sz = 0; + *out = pkey; + return 1; -int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl)); - } - else - return BAD_FUNC_ARG; } +#endif /* HAVE_FALCON */ -int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl) +#ifdef HAVE_DILITHIUM +static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, + long memSz, int priv) { - WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerDisableOCSPStapling(SSL_CM(ssl)); + 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; } - else - return BAD_FUNC_ARG; -} +#endif -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 (wc_dilithium_init(dilithium) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); + #endif + return 0; } - else - return BAD_FUNC_ARG; -} + /* 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); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); +#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); + if (!isDilithium) { + return -1; } - else - 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; -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; + *out = pkey; + return 1; } +#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_PQC */ - -int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx) +static WOLFSSL_EVP_PKEY* d2iGenericKey(WOLFSSL_EVP_PKEY** out, + const unsigned char** in, long inSz, int priv) { - WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP"); - if (ctx) - return wolfSSL_CertManagerDisableOCSP(ctx->cm); - else - return BAD_FUNC_ARG; -} + WOLFSSL_EVP_PKEY* pkey = NULL; + WOLFSSL_ENTER("d2iGenericKey"); -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 (in == NULL || *in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + if ((out != NULL) && (*out != NULL)) { + pkey = *out; + } -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); +#if !defined(NO_RSA) + if (d2iTryRsaKey(&pkey, *in, inSz, priv) >= 0) { + ; + } else - return BAD_FUNC_ARG; -} - -#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); +#endif /* NO_RSA */ +#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) + if (d2iTryEccKey(&pkey, *in, inSz, priv) >= 0) { + ; + } else - return BAD_FUNC_ARG; -} - -int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling"); - if (ctx) - return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm); +#endif /* HAVE_ECC && OPENSSL_EXTRA */ +#if !defined(NO_DSA) + if (d2iTryDsaKey(&pkey, *in, inSz, priv) >= 0) { + ; + } else - return BAD_FUNC_ARG; -} +#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 +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ -int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPMustStaple"); - if (ctx) - return wolfSSL_CertManagerEnableOCSPMustStaple(ctx->cm); +#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_CTX_DisableOCSPMustStaple(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPMustStaple"); - if (ctx) - return wolfSSL_CertManagerDisableOCSPMustStaple(ctx->cm); +#ifdef HAVE_PQC +#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 */ +#endif /* HAVE_PQC */ + { + WOLFSSL_MSG("wolfSSL_d2i_PUBKEY couldn't determine key type"); + } + + if ((pkey != NULL) && (out != NULL)) { + *out = pkey; + } + return pkey; } -#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ +#endif /* OPENSSL_EXTRA || WPA_SMALL */ -#endif /* HAVE_OCSP */ - -/* 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) - -#ifndef NO_FILESYSTEM +#ifdef OPENSSL_EXTRA -/* 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) +WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY( + WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf, + long keyLen) { -#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; - void* heapHint = wolfSSL_CTX_GetHeap(ctx, ssl); -#ifndef NO_CODING - const char* header = NULL; - const char* footer = NULL; -#endif - - (void)crl; - (void)heapHint; - - 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; - } + WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; +#ifdef WOLFSSL_PEM_TO_DER + int ret; + DerBuffer* der = NULL; - if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { - WOLFSSL_MSG("ProcessFile file size error"); - XFCLOSE(file); - return WOLFSSL_BAD_FILE; + if (keyBuf == NULL || *keyBuf == NULL || keyLen <= 0) { + WOLFSSL_MSG("Bad key PEM/DER args"); + 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; + 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); } - dynamic = 1; } - 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 (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_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; -} - -/* 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; - - WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex"); - - if (ctx == NULL || (file == NULL && path == NULL)) { - return WOLFSSL_FAILURE; + if (ret == 0) { + pkcs8 = wolfSSL_EVP_PKEY_new(); + if (pkcs8 == NULL) + ret = MEMORY_E; } - - verify = GET_VERIFY_SETTING_CTX(ctx); - if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) - verify = VERIFY_SKIP_DATE; - - 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 + 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 == 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); - - /* 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; - } - } - else { - ret = WOLFSSL_SUCCESS; - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX); - #endif -#else - ret = NOT_COMPILED_IN; - (void)flags; -#endif + if (ret == 0) { + XMEMCPY(pkcs8->pkey.ptr, der->buffer, der->length); + pkcs8->pkey_sz = der->length; } - return ret; -} + FreeDer(&der); + if (ret != 0) { + wolfSSL_EVP_PKEY_free(pkcs8); + pkcs8 = NULL; + } + if (pkey != NULL) { + *pkey = pkcs8; + } -WOLFSSL_ABI -int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, - const char* path) -{ - int ret = wolfSSL_CTX_load_verify_locations_ex(ctx, file, path, - WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); +#else + (void)bio; + (void)pkey; +#endif /* WOLFSSL_PEM_TO_DER */ - return WS_RETURN_CODE(ret,WOLFSSL_FAILURE); + return pkcs8; } -#ifdef WOLFSSL_SYS_CA_CERTS -#ifdef USE_WINDOWS_API +#ifndef NO_BIO +/* put SSL type in extra for now, not very common */ -static int LoadSystemCaCertsWindows(WOLFSSL_CTX* ctx, byte* loaded) +/* 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 ret = WOLFSSL_SUCCESS; - word32 i; - HANDLE handle = NULL; - PCCERT_CONTEXT certCtx = NULL; - LPCSTR storeNames[2] = {"ROOT", "CA"}; - HCRYPTPROV_LEGACY hProv = (HCRYPTPROV_LEGACY)NULL; + WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; +#ifdef WOLFSSL_PEM_TO_DER + unsigned char* mem = NULL; + int memSz; - if (ctx == NULL || loaded == NULL) { - ret = WOLFSSL_FAILURE; - } + WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio"); - 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 (bio == NULL) { + return NULL; + } - if (handle != NULL && !CertCloseStore(handle, 0)) { - WOLFSSL_MSG_EX("Failed to close cert store %s.", storeNames[i]); - ret = WOLFSSL_FAILURE; - } + if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) { + return NULL; } - return ret; + pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz); +#else + (void)bio; + (void)pkey; +#endif /* WOLFSSL_PEM_TO_DER */ + + return pkcs8; } -#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". +/* expecting DER format public key * - * 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. + * 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. */ -static int LoadSystemCaCertsMac(WOLFSSL_CTX* ctx, byte* loaded) +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out) { - int ret = WOLFSSL_SUCCESS; - word32 i; - const unsigned int trustDomains[] = { - kSecTrustSettingsDomainUser, - kSecTrustSettingsDomainAdmin, - kSecTrustSettingsDomainSystem - }; - CFArrayRef certs; - OSStatus stat; - CFIndex numCerts; - CFDataRef der; - CFIndex j; + unsigned char* mem; + long memSz; + WOLFSSL_EVP_PKEY* pkey = NULL; - if (ctx == NULL || loaded == NULL) { - ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio"); + + if (bio == NULL) { + return NULL; } + (void)out; - 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; - } + memSz = wolfSSL_BIO_get_len(bio); + if (memSz <= 0) { + return NULL; + } - CFRelease(der); - } - } + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + return NULL; + } - 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 = WOLFSSL_FAILURE; - break; + 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; } } - return ret; + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return pkey; } -#endif /* defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) */ -#else +#endif /* !NO_BIO */ -/* 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) +/* 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) { - const char** ret; - - if (num == NULL) { - ret = NULL; - } - else { - ret = systemCaDirs; - *num = sizeof(systemCaDirs)/sizeof(*systemCaDirs); - } - - return ret; + WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY"); + return d2iGenericKey(out, in, inSz, 0); } -static int LoadSystemCaCertsNix(WOLFSSL_CTX* ctx, byte* loaded) { - int ret = WOLFSSL_SUCCESS; - word32 i; - - if (ctx == NULL || loaded == NULL) { - ret = WOLFSSL_FAILURE; - } +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN) && \ + !defined(NO_PWDBASED) - 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]); +/* 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 (!key || !key->pkey_sz) + return WOLFSSL_FATAL_ERROR; + + /* 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 { - WOLFSSL_MSG_EX("Loaded CA certs from %s.", - systemCaDirs[i]); - *loaded = 1; - /* Stop searching after we've loaded one directory. */ - break; + *der = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); + if (*der == NULL) { + return WOLFSSL_FATAL_ERROR; + } + XMEMCPY(*der, pt + pkcs8HeaderSz, sz); } } + return sz; +} - return ret; +int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der) +{ + return wolfSSL_i2d_PublicKey(key, der); } -#endif +#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_ASN && !NO_PWDBASED */ -int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx) +static WOLFSSL_EVP_PKEY* _d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz, int priv) { - 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) */ + int ret = 0; + word32 idx = 0, algId; + word16 pkcs8HeaderSz = 0; + WOLFSSL_EVP_PKEY* local; + int opt = 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 + (void)opt; -#else + if (in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } - ret = LoadSystemCaCertsNix(ctx, &loaded); + 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; -#endif + 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 (ret == WOLFSSL_SUCCESS && !loaded) { - ret = WOLFSSL_BAD_PATH; + (void)idx; /* not used */ + } + else { + if (ret != ASN_PARSE_E) { + WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 " + "header"); + return NULL; + } + } } - WOLFSSL_LEAVE("wolfSSL_CTX_load_system_CA_certs", ret); + if (out != NULL && *out != NULL) { + wolfSSL_EVP_PKEY_free(*out); + *out = NULL; + } + local = wolfSSL_EVP_PKEY_new(); + if (local == NULL) { + return NULL; + } - return ret; -} + 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 { + XMEMCPY(local->pkey.ptr, *in, inSz); + } -#endif /* WOLFSSL_SYS_CA_CERTS */ + 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; + } -#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"); + /* advance pointer with success */ + if (local != NULL) { + if (local->pkey_sz <= (int)inSz) { + *in += local->pkey_sz; + } - if (ctx == NULL || file == NULL) { - return WOLFSSL_FAILURE; + if (out != NULL) { + *out = local; + } } - return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL, - GET_VERIFY_SETTING_CTX(ctx)); + return local; } -int wolfSSL_trust_peer_cert(WOLFSSL* ssl, const char* file, int type) +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz) { - WOLFSSL_ENTER("wolfSSL_trust_peer_cert"); - - if (ssl == NULL || file == NULL) { - return WOLFSSL_FAILURE; - } + WOLFSSL_ENTER("wolfSSL_d2i_PublicKey"); - return ProcessFile(NULL, file, type, TRUSTED_PEER_TYPE, ssl, 0, NULL, - GET_VERIFY_SETTING_SSL(ssl)); + return _d2i_PublicKey(type, out, in, inSz, 0); } -#endif /* WOLFSSL_TRUST_PEER_CERT */ - -#endif /* NO_FILESYSTEM */ - -#ifdef HAVE_CRL - -int wolfSSL_EnableCRL(WOLFSSL* ssl, int options) +/* 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_EnableCRL"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerEnableCRL(SSL_CM(ssl), options); - } - else - return BAD_FUNC_ARG; -} - + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); -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; + return _d2i_PublicKey(type, out, in, inSz, 1); } -#ifndef NO_FILESYSTEM -int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor) +#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_ENTER("wolfSSL_LoadCRL"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor); + WOLFSSL_EVP_PKEY* local; + + if (out != NULL && *out != NULL) { + wolfSSL_EVP_PKEY_free(*out); + *out = NULL; } - else - 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); + local = wolfSSL_EVP_PKEY_new_ex(heap); + if (local == NULL) { + return NULL; } - else - return BAD_FUNC_ARG; -} -#endif + local->type = type; + local->pkey_sz = 0; + local->pkcs8HeaderSz = 0; -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); + 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); + + local->ecc->inSet = 1; + break; + } +#endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Unsupported private key id type"); + wolfSSL_EVP_PKEY_free(local); + return NULL; } - else - return BAD_FUNC_ARG; -} -#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); + if (local != NULL && out != NULL) { + *out = local; } - else - return BAD_FUNC_ARG; -} -#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; + return local; } +#endif /* WOLF_PRIVATE_KEY_ID */ +#ifndef NO_CERTS /* // NOLINT(readability-redundant-preprocessor) */ -int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx) +#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_CTX_DisableCRL"); - if (ctx) - return wolfSSL_CertManagerDisableCRL(ctx->cm); - else - return BAD_FUNC_ARG; + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } +#ifdef WOLFSSL_DUAL_ALG_CERTS + return 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); +#else + return 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); +#endif } +#endif /* !NO_CHECK_PRIVATE_KEY */ +#endif /* !NO_CERTS */ -#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 /* OPENSSL_EXTRA */ -int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* file, - int type) +#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_CTX_LoadCRL"); - if (ctx) - return wolfSSL_CertManagerLoadCRLFile(ctx->cm, file, type); - else - return BAD_FUNC_ARG; + 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; } -#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_CTX_set_client_cert_type(WOLFSSL_CTX* ctx, + 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 (ctx == 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) { + 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; } - return WOLFSSL_FAILURE; -} + if (!isArrayUnique(buf, bufLen)) + return BAD_FUNC_ARG; -#endif /* WOLFSSL_DER_LOAD */ + 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]; + } + ctx->rpkConfig.preferred_ClientCertTypeCnt = bufLen; + return WOLFSSL_SUCCESS; +} -WOLFSSL_ABI -int wolfSSL_CTX_use_certificate_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_CTX_set_server_cert_type(WOLFSSL_CTX* ctx, + const char* buf, int bufLen) { - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file"); + int i; - if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; + if (ctx == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) { + return BAD_FUNC_ARG; } - 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_ServerCertTypeCnt = 1; + ctx->rpkConfig.preferred_ServerCertTypes[0]= WOLFSSL_CERT_TYPE_X509; + ctx->rpkConfig.preferred_ServerCertTypes[1]= WOLFSSL_CERT_TYPE_X509; + return WOLFSSL_SUCCESS; + } + if (!isArrayUnique(buf, bufLen)) + return BAD_FUNC_ARG; -WOLFSSL_ABI -int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file, - int format) -{ - WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_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, PRIVATEKEY_TYPE, NULL, 0, NULL, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; + ctx->rpkConfig.preferred_ServerCertTypes[i] = buf[i]; } + ctx->rpkConfig.preferred_ServerCertTypeCnt = bufLen; - return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; } -#ifdef WOLFSSL_DUAL_ALG_CERTS -int wolfSSL_CTX_use_AltPrivateKey_file(WOLFSSL_CTX* ctx, const char* file, - int format) +/* 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_use_AltPrivateKey_file"); + int i; + + if (ssl == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) { + return BAD_FUNC_ARG; + } - 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_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_DUAL_ALG_CERTS */ -#endif /* NO_FILESYSTEM */ - + if (!isArrayUnique(buf, 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_ClientCertTypes[i] = buf[i]; } + ssl->options.rpkConfig.preferred_ClientCertTypeCnt = bufLen; - ctx->verifyDepth = (byte)depth; + return WOLFSSL_SUCCESS; } - -/* get cert chaining depth using ssl struct */ -long wolfSSL_get_verify_depth(WOLFSSL* ssl) +/* 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) { - if(ssl == NULL) { + int i; + + if (ssl == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) { return BAD_FUNC_ARG; } -#ifndef OPENSSL_EXTRA - return MAX_CHAIN_DEPTH; -#else - return ssl->options.verifyDepth; -#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; + } -/* get cert chaining depth using ctx struct */ -long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx) -{ - if (ctx == NULL) { + if (!isArrayUnique(buf, bufLen)) return BAD_FUNC_ARG; - } -#ifndef OPENSSL_EXTRA - return MAX_CHAIN_DEPTH; -#else - return ctx->verifyDepth; -#endif -} + 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 + ssl->options.rpkConfig.preferred_ServerCertTypes[i] = buf[i]; + } + ssl->options.rpkConfig.preferred_ServerCertTypeCnt = bufLen; + return WOLFSSL_SUCCESS; +} -WOLFSSL_ABI -int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file) +/* 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) { - /* process up to MAX_CHAIN_DEPTH plus subject cert */ - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file"); + int ret = WOLFSSL_SUCCESS; - if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, 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_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; } - -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; - - 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) { 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 /* HAVE_ECC */ -#endif /* NO_FILESYSTEM */ -#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) +typedef struct { + byte verifyPeer:1; + byte verifyNone:1; + byte failNoCert:1; + byte failNoCertxPSK:1; + byte verifyPostHandshake:1; +} SetVerifyOptions; + +static SetVerifyOptions ModeToVerifyOptions(int mode) { -#ifdef WOLFSSL_SMALL_STACK - DecodedCert* der = NULL; -#else - DecodedCert der[1]; + 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 - word32 size; - byte* buff; - int ret = WOLFSSL_FAILURE; + } + } - WOLFSSL_ENTER("check_cert_key"); + return opts; +} - if (cert == NULL || key == NULL) { - return WOLFSSL_FAILURE; - } +WOLFSSL_ABI +void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) +{ + SetVerifyOptions opts; -#ifdef WOLFSSL_SMALL_STACK - der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); - if (der == NULL) - return MEMORY_E; + WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); + if (ctx == NULL) + return; + + opts = ModeToVerifyOptions(mode); + + 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 - 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; - } + ctx->verifyCallback = vc; +} - size = key->length; - buff = key->buffer; -#ifdef WOLF_PRIVATE_KEY_ID - if (devId != INVALID_DEVID) { - int type = 0; - void *pkey = NULL; +#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; - #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 + ctx->verifyCertCb = cb; + ctx->verifyCertCbArg = arg; +} +#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 wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc) +{ + SetVerifyOptions opts; - (void)devId; - (void)isKeyLabel; - (void)isKeyId; + WOLFSSL_ENTER("wolfSSL_set_verify"); + if (ssl == NULL) + return; - return ret; + opts = ModeToVerifyOptions(mode); + + 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 + + ssl->verifyCallback = vc; } -/* 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) +void wolfSSL_set_verify_result(WOLFSSL *ssl, long v) { - if (ctx == NULL) { - return WOLFSSL_FAILURE; - } - return check_cert_key(ctx->certificate, ctx->privateKey, ctx->heap, - ctx->privateKeyDevId, ctx->privateKeyLabel, ctx->privateKeyId); + WOLFSSL_ENTER("wolfSSL_set_verify_result"); + + if (ssl == NULL) + return; + +#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 } -#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) +#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) { - const unsigned char *key; - int type; - - WOLFSSL_ENTER("wolfSSL_CTX_get0_privatekey"); + 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); - if (ctx == NULL || ctx->privateKey == NULL || - ctx->privateKey->buffer == NULL) { - WOLFSSL_MSG("Bad parameter or key not set"); - return NULL; + } + else { + WOLFSSL_ERROR(ret); /* log the error in the error queue */ + } } + return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} - 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; +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 */ - key = ctx->privateKey->buffer; - - if (ctx->privateKeyPKey != NULL) - return ctx->privateKeyPKey; - else - return wolfSSL_d2i_PrivateKey(type, - (WOLFSSL_EVP_PKEY**)&ctx->privateKeyPKey, &key, - (long)ctx->privateKey->length); +/* store user ctx for verify callback */ +void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx) +{ + WOLFSSL_ENTER("wolfSSL_SetCertCbCtx"); + if (ssl) + ssl->verifyCbCtx = ctx; } -#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) +/* 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; +} - WOLFSSL_EVP_PKEY* pkey = NULL; - const unsigned char* mem; - long memSz = inSz; - - WOLFSSL_ENTER("d2iGenericKey"); - if (in == NULL || *in == NULL || inSz < 0) { - WOLFSSL_MSG("Bad argument"); - return NULL; - } - mem = *in; +/* store context CA Cache addition callback */ +void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb) +{ + if (ctx && ctx->cm) + ctx->cm->caCacheCallback = cb; +} - #if !defined(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)); - /* 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 +#if defined(PERSIST_CERT_CACHE) - 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 !defined(NO_FILESYSTEM) - 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; - } +/* Persist cert cache to file */ +int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname) +{ + WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache"); - return pkey; - } - else { - WOLFSSL_MSG("RSA wolfSSL_EVP_PKEY_new error"); - } - } - } - #endif /* NO_RSA */ + if (ctx == NULL || fname == NULL) + return BAD_FUNC_ARG; - #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)); + return CM_SaveCertCache(ctx->cm, fname); +} - 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 - 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; - } +/* Persist cert cache from file */ +int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname) +{ + WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache"); - pkey->ownEcc = 1; - pkey->ecc = wolfSSL_EC_KEY_new(); - if (pkey->ecc == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } + if (ctx == NULL || fname == NULL) + return BAD_FUNC_ARG; - 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 CM_RestoreCertCache(ctx->cm, fname); +} - return pkey; - } - else { - WOLFSSL_MSG("ECC wolfSSL_EVP_PKEY_new error"); - } - } - } - #endif /* HAVE_ECC && OPENSSL_EXTRA */ +#endif /* NO_FILESYSTEM */ - #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)); +/* 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 (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 + if (ctx == NULL || mem == NULL || used == NULL || sz <= 0) + return BAD_FUNC_ARG; - /* 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; - } + return CM_MemSaveCertCache(ctx->cm, mem, sz, used); +} - pkey->ownDsa = 1; - pkey->dsa = wolfSSL_DSA_new(); - if (pkey->dsa == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - 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; - } +/* 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"); - return pkey; - } - else { - WOLFSSL_MSG("DSA wolfSSL_EVP_PKEY_new error"); - } - } - } - #endif /* NO_DSA */ + if (ctx == NULL || mem == NULL || sz <= 0) + return BAD_FUNC_ARG; - #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)); + return CM_MemRestoreCertCache(ctx->cm, mem, sz); +} - 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 - /* 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; - } +/* 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"); - pkey->ownDh = 1; - pkey->dh = wolfSSL_DH_new(); - if (pkey->dh == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } + if (ctx == NULL) + return BAD_FUNC_ARG; - if (wolfSSL_DH_LoadDer(pkey->dh, - (const unsigned char*)pkey->pkey.ptr, - pkey->pkey_sz) != WOLFSSL_SUCCESS) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } + return CM_GetCertCacheMemSize(ctx->cm); +} - 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) */ +#endif /* PERSIST_CERT_CACHE */ +#endif /* !NO_CERTS */ - #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)); - /* test if DH-public key */ - if (wc_InitDhKey(dh) != 0) - return NULL; +void wolfSSL_load_error_strings(void) +{ + /* compatibility only */ +} - 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) { - 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; - } +int wolfSSL_library_init(void) +{ + WOLFSSL_ENTER("wolfSSL_library_init"); + if (wolfSSL_Init() == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FATAL_ERROR; +} - 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; - } - } - } + +#ifdef HAVE_SECRET_CALLBACK + +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; + + 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; } - #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 + return WOLFSSL_SUCCESS; +} - 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); - } +int wolfSSL_set_secret_cb(WOLFSSL* ssl, TlsSecretCb cb, void* ctx) +{ + WOLFSSL_ENTER("wolfSSL_set_secret_cb"); + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; - #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; - } + ssl->tlsSecretCb = cb; + ssl->tlsSecretCtx = ctx; - } - #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 + return WOLFSSL_SUCCESS; +} - 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); - } +#ifdef SHOW_SECRETS +int tlsShowSecrets(WOLFSSL* ssl, void* secret, int secretSz, + void* ctx) +{ + /* 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; - #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; - } + (void)ctx; + + clientRandomSz = (int)wolfSSL_get_client_random(ssl, clientRandom, + sizeof(clientRandom)); + if (clientRandomSz <= 0) { + printf("Error getting server random %d\n", clientRandomSz); + return BAD_FUNC_ARG; } - #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ - if (pkey == NULL) { - WOLFSSL_MSG("wolfSSL_d2i_PUBKEY couldn't determine key type"); + 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; - return 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); + } + } + #endif + return 0; } -#endif /* OPENSSL_EXTRA || WPA_SMALL */ +#endif /* SHOW_SECRETS */ + +#endif + #ifdef OPENSSL_EXTRA -WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY( - WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf, long keyLen) +/* + * 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) { - WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; -#ifdef WOLFSSL_PEM_TO_DER int ret; - DerBuffer* der = NULL; + int findTLSv13Suites = 0; + int findbeforeSuites = 0; + byte cipherSuite0; + byte cipherSuite1; + int flags; + char* next = (char*)list; - if (keyBuf == NULL || *keyBuf == NULL || keyLen <= 0) { - WOLFSSL_MSG("Bad key PEM/DER args"); - return NULL; - } + do { + char* current = next; + char name[MAX_SUITE_NAME + 1]; + word32 length = MAX_SUITE_NAME; + word32 current_length; - 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 */ - } - } + next = XSTRSTR(next, ":"); - 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; - } + current_length = (!next) ? (word32)XSTRLEN(current) + : (word32)(next - current); - FreeDer(&der); - if (ret != 0) { - wolfSSL_EVP_PKEY_free(pkcs8); - pkcs8 = NULL; - } - if (pkey != NULL) { - *pkey = pkcs8; - } + if (current_length < length) { + length = current_length; + } + XMEMCPY(name, current, length); + name[length] = 0; -#else - (void)bio; - (void)pkey; -#endif /* WOLFSSL_PEM_TO_DER */ + if (XSTRCMP(name, "ALL") == 0 || XSTRCMP(name, "DEFAULT") == 0 || + XSTRCMP(name, "HIGH") == 0) { + findTLSv13Suites = 1; + findbeforeSuites = 1; + break; + } - return pkcs8; -} + 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; + } + } + #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; -#ifndef NO_BIO -/* put SSL type in extra for now, not very common */ + do { + subStrNext = XSTRSTR(subStr, "+"); -/* 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_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; -#ifdef WOLFSSL_PEM_TO_DER - unsigned char* mem = NULL; - int memSz; + if ((XSTRCMP(subStr, "ECDHE") == 0) || + (XSTRCMP(subStr, "RSA") == 0)) { + return 0; + } - WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio"); + if (subStrNext && (XSTRLEN(subStrNext) > 0)) { + subStr = subStrNext + 1; /* +1 to skip past '+' */ + } + } while (subStrNext != NULL); + } + #endif - if (bio == NULL) { - return NULL; + if (findTLSv13Suites == 1 && findbeforeSuites == 1) { + /* list has mixed suites */ + return 0; + } } + while (next++); /* ++ needed to skip ':' */ - if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) { - return NULL; + if (findTLSv13Suites == 0 && findbeforeSuites == 1) { + ret = 1;/* only before TLSv13 suites */ } - - pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz); -#else - (void)bio; - (void)pkey; -#endif /* WOLFSSL_PEM_TO_DER */ - - return pkcs8; + else if (findTLSv13Suites == 1 && findbeforeSuites == 0) { + ret = 2;/* only TLSv13 suties */ + } + else { + ret = 0;/* handle as mixed */ + } + return ret; } - -/* 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 +/* parse some bulk lists like !eNULL / !aNULL * - * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case. + * returns WOLFSSL_SUCCESS on success and sets the cipher suite list */ -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY** out) +static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + Suites* suites, const char* list) { - unsigned char* mem; - long memSz; - WOLFSSL_EVP_PKEY* pkey = NULL; - - WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio"); + 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; - if (bio == NULL) { - return NULL; + if (suites == NULL || list == NULL) { + WOLFSSL_MSG("NULL argument"); + return WOLFSSL_FAILURE; } - (void)out; - memSz = wolfSSL_BIO_get_len(bio); - if (memSz <= 0) { - return NULL; - } + listattribute = CheckcipherList(list); - mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (mem == NULL) { - return 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; } - - 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; + 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; } } - XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - return pkey; -} - -#endif /* !NO_BIO */ - - -/* 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); -} + /* 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; + } -#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN) && \ - !defined(NO_PWDBASED) + XMEMSET(suitesCpy, 0, suites->suiteSz); + } +#else + XMEMSET(suitesCpy, 0, sizeof(suitesCpy)); +#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 (suites->suiteSz > 0) + XMEMCPY(suitesCpy, suites->suites, suites->suiteSz); + suitesCpySz = suites->suiteSz; - if (!key || !key->pkey_sz) - return WOLFSSL_FATAL_ERROR; + 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; + } - /* 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; + 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; + } } - else { - *der = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); - if (*der == NULL) { - return WOLFSSL_FATAL_ERROR; + 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; + } } - 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); +#ifdef WOLFSSL_SMALL_STACK + XFREE(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } -#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_ASN && !NO_PWDBASED */ +#endif -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; +int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list"); - if (in == NULL || inSz < 0) { - WOLFSSL_MSG("Bad argument"); - return NULL; - } + if (ctx == NULL) + return WOLFSSL_FAILURE; - 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 (AllocateCtxSuites(ctx) != 0) + return WOLFSSL_FAILURE; - 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; - } +#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 +} - (void)idx; /* not used */ - } - else { - if (ret != ASN_PARSE_E) { - WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 " - "header"); - return NULL; - } - } - } +#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 (out != NULL && *out != NULL) { - wolfSSL_EVP_PKEY_free(*out); - *out = NULL; - } - local = wolfSSL_EVP_PKEY_new(); - if (local == NULL) { - return NULL; - } + if (ctx == NULL) + return WOLFSSL_FAILURE; - 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 { - XMEMCPY(local->pkey.ptr, *in, inSz); - } + if (AllocateCtxSuites(ctx) != 0) + return 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; - } + return (SetCipherListFromBytes(ctx, ctx->suites, list, listSz)) ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} +#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */ - /* advance pointer with success */ - if (local != NULL) { - if (local->pkey_sz <= (int)inSz) { - *in += local->pkey_sz; - } +int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) +{ + WOLFSSL_ENTER("wolfSSL_set_cipher_list"); - if (out != NULL) { - *out = local; - } + if (ssl == NULL || ssl->ctx == NULL) { + return WOLFSSL_FAILURE; } - return local; + 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 } -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out, - const unsigned char **in, long inSz) +#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_d2i_PublicKey"); + WOLFSSL_ENTER("wolfSSL_set_cipher_list_bytes"); - 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"); + if (ssl == NULL || ssl->ctx == NULL) { + return WOLFSSL_FAILURE; + } - return _d2i_PublicKey(type, out, in, inSz, 1); + 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 */ -#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) + +#ifdef HAVE_KEYING_MATERIAL + +#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" + +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}, +}; + +/** + * 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) { - WOLFSSL_EVP_PKEY* local; + byte* seed = NULL; + word32 seedLen; + const struct ForbiddenLabels* fl; - if (out != NULL && *out != NULL) { - wolfSSL_EVP_PKEY_free(*out); - *out = NULL; + WOLFSSL_ENTER("wolfSSL_export_keying_material"); + + if (ssl == NULL || out == NULL || label == NULL || + (use_context && contextLen && context == NULL)) { + WOLFSSL_MSG("Bad argument"); + return WOLFSSL_FAILURE; } - local = wolfSSL_EVP_PKEY_new_ex(heap); - if (local == NULL) { - return NULL; + /* clientRandom + serverRandom + * OR + * clientRandom + serverRandom + ctx len encoding + ctx */ + seedLen = !use_context ? (word32)SEED_LEN : + (word32)SEED_LEN + 2 + (word32)contextLen; + + 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; } - local->type = type; - local->pkey_sz = 0; - local->pkcs8HeaderSz = 0; + /* 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; + } + } - 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; +#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 */ } -#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); - local->ecc->inSet = 1; - break; + if (Tls13_Exporter(ssl, out, (word32)outLen, label, labelLen, + context, contextLen) != 0) { + WOLFSSL_MSG("Tls13_Exporter error"); + return WOLFSSL_FAILURE; } -#endif /* HAVE_ECC */ - default: - WOLFSSL_MSG("Unsupported private key id type"); - wolfSSL_EVP_PKEY_free(local); - return NULL; + return WOLFSSL_SUCCESS; } +#endif - if (local != NULL && out != NULL) { - *out = local; + /* Path for <=TLS 1.2 */ + seed = (byte*)XMALLOC(seedLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (seed == NULL) { + WOLFSSL_MSG("malloc error"); + return WOLFSSL_FAILURE; } - return local; -} -#endif /* WOLF_PRIVATE_KEY_ID */ + XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); -#ifndef NO_CERTS /* // NOLINT(readability-redundant-preprocessor) */ + 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); + } + } -#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) -{ - if (ssl == NULL) { + 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; } - 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 */ + PRIVATE_KEY_LOCK(); -#endif /* !NO_CERTS */ + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_KEYING_MATERIAL */ -int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) +int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_use_PrivateKey"); - if (ssl == NULL || pkey == NULL ) { + int useNb = 0; + + if (ssl == NULL) return WOLFSSL_FAILURE; - } - return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr, - pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1); + 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; } -int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der, - long derSz) +#ifndef WOLFSSL_LEANPSK + +void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock) { - WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1"); - if (ssl == NULL || der == NULL ) { - return WOLFSSL_FAILURE; - } + (void)nonblock; - (void)pri; /* type of private key */ - return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); -} -/****************************************************************************** -* wolfSSL_CTX_use_PrivateKey_ASN1 - loads a private key buffer into the SSL ctx -* -* RETURNS: -* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE -*/ + WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock"); -int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx, - unsigned char* der, long derSz) -{ - WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_ASN1"); - if (ctx == NULL || der == NULL ) { - return WOLFSSL_FAILURE; - } + if (ssl == NULL) + return; - (void)pri; /* type of private key */ - return wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1); + 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."); + } } -#ifndef NO_RSA -int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz) +#ifdef WOLFSSL_DTLS + +int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1"); - if (ssl == NULL || der == NULL ) { - return WOLFSSL_FAILURE; - } + int timeout = 0; + if (ssl) + timeout = ssl->dtls_timeout; - return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); + WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout", timeout); + return timeout; } -#endif -int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509) -{ - long idx = 0; +#ifdef WOLFSSL_DTLS13 - 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; - } - } - - (void)idx; - return WOLFSSL_FAILURE; -} - -#endif /* OPENSSL_EXTRA */ - -#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. +/* + * 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(). */ -static int isArrayUnique(const char* buf, size_t len) +int wolfSSL_dtls13_use_quick_timeout(WOLFSSL* ssl) { - 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; + return ssl->dtls13FastTimeout; } -/* 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. +/* + * 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_CTX_set_client_cert_type(WOLFSSL_CTX* ctx, - const char* buf, int bufLen) +void wolfSSL_dtls13_set_send_more_acks(WOLFSSL* ssl, int value) { - int i; + if (ssl != NULL) + ssl->options.dtls13SendMoreAcks = !!value; +} +#endif /* WOLFSSL_DTLS13 */ - if (ctx == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) { - return BAD_FUNC_ARG; +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; } + return 0; +} - /* 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; - } +#ifndef NO_WOLFSSL_STUB +int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl) +{ + WOLFSSL_STUB("SSL_DTLSv1_handle_timeout"); + (void)ssl; + return 0; +} +#endif - if (!isArrayUnique(buf, bufLen)) - return BAD_FUNC_ARG; +#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 - for (i = 0; i < bufLen; i++){ - if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) - return BAD_FUNC_ARG; +/* 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; - ctx->rpkConfig.preferred_ClientCertTypes[i] = buf[i]; + if (timeout > ssl->dtls_timeout_max) { + WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout " + "max"); + return BAD_FUNC_ARG; } - ctx->rpkConfig.preferred_ClientCertTypeCnt = bufLen; + + ssl->dtls_timeout_init = timeout; + ssl->dtls_timeout = timeout; 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; - if (ctx == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) { +/* 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; - } - - /* 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; - } - if (!isArrayUnique(buf, bufLen)) + if (timeout < ssl->dtls_timeout_init) { + WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init"); 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; - - ctx->rpkConfig.preferred_ServerCertTypes[i] = buf[i]; } - ctx->rpkConfig.preferred_ServerCertTypeCnt = bufLen; + + ssl->dtls_timeout_max = timeout; return WOLFSSL_SUCCESS; } -/* 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_got_timeout(WOLFSSL* ssl) { - int i; + int result = WOLFSSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_dtls_got_timeout"); - if (ssl == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) { - 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 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; } +#endif /* WOLFSSL_DTLS13 */ - 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; - - ssl->options.rpkConfig.preferred_ClientCertTypes[i] = buf[i]; + 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; + } } - ssl->options.rpkConfig.preferred_ClientCertTypeCnt = bufLen; - return WOLFSSL_SUCCESS; + WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout", result); + return result; } -/* 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) + +/* retransmit all the saves messages, WOLFSSL_SUCCESS on ok */ +int wolfSSL_dtls_retransmit(WOLFSSL* ssl) { - int i; + WOLFSSL_ENTER("wolfSSL_dtls_retransmit"); - if (ssl == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) { - return BAD_FUNC_ARG; - } + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; - /* 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; + if (!ssl->options.handShakeDone) { + int result = DtlsMsgPoolSend(ssl, 0); + if (result < 0) { + ssl->error = result; + WOLFSSL_ERROR(result); + return WOLFSSL_FATAL_ERROR; + } } - if (!isArrayUnique(buf, bufLen)) - return BAD_FUNC_ARG; + return 0; +} - for (i = 0; i < bufLen; i++){ - if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) - return BAD_FUNC_ARG; +#endif /* DTLS */ +#endif /* LEANPSK */ - ssl->options.rpkConfig.preferred_ServerCertTypes[i] = buf[i]; - } - ssl->options.rpkConfig.preferred_ServerCertTypeCnt = bufLen; - return WOLFSSL_SUCCESS; -} +#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) -/* 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) +/* 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 = WOLFSSL_SUCCESS; + int ret = 0; - if (ssl == NULL || tp == NULL) + WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret"); + + if (ssl == NULL) { + WOLFSSL_MSG("need a SSL object"); 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; -} - -/* 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) -{ - int ret = WOLFSSL_SUCCESS; - - if (ssl == NULL || tp == NULL) + if (secret != NULL && secretSz == 0) { + WOLFSSL_MSG("can't have a new secret without a size"); 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; -} -#endif /* HAVE_RPK */ + /* If secretSz is 0, use the default size. */ + if (secretSz == 0) + secretSz = COOKIE_SECRET_SZ; -int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der, - int derSz) -{ - long idx = 0; + if (secretSz != ssl->buffers.dtlsCookieSecret.length) { + byte* newSecret; - 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->buffers.dtlsCookieSecret.buffer != NULL) { + ForceZero(ssl->buffers.dtlsCookieSecret.buffer, + ssl->buffers.dtlsCookieSecret.length); + XFREE(ssl->buffers.dtlsCookieSecret.buffer, + ssl->heap, DYNAMIC_TYPE_COOKIE_PWD); } - } - - (void)idx; - return WOLFSSL_FAILURE; -} - -#ifndef NO_FILESYSTEM - -WOLFSSL_ABI -int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format) -{ - WOLFSSL_ENTER("wolfSSL_use_certificate_file"); - if (ssl == NULL) { - return BAD_FUNC_ARG; + 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 } - if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, - ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; + /* 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_FAILURE; + WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0); + return ret; } +#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ -WOLFSSL_ABI -int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format) -{ - WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file"); - if (ssl == NULL) { - return BAD_FUNC_ARG; +/* 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 (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, - ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; + return m; } - return WOLFSSL_FAILURE; -} + #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; + } + return m; + } + #endif + #endif +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ -WOLFSSL_ABI -int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file) -{ - /* process up to MAX_CHAIN_DEPTH plus subject cert */ - WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file"); +/* client only parts */ +#ifndef NO_WOLFSSL_CLIENT - if (ssl == NULL) { - return BAD_FUNC_ARG; + #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS) + WOLFSSL_METHOD* wolfSSLv2_client_method(void) + { + WOLFSSL_STUB("wolfSSLv2_client_method"); + return NULL; } + #endif - if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, - ssl, 1, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; + #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 */ - return WOLFSSL_FAILURE; -} - -int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file, - int format) -{ - /* process up to MAX_CHAIN_DEPTH plus subject cert */ - WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format"); - if (ssl == NULL) { - return BAD_FUNC_ARG; + WOLFSSL_METHOD* wolfSSLv23_client_method(void) + { + return wolfSSLv23_client_method_ex(NULL); } - - if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1, - NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; + 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 WOLFSSL_FAILURE; -} - -#endif /* !NO_FILESYSTEM */ -#ifdef HAVE_ECC + /* 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; -/* 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) -{ - if (ctx == NULL) - return BAD_FUNC_ARG; + (void)ret; - /* 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; + #ifdef HAVE_ERRNO_H + errno = 0; + #endif - if (ctx->privateKeySz == 0) { - WOLFSSL_MSG("Must set private key/cert first"); + 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 */ } - 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; -} + #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 */ + #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 -/* 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; + WOLFSSL_MSG("TLS 1.2 or lower"); + WOLFSSL_ENTER("wolfSSL_connect"); - /* 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; + /* 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; + } - ssl->eccTempKeySz = sz; +#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 */ - return WOLFSSL_SUCCESS; -} + if (ssl->options.side != WOLFSSL_CLIENT_END) { + ssl->error = SIDE_ERROR; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } -#endif /* HAVE_ECC */ + #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 + /* 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)); -#ifdef OPENSSL_EXTRA +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) + advanceState = advanceState && !ssl->dtls13SendingAckOrRtx; +#endif /* WOLFSSL_DTLS13 */ -#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 (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 */ + } - return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format); -} + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + switch (ssl->options.connectState) { -int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format) -{ - WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file"); + 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; - return wolfSSL_use_PrivateKey_file(ssl, file, format); -} -#endif /* NO_FILESYSTEM */ + 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."); +#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 */ + } -/* 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; + ssl->options.connectState = HELLO_AGAIN; + WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; - ses = ClientSessionToSession(ses); + case HELLO_AGAIN : - if (outSz == 0) { - return SECRET_LEN; - } + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif - if (ses == NULL || out == NULL || outSz < 0) { - 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; + } + } + } + #endif - if (outSz > SECRET_LEN) { - size = SECRET_LEN; - } - else { - size = outSz; - } + ssl->options.connectState = HELLO_AGAIN_REPLY; + WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; - XMEMCPY(out, ses->masterSecret, size); - return size; -} + case HELLO_AGAIN_REPLY : + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + neededState = ssl->options.resuming ? + SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE; + /* 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 -int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses) -{ - (void)ses; - return SECRET_LEN; -} + ssl->options.connectState = FIRST_REPLY_DONE; + WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; -#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 */ - -typedef struct { - byte verifyPeer:1; - byte verifyNone:1; - byte failNoCert:1; - byte failNoCertxPSK:1; - byte verifyPostHandshake:1; -} SetVerifyOptions; + 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"); + } -static SetVerifyOptions ModeToVerifyOptions(int mode) -{ - SetVerifyOptions opts; - XMEMSET(&opts, 0, sizeof(SetVerifyOptions)); + #endif + ssl->options.connectState = FIRST_REPLY_FIRST; + WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; - 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; + 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 - } - } - - return opts; -} + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: client key exchange"); + } -WOLFSSL_ABI -void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) -{ - SetVerifyOptions opts; + ssl->options.connectState = FIRST_REPLY_SECOND; + WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; - WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); - if (ctx == NULL) - return; + #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; + } - opts = ModeToVerifyOptions(mode); + #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; - 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 + 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; - ctx->verifyCallback = vc; -} + 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; -#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; +#ifdef WOLFSSL_DTLS13 + case WAIT_FINISHED_ACK: + ssl->options.connectState = FINISHED_DONE; + FALL_THROUGH; +#endif /* WOLFSSL_DTLS13 */ - ctx->verifyCertCb = cb; - ctx->verifyCertCbArg = arg; -} -#endif + 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; -void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc) -{ - SetVerifyOptions opts; + 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_set_verify"); - if (ssl == NULL) - return; + if (!ssl->options.dtls) { + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + } + #ifdef WOLFSSL_DTLS + else { + ssl->options.dtlsHsRetain = 1; + } + #endif /* WOLFSSL_DTLS */ - opts = ModeToVerifyOptions(mode); + #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 - 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 + ssl->error = 0; /* clear the error */ - ssl->verifyCallback = vc; -} + WOLFSSL_LEAVE("wolfSSL_connect", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */ -void wolfSSL_set_verify_result(WOLFSSL *ssl, long v) -{ - WOLFSSL_ENTER("wolfSSL_set_verify_result"); + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return WOLFSSL_FATAL_ERROR; /* unknown connect state */ + } + #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS || !WOLFSSL_TLS13 */ + } - if (ssl == NULL) - return; +#endif /* NO_WOLFSSL_CLIENT */ -#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 -} -#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); +/* server only parts */ +#ifndef NO_WOLFSSL_SERVER - } - else { - WOLFSSL_ERROR(ret); /* log the error in the error queue */ - } + #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS) + WOLFSSL_METHOD* wolfSSLv2_server_method(void) + { + WOLFSSL_STUB("wolfSSLv2_server_method"); + return 0; } - return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; -} + #endif -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); + #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + WOLFSSL_METHOD* wolfSSLv3_server_method(void) + { + return wolfSSLv3_server_method_ex(NULL); } - 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); + 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; } - return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; -} -#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_TLS13 && WOLFSSL_POST_HANDSHAKE_AUTH */ - -/* store user ctx for verify callback */ -void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx) -{ - WOLFSSL_ENTER("wolfSSL_SetCertCbCtx"); - if (ssl) - ssl->verifyCbCtx = ctx; -} - - -/* 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; -} - + #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */ -/* store context CA Cache addition callback */ -void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb) -{ - if (ctx && ctx->cm) - ctx->cm->caCacheCallback = cb; -} + WOLFSSL_METHOD* wolfSSLv23_server_method(void) + { + return wolfSSLv23_server_method_ex(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 defined(PERSIST_CERT_CACHE) -#if !defined(NO_FILESYSTEM) + 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; -/* Persist cert cache to file */ -int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname) -{ - WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache"); + (void)ret; - if (ctx == NULL || fname == NULL) - return BAD_FUNC_ARG; + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; - return CM_SaveCertCache(ctx->cm, fname); -} + #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 */ +#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"); -/* Persist cert cache from file */ -int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname) -{ - WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache"); + /* 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 (ctx == NULL || fname == NULL) - return BAD_FUNC_ARG; +#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 */ - return CM_RestoreCertCache(ctx->cm, fname); -} + #ifdef HAVE_ERRNO_H + errno = 0; + #endif -#endif /* NO_FILESYSTEM */ + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + (void)havePSK; -/* 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"); + #ifdef HAVE_ANON + haveAnon = ssl->options.useAnon; + #endif + (void)haveAnon; - if (ctx == NULL || mem == NULL || used == NULL || sz <= 0) - return BAD_FUNC_ARG; + #ifdef WOLFSSL_MULTICAST + haveMcast = ssl->options.haveMcast; + #endif + (void)haveMcast; - return CM_MemSaveCertCache(ctx->cm, mem, sz, used); -} + if (ssl->options.side != WOLFSSL_SERVER_END) { + ssl->error = SIDE_ERROR; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + #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) { -/* 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"); + WOLFSSL_MSG("accept error: server cert required"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } - if (ctx == NULL || mem == NULL || sz <= 0) - return BAD_FUNC_ARG; + 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 - return CM_MemRestoreCertCache(ctx->cm, mem, sz); -} + #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 - -/* 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"); - - if (ctx == NULL) - return BAD_FUNC_ARG; - - return CM_GetCertCacheMemSize(ctx->cm); -} - -#endif /* PERSIST_CERT_CACHE */ -#endif /* !NO_CERTS */ - - -#ifndef NO_SESSION_CACHE - -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; + 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 + } } - 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; + else { + WOLFSSL_MSG("accept state: " + "Not advanced, more fragments to send"); } } -#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; + 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 */ } - } - return sess; -} - -/* - * 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"); + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } - if (ssl == NULL || id == NULL || len <= 0) - return BAD_FUNC_ARG; + switch (ssl->options.acceptState) { - 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; + case ACCEPT_BEGIN : +#ifdef HAVE_SECURE_RENEGOTIATION + case ACCEPT_BEGIN_RENEG: #endif - id = idHash; - len = SERVER_ID_LEN; - } + /* 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; - 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; + case ACCEPT_CLIENT_HELLO_DONE : + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); } - } - } - - 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: + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; - 1) cache_header_t - 2) SessionCache - 3) ClientCache + 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; - update WOLFSSL_CACHE_VERSION if change layout for the following - PERSISTENT_SESSION_CACHE functions -*/ + 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; -/* 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; -} + 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; -/* 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)); + 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; - WOLFSSL_ENTER("wolfSSL_memsave_session_cache"); + 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; - if (sz < wolfSSL_get_session_cache_memsize()) { - WOLFSSL_MSG("Memory buffer too small"); - return BUFFER_E; - } + 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; - 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); + 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 - return WOLFSSL_SUCCESS; -} +#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; + case TICKET_SENT: + /* SERVER: Fail-safe for CLient Authentication. */ + if (!ssl->options.peerAuthGood) { + WOLFSSL_MSG("Client authentication did not happen"); + return WOLFSSL_FATAL_ERROR; + } -/* 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)); + 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; - WOLFSSL_ENTER("wolfSSL_memrestore_session_cache"); + 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; + } - if (sz < wolfSSL_get_session_cache_memsize()) { - WOLFSSL_MSG("Memory buffer too small"); - return BUFFER_E; - } + ssl->options.acceptState = ACCEPT_FINISHED_DONE; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; - 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)) { + 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; - WOLFSSL_MSG("Session cache header match failed"); - return CACHE_MATCH_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 */ -#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 + if (!ssl->options.dtls) { + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + } +#ifdef WOLFSSL_DTLS + else { + ssl->options.dtlsHsRetain = 1; + } +#endif /* WOLFSSL_DTLS */ - 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]); +#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 -#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); +#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_memrestore_session_cache", WOLFSSL_SUCCESS); + WOLFSSL_LEAVE("wolfSSL_accept", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; - return WOLFSSL_SUCCESS; -} + default : + WOLFSSL_MSG("Unknown accept state ERROR"); + return WOLFSSL_FATAL_ERROR; + } +#endif /* !WOLFSSL_NO_TLS12 */ + } -#if !defined(NO_FILESYSTEM) +#endif /* NO_WOLFSSL_SERVER */ -/* Persist session cache to file */ -/* doesn't use memsave because of additional memory use */ -int wolfSSL_save_session_cache(const char *fname) +#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) +int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx) { - XFILE file; - int ret; - int rc = WOLFSSL_SUCCESS; - int i; - cache_header_t cache_header; - - WOLFSSL_ENTER("wolfSSL_save_session_cache"); + WOLFSSL_ENTER("wolfDTLS_SetChGoodCb"); - 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); + if (ssl == NULL) + return BAD_FUNC_ARG; - /* 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; - } + ssl->chGoodCb = cb; + ssl->chGoodCtx = user_ctx; -#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; - } + return WOLFSSL_SUCCESS; +} #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_HANDSHAKE_DONE_CB -#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 */ +int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx) +{ + WOLFSSL_ENTER("wolfSSL_SetHsDoneCb"); + + if (ssl == NULL) + return BAD_FUNC_ARG; - XFCLOSE(file); - WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc); + ssl->hsDoneCb = cb; + ssl->hsDoneCtx = user_ctx; - return rc; + return WOLFSSL_SUCCESS; } +#endif /* NO_HANDSHAKE_DONE_CB */ -/* Restore the persistent session cache from file */ -/* doesn't use memstore because of additional memory use */ -int wolfSSL_restore_session_cache(const char *fname) +WOLFSSL_ABI +int wolfSSL_Cleanup(void) { - 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)) { + 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_MSG("Session cache header match failed"); - XFCLOSE(file); - return CACHE_MATCH_ERROR; - } + WOLFSSL_ENTER("wolfSSL_Cleanup"); -#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; - } +#ifndef WOLFSSL_MUTEX_INITIALIZER + if (inits_count_mutex_valid == 1) { #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); + if (wc_LockMutex(&inits_count_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex count"); 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 WOLFSSL_MUTEX_INITIALIZER } -#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; + if (initRefCount > 0) { + --initRefCount; + if (initRefCount == 0) + release = 1; } - wc_UnLockMutex(&clisession_mutex); -#endif /* !NO_CLIENT_CACHE */ - - XFCLOSE(file); - WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc); - return rc; -} +#ifndef WOLFSSL_MUTEX_INITIALIZER + if (inits_count_mutex_valid == 1) { +#endif + wc_UnLockMutex(&inits_count_mutex); +#ifndef WOLFSSL_MUTEX_INITIALIZER + } +#endif -#endif /* !NO_FILESYSTEM */ -#endif /* PERSIST_SESSION_CACHE && !SESSION_CACHE_DYNAMIC_MEM */ -#endif /* NO_SESSION_CACHE */ + if (!release) + return ret; +#ifdef OPENSSL_EXTRA + wolfSSL_BN_free_one(); +#endif -void wolfSSL_load_error_strings(void) -{ - /* compatibility only */ -} - +#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 */ -int wolfSSL_library_init(void) -{ - WOLFSSL_ENTER("wolfSSL_library_init"); - if (wolfSSL_Init() == WOLFSSL_SUCCESS) - return WOLFSSL_SUCCESS; - else - return WOLFSSL_FATAL_ERROR; -} +#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 -#ifdef HAVE_SECRET_CALLBACK + if (wolfCrypt_Cleanup() != 0) { + WOLFSSL_MSG("Error with wolfCrypt_Cleanup call"); + if (ret == WOLFSSL_SUCCESS) + ret = WC_CLEANUP_E; + } -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; +#if FIPS_VERSION_GE(5,1) + if (wolfCrypt_SetPrivateKeyReadEnable_fips(0, WC_KEYTYPE_ALL) < 0) { + if (ret == WOLFSSL_SUCCESS) + ret = WC_CLEANUP_E; + } +#endif - 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; +#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 */ - return WOLFSSL_SUCCESS; -} + #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 -#ifndef NO_SESSION_CACHE + return ret; +} -/* on by default if built in but allow user to turn off */ + +/* call before SSL_connect, if verifying will add name check to + date check and signature check */ WOLFSSL_ABI -long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode) +int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn) { - WOLFSSL_ENTER("wolfSSL_CTX_set_session_cache_mode"); + WOLFSSL_ENTER("wolfSSL_check_domain_name"); - if (ctx == NULL) + if (ssl == NULL || dn == NULL) { + WOLFSSL_MSG("Bad function argument: 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; + if (ssl->buffers.domainName.buffer) + XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); -#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->buffers.domainName.length = (word32)XSTRLEN(dn); + ssl->buffers.domainName.buffer = (byte*)XMALLOC( + ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN); - return WOLFSSL_SUCCESS; + 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; + } } -#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) + +/* turn on wolfSSL zlib compression + returns WOLFSSL_SUCCESS for success, else error (not built in) +*/ +int wolfSSL_set_compression(WOLFSSL* ssl) { - long m = 0; + WOLFSSL_ENTER("wolfSSL_set_compression"); + (void)ssl; +#ifdef HAVE_LIBZ + ssl->options.usingCompression = 1; + return WOLFSSL_SUCCESS; +#else + return NOT_COMPILED_IN; +#endif +} - WOLFSSL_ENTER("wolfSSL_CTX_get_session_cache_mode"); - if (ctx == NULL) { - return m; - } +#ifndef USE_WINDOWS_API + #ifndef NO_WRITEV - if (ctx->sessionCacheOff != 1) { - m |= WOLFSSL_SESS_CACHE_SERVER; - } + /* 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; - if (ctx->sessionCacheFlushOff == 1) { - m |= WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR; - } + WOLFSSL_ENTER("wolfSSL_writev"); -#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 + for (i = 0; i < iovcnt; i++) + sending += (int)iov[i].iov_len; - return m; -} -#endif /* OPENSSL_EXTRA */ + if (sending > (int)sizeof(staticBuffer)) { + myBuffer = (byte*)XMALLOC(sending, ssl->heap, + DYNAMIC_TYPE_WRITEV); + if (!myBuffer) + return MEMORY_ERROR; -#endif /* NO_SESSION_CACHE */ + dynamic = 1; + } -#ifdef OPENSSL_EXTRA + for (i = 0; i < iovcnt; i++) { + XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len); + idx += (int)iov[i].iov_len; + } -/* - * 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; + /* 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 - do { - char* current = next; - char name[MAX_SUITE_NAME + 1]; - word32 length = MAX_SUITE_NAME; - word32 current_length; + if (dynamic) + XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV); - next = XSTRSTR(next, ":"); + return ret; + } + #endif +#endif - current_length = (!next) ? (word32)XSTRLEN(current) - : (word32)(next - current); - if (current_length < length) { - length = current_length; - } - XMEMCPY(name, current, length); - name[length] = 0; +#ifdef WOLFSSL_CALLBACKS - if (XSTRCMP(name, "ALL") == 0 || XSTRCMP(name, "DEFAULT") == 0 || - XSTRCMP(name, "HIGH") == 0) { - findTLSv13Suites = 1; - findbeforeSuites = 1; - break; - } + typedef struct itimerval Itimerval; - 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; - } - } + /* don't keep calling simple functions while setting up timer and signals + if no inlining these are the next best */ - #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; + #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) - do { - subStrNext = XSTRSTR(subStr, "+"); - if ((XSTRCMP(subStr, "ECDHE") == 0) || - (XSTRCMP(subStr, "RSA") == 0)) { - return 0; - } + #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) - if (subStrNext && (XSTRLEN(subStrNext) > 0)) { - subStr = subStrNext + 1; /* +1 to skip past '+' */ - } - } while (subStrNext != NULL); - } - #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 (findTLSv13Suites == 1 && findbeforeSuites == 1) { - /* list has mixed suites */ - return 0; - } - } - while (next++); /* ++ needed to skip ':' */ - if (findTLSv13Suites == 0 && findbeforeSuites == 1) { - ret = 1;/* only before TLSv13 suites */ - } - else if (findTLSv13Suites == 1 && findbeforeSuites == 0) { - ret = 2;/* only TLSv13 suties */ - } - else { - ret = 0;/* handle as mixed */ + /* do nothing handler */ + static void myHandler(int signo) + { + (void)signo; + return; } - 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) -{ - 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; - if (suites == NULL || list == NULL) { - WOLFSSL_MSG("NULL argument"); - return WOLFSSL_FAILURE; - } - listattribute = CheckcipherList(list); + 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; - 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; - } - } + #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; } - /* 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; + if (hsCb) { + ssl->hsInfoOn = 1; + InitHandShakeInfo(&ssl->handShakeInfo, ssl); } + if (toCb) { + ssl->toInfoOn = 1; + InitTimeoutInfo(&ssl->timeoutInfo); - XMEMSET(suitesCpy, 0, suites->suiteSz); - } -#else - XMEMSET(suitesCpy, 0, sizeof(suitesCpy)); -#endif + if (gettimeofday(&startTime, 0) < 0) + ERR_OUT(GETTIME_ERROR); - if (suites->suiteSz > 0) - XMEMCPY(suitesCpy, suites->suites, suites->suiteSz); - suitesCpySz = suites->suiteSz; + /* 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); - 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 (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) { + oldTimerOn = 1; - 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; + /* 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; } } - } - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; -} + 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); + if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0) + ERR_OUT(SETITIMER_ERROR); + } -int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list"); - - if (ctx == NULL) - return WOLFSSL_FAILURE; - - if (AllocateCtxSuites(ctx) != 0) - return WOLFSSL_FAILURE; - -#ifdef OPENSSL_EXTRA - return wolfSSL_parse_cipher_list(ctx, NULL, ctx->suites, list); -#else - return (SetCipherList(ctx, ctx->suites, list)) ? - WOLFSSL_SUCCESS : 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 -} - -#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; - - if (AllocateCtxSuites(ctx) != 0) - 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; - return (SetCipherListFromBytes(ctx, ctx->suites, list, listSz)) ? - WOLFSSL_SUCCESS : WOLFSSL_FAILURE; -} -#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */ + /* 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; + } -int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) -{ - WOLFSSL_ENTER("wolfSSL_set_cipher_list"); + /* clean up buffers allocated by AddPacketInfo */ + FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap); - if (ssl == NULL || ssl->ctx == NULL) { - return WOLFSSL_FAILURE; + if (hsCb) { + FinishHandShakeInfo(&ssl->handShakeInfo); + (hsCb)(&ssl->handShakeInfo); + ssl->hsInfoOn = 0; + } + return ret; } - 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 -} -#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"); +#ifndef NO_WOLFSSL_CLIENT - if (ssl == NULL || ssl->ctx == NULL) { - return WOLFSSL_FAILURE; + 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); } - if (AllocateSuites(ssl) != 0) - return WOLFSSL_FAILURE; +#endif - return (SetCipherListFromBytes(ssl->ctx, ssl->suites, list, listSz)) - ? WOLFSSL_SUCCESS - : WOLFSSL_FAILURE; -} -#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */ +#ifndef NO_WOLFSSL_SERVER -#ifdef HAVE_KEYING_MATERIAL + 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); + } -#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 -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}, -}; +#endif /* WOLFSSL_CALLBACKS */ -/** - * 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; - WOLFSSL_ENTER("wolfSSL_export_keying_material"); +#ifndef NO_PSK - if (ssl == NULL || out == NULL || label == NULL || - (use_context && contextLen && context == NULL)) { - WOLFSSL_MSG("Bad argument"); - return WOLFSSL_FAILURE; - } + void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx, + wc_psk_client_callback cb) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_psk_client_callback"); - /* clientRandom + serverRandom - * OR - * clientRandom + serverRandom + ctx len encoding + ctx */ - seedLen = !use_context ? (word32)SEED_LEN : - (word32)SEED_LEN + 2 + (word32)contextLen; + if (ctx == NULL) + return; - 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; + ctx->havePSK = 1; + ctx->client_psk_cb = cb; } - /* 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; - } - } + void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb) + { + byte haveRSA = 1; + int keySz = 0; -#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 */ - } + WOLFSSL_ENTER("wolfSSL_set_psk_client_callback"); - 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 (ssl == NULL) + return; - /* Path for <=TLS 1.2 */ - seed = (byte*)XMALLOC(seedLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (seed == NULL) { - WOLFSSL_MSG("malloc error"); - return WOLFSSL_FAILURE; - } + ssl->options.havePSK = 1; + ssl->options.client_psk_cb = cb; - XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); - XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); + #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); + } + #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 (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); + if (ssl != NULL) { + ssl->options.havePSK = 1; + ssl->options.session_psk_cb = cb; } + + WOLFSSL_LEAVE("wolfSSL_set_psk_use_session_callback", WOLFSSL_SUCCESS); } + #endif - 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; + 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; } - PRIVATE_KEY_LOCK(); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_SUCCESS; -} -#endif /* HAVE_KEYING_MATERIAL */ + void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb) + { + byte haveRSA = 1; + int keySz = 0; -int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl) -{ - int useNb = 0; + WOLFSSL_ENTER("wolfSSL_set_psk_server_callback"); + if (ssl == NULL) + return; - if (ssl == NULL) - return WOLFSSL_FAILURE; + ssl->options.havePSK = 1; + ssl->options.server_psk_cb = cb; - 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."); + #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 useNb; -} - - -#ifndef WOLFSSL_LEANPSK - -void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock) -{ - (void)nonblock; - WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock"); + const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_get_psk_identity_hint"); - if (ssl == NULL) - return; + if (ssl == NULL || ssl->arrays == NULL) + return NULL; - 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."); + return ssl->arrays->server_hint; } -} - - -#ifdef WOLFSSL_DTLS - -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 + const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_get_psk_identity"); -/* - * 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 || ssl->arrays == NULL) + return NULL; -/* - * 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 */ + return ssl->arrays->client_identity; + } -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; + 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; } - return 0; -} -#ifndef NO_WOLFSSL_STUB -int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl) -{ - WOLFSSL_STUB("SSL_DTLSv1_handle_timeout"); - (void)ssl; - return 0; -} -#endif + int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint) + { + WOLFSSL_ENTER("wolfSSL_use_psk_identity_hint"); -#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 + if (ssl == NULL || ssl->arrays == NULL) + return WOLFSSL_FAILURE; -/* 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 (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; + } - if (timeout > ssl->dtls_timeout_max) { - WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout max"); - return BAD_FUNC_ARG; + 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 */ - ssl->dtls_timeout_init = timeout; - ssl->dtls_timeout = timeout; - return WOLFSSL_SUCCESS; -} +#ifdef HAVE_ANON + int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher"); -/* 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; + if (ctx == NULL) + return WOLFSSL_FAILURE; - if (timeout < ssl->dtls_timeout_init) { - WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init"); - return BAD_FUNC_ARG; + ctx->useAnon = 1; + + return WOLFSSL_SUCCESS; } - ssl->dtls_timeout_max = timeout; +#endif /* HAVE_ANON */ - return WOLFSSL_SUCCESS; -} +#ifndef NO_CERTS + /* 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; + } -int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) -{ - int result = WOLFSSL_SUCCESS; - WOLFSSL_ENTER("wolfSSL_dtls_got_timeout"); + 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; + } - if (ssl == NULL) - return WOLFSSL_FATAL_ERROR; + if (ssl->buffers.weOwnCertChain) { + WOLFSSL_MSG("Unloading cert chain"); + FreeDer(&ssl->buffers.certChain); + ssl->buffers.weOwnCertChain = 0; + } -#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->buffers.weOwnKey) { + WOLFSSL_MSG("Unloading key"); + ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length); + FreeDer(&ssl->buffers.key); + ssl->buffers.weOwnKey = 0; + } + +#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 */ return WOLFSSL_SUCCESS; } -#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; - } - else { - /* Reset return value to success */ - result = 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_CTX_UnloadCAs(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs"); - if (ssl == NULL) - return WOLFSSL_FATAL_ERROR; + if (ctx == NULL) + 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; - } + return wolfSSL_CertManagerUnloadCAs(ctx->cm); } - return 0; -} + int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts"); -#endif /* DTLS */ -#endif /* LEANPSK */ + 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; + } -#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) + return wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm); + } -/* 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; - WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret"); +#ifdef WOLFSSL_TRUST_PEER_CERT + int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); - if (ssl == NULL) { - WOLFSSL_MSG("need a SSL object"); - return BAD_FUNC_ARG; - } + if (ctx == NULL) + return BAD_FUNC_ARG; - if (secret != NULL && secretSz == 0) { - WOLFSSL_MSG("can't have a new secret without a size"); - return BAD_FUNC_ARG; + return wolfSSL_CertManagerUnload_trust_peers(ctx->cm); } - /* If secretSz is 0, use the default size. */ - if (secretSz == 0) - secretSz = COOKIE_SECRET_SZ; - - if (secretSz != ssl->buffers.dtlsCookieSecret.length) { - byte* newSecret; - - 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); - } +#ifdef WOLFSSL_LOCAL_X509_STORE + int wolfSSL_Unload_trust_peers(WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); - 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 - } + if (ssl == NULL) + return BAD_FUNC_ARG; - /* 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); + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl)); } - else - XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz); - - WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0); - return ret; -} +#endif /* WOLFSSL_LOCAL_X509_STORE */ +#endif /* WOLFSSL_TRUST_PEER_CERT */ +/* old NO_FILESYSTEM end */ +#endif /* !NO_CERTS */ -#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ +#ifdef OPENSSL_EXTRA -/* EITHER SIDE METHODS */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) - WOLFSSL_METHOD* wolfSSLv23_method(void) + int wolfSSL_add_all_algorithms(void) { - return wolfSSLv23_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* wolfSSLv23_method_ex(void* heap) + + int wolfSSL_OpenSSL_add_all_algorithms_noconf(void) { - 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_OpenSSL_add_all_algorithms_noconf"); - return m; - } + if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) + return WOLFSSL_FATAL_ERROR; - #ifdef WOLFSSL_ALLOW_SSLV3 - WOLFSSL_METHOD* wolfSSLv3_method(void) - { - return wolfSSLv3_method_ex(NULL); + return WOLFSSL_SUCCESS; } - WOLFSSL_METHOD* wolfSSLv3_method_ex(void* heap) + + int wolfSSL_OpenSSL_add_all_algorithms_conf(void) { - 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_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. */ - return m; + if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) { + return WOLFSSL_FATAL_ERROR; + } + return WOLFSSL_SUCCESS; } - #endif -#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ - -/* 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 +#endif - #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) +#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_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; + WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown"); + if (mode) + ctx->quietShutdown = 1; } - #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */ - WOLFSSL_METHOD* wolfSSLv23_client_method(void) + void wolfSSL_set_quiet_shutdown(WOLFSSL* ssl, int mode) { - return wolfSSLv23_client_method_ex(NULL); + WOLFSSL_ENTER("wolfSSL_set_quiet_shutdown"); + if (mode) + ssl->options.quietShutdown = 1; } - WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap) +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || + WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */ + +#ifdef OPENSSL_EXTRA +#ifndef NO_BIO + void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr) { - 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_set_bio"); + + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument, ssl was NULL"); + return; } - return method; - } - /* 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; - - #ifdef HAVE_ERRNO_H - errno = 0; - #endif - - 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; + /* 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; } - ssl->error = 0; /* expected to be zero here */ + 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; - #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 */ + ssl->biord = rd; + ssl->biowr = wr; - #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); + /* 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; } - #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; + /* 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_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 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 /* WOLFSSL_WOLFSENTRY_HOOKS */ + } - if (ssl->options.side != WOLFSSL_CLIENT_END) { - ssl->error = SIDE_ERROR; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; + 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_DTLS - if (ssl->version.major == DTLS_MAJOR) { - ssl->options.dtls = 1; - ssl->options.tls = 1; - ssl->options.tls1_1 = 1; - ssl->options.dtlsStateful = 1; + #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 (ctx != NULL) { + ctx->CBClientCert = cb; } - #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_CTX_set_cert_cb(WOLFSSL_CTX* ctx, + CertSetupCallback cb, void *arg) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_cert_cb"); + if (ctx == NULL) + return; -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) - advanceState = advanceState && !ssl->dtls13SendingAckOrRtx; -#endif /* WOLFSSL_DTLS13 */ + ctx->certSetupCb = cb; + ctx->certSetupCbArg = arg; + } - 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"); - } + 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; } - else { - ssl->error = ret; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; + if (hashSigAlgo != NULL && hashSigAlgoSz != NULL) { + *hashSigAlgo = ssl->clSuites->hashSigAlgo; + *hashSigAlgoSz = ssl->clSuites->hashSigAlgoSz; } -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls) - ssl->dtls13SendingAckOrRtx = 0; -#endif /* WOLFSSL_DTLS13 */ + 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; + } - ret = RetrySendAlert(ssl); - if (ret != 0) { - ssl->error = ret; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } + /** + * @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; - switch (ssl->options.connectState) { + if (hashAlgo == NULL || sigAlgo == NULL) + return BAD_FUNC_ARG; - 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; + input[0] = first; + input[1] = second; + DecodeSigAlg(input, &hashType, &sigType); - 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."); + /* 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_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 */ + /* 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; + } + + /** + * 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; + } + #endif /* OPENSSL_EXTRA */ - ssl->options.connectState = HELLO_AGAIN; - WOLFSSL_MSG("connect state: HELLO_AGAIN"); - FALL_THROUGH; +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */ - case HELLO_AGAIN : +#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"); - #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) - return wolfSSL_connect_TLSv13(ssl); - #endif + if (ctx == NULL) { + WOLFSSL_MSG("Bad argument passed to " + "wolfSSL_CTX_get_client_CA_list"); + return NULL; + } - #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 + return ctx->client_ca_names; + } - ssl->options.connectState = HELLO_AGAIN_REPLY; - WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); - FALL_THROUGH; + /* 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"); - case HELLO_AGAIN_REPLY : - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - neededState = ssl->options.resuming ? - SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE; + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list"); + return NULL; + } - /* 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 + return SSL_CA_NAMES(ssl); + } - ssl->options.connectState = FIRST_REPLY_DONE; - WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); - FALL_THROUGH; + #if !defined(NO_CERTS) + int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) + { + WOLFSSL_X509_NAME *nameCopy = NULL; - 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"); - } + WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); - #endif - ssl->options.connectState = FIRST_REPLY_FIRST; - WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); - FALL_THROUGH; + if (ctx == NULL || x509 == NULL){ + WOLFSSL_MSG("Bad argument"); + return WOLFSSL_FAILURE; + } - 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"); + 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; } + } - ssl->options.connectState = FIRST_REPLY_SECOND; - WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); - 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; + } - #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 (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 !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 WOLFSSL_SUCCESS; + } + #endif - 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; + #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 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_ENTER("wolfSSL_load_client_CA_file"); + + bio = wolfSSL_BIO_new_file(fname, "rb"); + if (bio == NULL) { + WOLFSSL_MSG("wolfSSL_BIO_new_file error"); + goto cleanup; } - WOLFSSL_MSG("sent: finished"); - ssl->options.connectState = FINISHED_DONE; - WOLFSSL_MSG("connect state: FINISHED_DONE"); - FALL_THROUGH; -#ifdef WOLFSSL_DTLS13 - case WAIT_FINISHED_ACK: - ssl->options.connectState = FINISHED_DONE; - FALL_THROUGH; -#endif /* WOLFSSL_DTLS13 */ + list = wolfSSL_sk_X509_NAME_new(NULL); + if (list == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); + goto cleanup; + } - 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; + /* 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; - ssl->options.connectState = SECOND_REPLY_DONE; - WOLFSSL_MSG("connect state: SECOND_REPLY_DONE"); - FALL_THROUGH; - - 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; + 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_HANDSHAKE_DONE_CB */ - if (!ssl->options.dtls) { - if (!ssl->options.keepResources) { - FreeHandshakeResources(ssl); - } - } - #ifdef WOLFSSL_DTLS - else { - ssl->options.dtlsHsRetain = 1; + wolfSSL_X509_free(cert); + cert = NULL; } - #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; + CLEAR_ASN_NO_PEM_HEADER_ERROR(err); + + 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; } - #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); + return list; + #else + (void)fname; + return NULL; #endif - - ssl->error = 0; /* clear the error */ - - WOLFSSL_LEAVE("wolfSSL_connect", WOLFSSL_SUCCESS); - return WOLFSSL_SUCCESS; - #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */ - - 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 */ + #endif + #endif /* !NO_BIO */ +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */ +#ifdef OPENSSL_EXTRA -/* server only parts */ -#ifndef NO_WOLFSSL_SERVER + #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 + }; - #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS) - WOLFSSL_METHOD* wolfSSLv2_server_method(void) + int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username) { - WOLFSSL_STUB("wolfSSLv2_server_method"); - return 0; - } - #endif + int r = 0; + SrpSide srp_side = SRP_CLIENT_SIDE; + byte salt[SRP_SALT_SIZE]; - #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; + 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; } - return method; - } - #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */ - WOLFSSL_METHOD* wolfSSLv23_server_method(void) - { - return wolfSSLv23_server_method_ex(NULL); - } + 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; + } - 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; + /* 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 method; - } + return WOLFSSL_SUCCESS; + } - WOLFSSL_ABI - int wolfSSL_accept(WOLFSSL* ssl) + int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password) { -#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; + int r; + byte salt[SRP_SALT_SIZE]; - (void)ret; + WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password"); + if (ctx == NULL || ctx->srp == NULL || password == NULL) + return WOLFSSL_FAILURE; - if (ssl == NULL) - return WOLFSSL_FATAL_ERROR; + 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); - #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; + 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; } - ssl->error = 0; /* expected to be zero here */ + XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1); } - #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ - -#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"); + return WOLFSSL_SUCCESS; + } - /* 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; + /** + * 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) + { + (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; + } -#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; - } + char* wolfSSL_get_srp_username(WOLFSSL *ssl) + { + if (ssl && ssl->ctx && ssl->ctx->srp) { + return (char*) ssl->ctx->srp->user; } -#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ + return NULL; + } + #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */ - #ifdef HAVE_ERRNO_H - errno = 0; - #endif + /* keyblock size in bytes or -1 */ + int wolfSSL_get_keyblock_size(WOLFSSL* ssl) + { + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; - #ifndef NO_PSK - havePSK = ssl->options.havePSK; - #endif - (void)havePSK; + return 2 * (ssl->specs.key_size + ssl->specs.iv_size + + ssl->specs.hash_size); + } - #ifdef HAVE_ANON - haveAnon = ssl->options.useAnon; - #endif - (void)haveAnon; +#endif /* OPENSSL_EXTRA */ - #ifdef WOLFSSL_MULTICAST - haveMcast = ssl->options.haveMcast; - #endif - (void)haveMcast; +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || \ + defined(WOLFSSL_WPAS_SMALL) - if (ssl->options.side != WOLFSSL_SERVER_END) { - ssl->error = SIDE_ERROR; - WOLFSSL_ERROR(ssl->error); + /* 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; - } - #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) { + *ms = ssl->arrays->masterSecret; + *sr = ssl->arrays->serverRandom; + *cr = ssl->arrays->clientRandom; - WOLFSSL_MSG("accept error: server cert required"); - ssl->error = NO_PRIVATE_KEY; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } + *msLen = SECRET_LEN; + *srLen = RAN_LEN; + *crLen = RAN_LEN; - 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 + return WOLFSSL_SUCCESS; + } - #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 + void wolfSSL_set_accept_state(WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_set_accept_state"); - 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 + if (ssl == NULL) + return; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_ECC + #ifdef WOLFSSL_SMALL_STACK + ecc_key* key = NULL; + #else + ecc_key key[1]; #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 + word32 idx = 0; + + #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; } - } - 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; + 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 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; - - 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(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 &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); - -void TlsSessionCacheUnlockRow(word32 row) -{ - SessionRow* sessRow; - - sessRow = &SessionCache[row]; - (void)sessRow; - SESSION_ROW_UNLOCK(sessRow); -} + if (ssl == NULL || out == NULL) { + return 0; + } -/* 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 (ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; } - if (*sess == NULL) { - SESSION_ROW_UNLOCK(sessRow); + + if (outSz > RAN_LEN) { + size = RAN_LEN; } else { - *lockedRow = row; + size = outSz; } - 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); + XMEMCPY(out, ssl->arrays->serverRandom, size); + return size; } +#endif /* !NO_WOLFSSL_SERVER */ +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ -int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) +#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) { - 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); + 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 + #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 - 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 + } + /* 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"); - - 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"); + WOLFSSL_ENTER("Set_SSL_max_proto_version"); - session = ClientSessionToSession(session); - if (session) { - int count; + if (!ssl) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } - 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; + 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_MSG("No session passed in"); - return NULL; + return CheckSslMethodVersion(ssl->version.major, ssl->options.mask); } -#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 wolfSSL_set_max_proto_version(WOLFSSL* ssl, int version) { - 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 + int ret = WOLFSSL_FAILURE;; - seen += row->totalCount; + WOLFSSL_ENTER("wolfSSL_set_max_proto_version"); - if (active == NULL) { - SESSION_ROW_UNLOCK(row); - continue; - } + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + if (version != 0) { + return Set_SSL_max_proto_version(ssl, version); + } - 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 */ - } + /* 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; + } - 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; - } +static int GetMinProtoVersion(int minDowngrade) +{ + int ret; - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(row); + switch (minDowngrade) { +#ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_SSLV3 + case SSLv3_MINOR: + ret = SSL3_VERSION; + break; #endif - } -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(&SessionCache[0]); + #ifdef WOLFSSL_ALLOW_TLSV10 + case TLSv1_MINOR: + ret = TLS1_VERSION; + break; + #endif + case TLSv1_1_MINOR: + ret = TLS1_1_VERSION; + break; #endif - - if (active) { - *active = now; - } - if (total) { - *total = seen; - } - -#ifdef WOLFSSL_PEAK_SESSIONS - if (peak) { - *peak = PeakSessions; - } -#else - (void)peak; +#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; + } - WOLFSSL_LEAVE("get_locked_session_stats", result); - - return result; + return ret; } - -/* return WOLFSSL_SUCCESS on ok */ -int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, - word32* maxSessions) +int wolfSSL_CTX_get_min_proto_version(WOLFSSL_CTX* ctx) { - int result = WOLFSSL_SUCCESS; - - WOLFSSL_ENTER("wolfSSL_get_session_stats"); + int ret = 0; - if (maxSessions) { - *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS; + WOLFSSL_ENTER("wolfSSL_CTX_get_min_proto_version"); - if (active == NULL && total == NULL && peak == NULL) - return result; /* we're done */ + if (ctx != NULL) { + if (ctx->minProto) { + ret = 0; + } + else { + ret = GetMinProtoVersion(ctx->minDowngrade); + } } - - /* user must provide at least one query value */ - if (active == NULL && total == NULL && peak == NULL) { - return BAD_FUNC_ARG; + else { + ret = GetMinProtoVersion(WOLFSSL_MIN_DOWNGRADE); } - result = get_locked_session_stats(active, total, peak); - - WOLFSSL_LEAVE("wolfSSL_get_session_stats", result); + WOLFSSL_LEAVE("wolfSSL_CTX_get_min_proto_version", ret); - return result; + return ret; } -#endif /* WOLFSSL_SESSION_STATS */ - - #ifdef PRINT_SESSION_STATS +/* 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 +#endif +#else + (void)options; +#endif /* NO_TLS */ + return WOLFSSL_FATAL_ERROR; +} - /* 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; - } +/* 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 */ - #endif /* SESSION_STATS */ + WOLFSSL_ENTER("wolfSSL_CTX_get_max_proto_version"); -#else /* NO_SESSION_CACHE */ + if (ctx != NULL) { + options = wolfSSL_CTX_get_options(ctx); + } -WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session) -{ - return (WOLFSSL_SESSION*)session; -} + if ((ctx != NULL) && ctx->maxProto) { + ret = 0; + } + else { + ret = GetMaxProtoVersion(options); + } -/* No session cache version */ -WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, - byte restoreSessionCerts) -{ - (void)ssl; - (void)masterSecret; - (void)restoreSessionCerts; + WOLFSSL_LEAVE("wolfSSL_CTX_get_max_proto_version", ret); - return NULL; + 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 */ -#endif /* NO_SESSION_CACHE */ - - -/* 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) +#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) { - WOLFSSL_ENTER("wolfSSL_check_domain_name"); + size_t size; - if (ssl == NULL || dn == NULL) { - WOLFSSL_MSG("Bad function argument: NULL"); - return WOLFSSL_FAILURE; + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; } - if (ssl->buffers.domainName.buffer) - XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); + if (ssl == NULL || out == NULL) { + return 0; + } - 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->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } - 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; + if (outSz > RAN_LEN) { + size = RAN_LEN; } else { - ssl->error = MEMORY_ERROR; - return WOLFSSL_FAILURE; + size = outSz; } + + XMEMCPY(out, ssl->arrays->clientRandom, size); + return size; } +#endif /* !NO_WOLFSSL_CLIENT */ +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ +#ifdef OPENSSL_EXTRA -/* 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; + unsigned long wolfSSLeay(void) + { + return SSLEAY_VERSION_NUMBER; + } + + unsigned long wolfSSL_OpenSSL_version_num(void) + { + return OPENSSL_VERSION_NUMBER; + } + + const char* wolfSSLeay_version(int type) + { + (void)type; +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L + return wolfSSL_OpenSSL_version(type); #else - return NOT_COMPILED_IN; + return wolfSSL_OpenSSL_version(); #endif -} + } +#endif /* OPENSSL_EXTRA */ +#ifdef OPENSSL_EXTRA + void wolfSSL_ERR_free_strings(void) + { + /* handled internally */ + } -#ifndef USE_WINDOWS_API - #ifndef NO_WRITEV + void wolfSSL_cleanup_all_ex_data(void) + { + /* nothing to do here */ + } - /* 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_ENTER("wolfSSL_writev"); +#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 - for (i = 0; i < iovcnt; i++) - sending += (int)iov[i].iov_len; +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + int wolfSSL_clear(WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_clear"); - if (sending > (int)sizeof(staticBuffer)) { - myBuffer = (byte*)XMALLOC(sending, ssl->heap, - DYNAMIC_TYPE_WRITEV); - if (!myBuffer) - return MEMORY_ERROR; + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } - dynamic = 1; + 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; } + } - for (i = 0; i < iovcnt; i++) { - XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len); - idx += (int)iov[i].iov_len; - } + /* reset error */ + ssl->error = 0; - /* 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 + /* 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 (dynamic) - XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV); + #if defined(HAVE_TLS_EXTENSIONS) && !defined(NO_TLS) + TLSX_FreeAll(ssl->extensions, ssl->heap); + ssl->extensions = NULL; + #endif - return ret; + 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 } - #endif -#endif + ssl->keys.encryptionOn = 0; + XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); + if (InitSSL_Suites(ssl) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; -#ifdef WOLFSSL_CALLBACKS + if (InitHandshakeHashes(ssl) != 0) + return WOLFSSL_FAILURE; - typedef struct itimerval Itimerval; +#ifdef KEEP_PEER_CERT + FreeX509(&ssl->peerCert); + InitX509(&ssl->peerCert, 0, ssl->heap); +#endif - /* don't keep calling simple functions while setting up timer and signals - if no inlining these are the next best */ +#ifdef WOLFSSL_QUIC + wolfSSL_quic_clear(ssl); +#endif - #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) + return WOLFSSL_SUCCESS; + } +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - #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) +#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 */ - #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)) \ + 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"); + } + /* SSL_MODE_AUTO_RETRY + * Should not return -1 with renegotiation on read/write */ - /* do nothing handler */ - static void myHandler(int signo) - { - (void)signo; - return; + return mode; } - - static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb, - TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) + long wolfSSL_CTX_clear_mode(WOLFSSL_CTX* ctx, long mode) { - 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; + /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */ - #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; } + 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 (hsCb) { - ssl->hsInfoOn = 1; - InitHandShakeInfo(&ssl->handShakeInfo, ssl); - } - if (toCb) { - ssl->toInfoOn = 1; - InitTimeoutInfo(&ssl->timeoutInfo); - - 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); - - if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) { - oldTimerOn = 1; - - /* 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); - - if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0) - ERR_OUT(SETITIMER_ERROR); - } + /* SSL_MODE_AUTO_RETRY + * Should not return -1 with renegotiation on read/write */ - /* 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); + return 0; + } #endif - /* 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; - - /* 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; - } - - /* clean up buffers allocated by AddPacketInfo */ - FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap); +#ifdef OPENSSL_EXTRA - if (hsCb) { - FinishHandShakeInfo(&ssl->handShakeInfo); - (hsCb)(&ssl->handShakeInfo); - ssl->hsInfoOn = 0; - } - return ret; + #ifndef NO_WOLFSSL_STUB + long wolfSSL_SSL_get_mode(WOLFSSL* ssl) + { + /* TODO: */ + (void)ssl; + WOLFSSL_STUB("SSL_get_mode"); + return 0; } + #endif + #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_CLIENT - - int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb, - TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) + #ifndef NO_WOLFSSL_STUB + void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m) { - WOLFSSL_ENTER("wolfSSL_connect_ex"); - return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout); + /* TODO: maybe? */ + (void)ctx; + (void)m; + WOLFSSL_STUB("SSL_CTX_set_default_read_ahead"); } + #endif -#endif + /* 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 */ -#ifndef NO_WOLFSSL_SERVER + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + return (unsigned long)ret; + #else + (void)file; + (void)line; - 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 0; + #endif } -#endif -#endif /* WOLFSSL_CALLBACKS */ +#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"; + /* 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 */ -#ifndef NO_PSK - void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx, - wc_psk_client_callback cb) + void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file, + int line) { - WOLFSSL_ENTER("wolfSSL_CTX_set_psk_client_callback"); - - if (ctx == NULL) - return; + WOLFSSL_ENTER("wolfSSL_ERR_put_error"); - ctx->havePSK = 1; - ctx->client_psk_cb = cb; + #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; } - void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb) + + /* 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) { - byte haveRSA = 1; - int keySz = 0; +#ifdef WOLFSSL_HAVE_ERROR_QUEUE + int ret; - WOLFSSL_ENTER("wolfSSL_set_psk_client_callback"); + WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data"); - if (ssl == NULL) - return; + if (flags != NULL) + *flags = ERR_TXT_STRING; /* Clear the flags */ - ssl->options.havePSK = 1; - ssl->options.client_psk_cb = cb; - - #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); - } - #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"); + 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 */ - if (ssl != NULL) { - ssl->options.havePSK = 1; - ssl->options.session_psk_cb = cb; + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); } - WOLFSSL_LEAVE("wolfSSL_set_psk_use_session_callback", WOLFSSL_SUCCESS); + 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 - 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; - } +#endif /* OPENSSL_EXTRA */ - void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb) + +#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) { - byte haveRSA = 1; - int keySz = 0; + 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_set_psk_server_callback"); - if (ssl == NULL) - return; + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif - ssl->options.havePSK = 1; - ssl->options.server_psk_cb = cb; + /* 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); + } + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif - #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 ret; } +#endif /* (KEEP_PEER_CERT & SESSION_CERTS) || (OPENSSL_EXTRA & SESSION_CERTS) */ - const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl) + +#ifdef KEEP_PEER_CERT + WOLFSSL_ABI + WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_get_psk_identity_hint"); + 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; + } - if (ssl == NULL || ssl->arrays == NULL) - return NULL; +#endif /* KEEP_PEER_CERT */ - return ssl->arrays->server_hint; - } +#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 (ssl == NULL) + return NULL; - const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_get_psk_identity"); + /* 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 (ssl == NULL || ssl->arrays == NULL) - return 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; - return ssl->arrays->client_identity; + for (i = 0; i < MAX_CHAIN_DEPTH; i++) { + if (x509GetIssuerFromCM(&issuer[i], cm, x) + != WOLFSSL_SUCCESS) + break; + x = issuer[i]; } - - 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'; + 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 { - /* 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 */ + wolfSSL_X509_free(issuer[i]); } - return WOLFSSL_SUCCESS; } + return ret; +} +#endif /* !WOLFSSL_QT */ - int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint) - { - WOLFSSL_ENTER("wolfSSL_use_psk_identity_hint"); +/* 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; - if (ssl == NULL || ssl->arrays == NULL) - return WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain"); + if ((ssl == NULL) || (ssl->session->chain.count == 0)) + return NULL; - 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'; + 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; + } } - return WOLFSSL_SUCCESS; - } - - 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 */ - - -#ifdef HAVE_ANON - - int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher"); - - if (ctx == NULL) - return WOLFSSL_FAILURE; - - ctx->useAnon = 1; - - return WOLFSSL_SUCCESS; - } - -#endif /* HAVE_ANON */ - - -#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; - - WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer_ex"); - - verify = GET_VERIFY_SETTING_CTX(ctx); - if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) - verify = VERIFY_SKIP_DATE; - - 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 - WOLFSSL_LEAVE("wolfSSL_CTX_load_verify_buffer_ex", ret); - return ret; + 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; + } } - /* 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 == NULL) { + WOLFSSL_MSG("Null session chain"); } - - 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 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 */ +#ifndef NO_CERTS +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -#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; - } - - #if (WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) - verify = VERIFY_SKIP_DATE; - #else - verify = GET_VERIFY_SETTING_CTX(ctx); - #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"); - 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); + sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap, + DYNAMIC_TYPE_OPENSSL); + if (sk != NULL) { + XMEMSET(sk, 0, sizeof(*sk)); + sk->heap = heap; } -#endif /* WOLFSSL_TRUST_PEER_CERT */ + return sk; +} - 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; +/* 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); } +} - - int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx, - const unsigned char* in, long sz, int format) - { - int ret = WOLFSSL_FAILURE; - - 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; +/* 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; } -#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 (*stack == NULL) { + in->num = 1; + *stack = in; + return WOLFSSL_SUCCESS; } - 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; - } + in->num = (*stack)->num + 1; + in->next = *stack; + *stack = in; + return WOLFSSL_SUCCESS; +} - return ret; - } +#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 */ - 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; - ret = WOLFSSL_SUCCESS; - } +/* 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"); - return ret; + if (!sk) { + return WOLFSSL_FAILURE; } -#endif /* WOLF_PRIVATE_KEY_ID */ - 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)); + /* 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; } - 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); + /* 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; } + /* push new x509 onto head of stack */ + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->num += 1; -#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 - - if (ctx == NULL || buf == NULL) - return BAD_FUNC_ARG; - - ret = AllocDer(&der, 0, DH_PARAM_TYPE, ctx->heap); - if (ret != 0) { - return ret; - } - 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; - } - #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 */ +#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); } - - 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); + 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); } - } - - FreeDer(&der); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - #endif - - return ret; +#endif + break; } + return WOLFSSL_SUCCESS; +} - /* 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; +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format); - } +#ifdef OPENSSL_EXTRA +/* 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; - /* 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); + current = sk; + for (i = 0; i <= idx && current != NULL; i++) { + if (i == idx) { + ret = current; + break; + } + current = current->next; } + return ret; +} -#endif /* NO_DH */ +#endif /* OPENSSL_EXTRA */ - 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; +#ifdef OPENSSL_EXTRA - return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0, - GET_VERIFY_SETTING_SSL(ssl)); - } +#if defined(OPENSSL_ALL) +void *wolfSSL_lh_retrieve(WOLFSSL_STACK *sk, void *data) +{ + unsigned long hash; - 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; + WOLFSSL_ENTER("wolfSSL_lh_retrieve"); - return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE, - ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl)); + if (!sk || !data) { + WOLFSSL_MSG("Bad parameters"); + return NULL; } -#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); - - if (ret == WOLFSSL_SUCCESS) - ssl->buffers.keySz = (word32)keySz; - - return ret; + if (!sk->hash_fn) { + WOLFSSL_MSG("No hash function defined"); + return NULL; } - int wolfSSL_use_PrivateKey_Id(WOLFSSL* ssl, const unsigned char* id, - long sz, int devId) - { - int ret = WOLFSSL_FAILURE; - - 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; + hash = sk->hash_fn(data); - ret = WOLFSSL_SUCCESS; + 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; + } } - - return ret; + 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; } - int wolfSSL_use_PrivateKey_Label(WOLFSSL* ssl, const char* label, int devId) - { - int ret = WOLFSSL_FAILURE; - word32 sz = (word32)XSTRLEN(label) + 1; + return NULL; +} - 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; +#endif /* OPENSSL_ALL */ - ret = WOLFSSL_SUCCESS; - } +#endif /* OPENSSL_EXTRA */ - 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; } -#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; - - return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, - ssl, NULL, 1, GET_VERIFY_SETTING_SSL(ssl)); + 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_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); + 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 NULL; +} - /* 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.weOwnCert && !ssl->keepCert) { - WOLFSSL_MSG("Unloading cert"); - FreeDer(&ssl->buffers.certificate); - #ifdef KEEP_OUR_CERT - wolfSSL_X509_free(ssl->ourCert); - ssl->ourCert = NULL; +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 - ssl->buffers.weOwnCert = 0; - } - - if (ssl->buffers.weOwnCertChain) { - WOLFSSL_MSG("Unloading cert chain"); - FreeDer(&ssl->buffers.certChain); - ssl->buffers.weOwnCertChain = 0; - } - - 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; - } - -#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; + ctx->ownOurCert = 1; } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - - return WOLFSSL_SUCCESS; + return ctx->ourCert; } + return NULL; +} +#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */ +#endif /* NO_CERTS */ - - int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs"); - - if (ctx == NULL) - return BAD_FUNC_ARG; - - return wolfSSL_CertManagerUnloadCAs(ctx->cm); +#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_UnloadIntermediateCerts(WOLFSSL_CTX* ctx) - { - 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 wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm); + #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 */ -#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; - return wolfSSL_CertManagerUnload_trust_peers(ctx->cm); - } +int wolfSSL_get_shutdown(const WOLFSSL* ssl) +{ + int isShutdown = 0; -#ifdef WOLFSSL_LOCAL_X509_STORE - int wolfSSL_Unload_trust_peers(WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); + WOLFSSL_ENTER("wolfSSL_get_shutdown"); - if (ssl == NULL) - return BAD_FUNC_ARG; + 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; + } - 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 */ + WOLFSSL_LEAVE("wolfSSL_get_shutdown", isShutdown); + return isShutdown; +} -#ifdef OPENSSL_EXTRA - 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; +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; +} - 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; +/* 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"); - return WOLFSSL_SUCCESS; + if (version == NULL) { + return "Bad arg"; } - 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 (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) { - return WOLFSSL_FATAL_ERROR; + 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"; } - return WOLFSSL_SUCCESS; } - - /* 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 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"; +} -#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; +const char* wolfSSL_get_version(const WOLFSSL* ssl) +{ + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument"); + return "unknown"; } + return wolfSSL_internal_get_version(&ssl->version); +} - 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 -#ifndef NO_BIO - void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr) - { - WOLFSSL_ENTER("wolfSSL_set_bio"); +/* current library version */ +const char* wolfSSL_lib_version(void) +{ + return LIBWOLFSSL_VERSION_STRING; +} - if (ssl == NULL) { - WOLFSSL_MSG("Bad argument, ssl was NULL"); - return; - } +#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 - /* 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; +/* current library version in hex */ +word32 wolfSSL_lib_version_hex(void) +{ + return LIBWOLFSSL_VERSION_HEX; +} - /* 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; - } - /* 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 */ +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; +} -#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; - } +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; +} - 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 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"); +const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_ENTER("wolfSSL_CIPHER_get_name"); - if (ctx != NULL) { - ctx->CBClientCert = cb; - } + if (cipher == NULL) { + return NULL; } - void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx, - CertSetupCallback cb, void *arg) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_cert_cb"); - if (ctx == NULL) - return; + #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 +} - ctx->certSetupCb = cb; - ctx->certSetupCbArg = arg; +const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_ENTER("wolfSSL_CIPHER_get_version"); + + if (cipher == NULL || cipher->ssl == NULL) { + return NULL; } - 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"); + return wolfSSL_get_version(cipher->ssl); +} - if (suites != NULL) - *suites = NULL; - if (suiteSz != NULL) - *suiteSz = 0; - if (hashSigAlgo != NULL) - *hashSigAlgo = NULL; - if (hashSigAlgoSz != NULL) - *hashSigAlgoSz = 0; +const char* wolfSSL_get_cipher(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_cipher"); + return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)); +} - 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; - } - 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; - } +/* 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); +} - /** - * @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; +const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0, + const byte cipherSuite) +{ + return GetCipherNameInternal(cipherSuite0, cipherSuite); +} - if (hashAlgo == NULL || sigAlgo == NULL) - return BAD_FUNC_ARG; +const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0, + const byte cipherSuite) +{ + return GetCipherNameIana(cipherSuite0, cipherSuite); +} - input[0] = first; - input[1] = second; - DecodeSigAlg(input, &hashType, &sigType); +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); +} - /* 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; - } - /** - * 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; - } - #endif /* OPENSSL_EXTRA */ +#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"); -#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */ + sk = wolfSSL_sk_new_null(); + if (sk == NULL) + return NULL; + sk->type = STACK_TYPE_CIPHER; -#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"); + return sk; +} - if (ctx == NULL) { - WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get_client_CA_list"); - return NULL; - } +/* 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); +} - return ctx->client_ca_names; - } +#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 */ - /* 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"); +word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher) +{ + word16 cipher_id = 0; - if (ssl == NULL) { - WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list"); - return NULL; - } + WOLFSSL_ENTER("wolfSSL_CIPHER_get_id"); - return SSL_CA_NAMES(ssl); + if (cipher && cipher->ssl) { + cipher_id = (cipher->ssl->options.cipherSuite0 << 8) | + cipher->ssl->options.cipherSuite; } - #if !defined(NO_CERTS) - int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) - { - WOLFSSL_X509_NAME *nameCopy = NULL; + return cipher_id; +} - WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); +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"); - if (ctx == NULL || x509 == NULL){ - WOLFSSL_MSG("Bad argument"); - return WOLFSSL_FAILURE; - } + /* extract cipher id information */ + cipherSuite = (value & 0xFF); + cipherSuite0 = ((value >> 8) & 0xFF); - 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; - } - } + /* TODO: lookup by cipherSuite0 / cipherSuite */ + (void)cipherSuite0; + (void)cipherSuite; - nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509)); - if (nameCopy == NULL) { - WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); - return WOLFSSL_FAILURE; - } + return cipher; +} - 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; - } - return WOLFSSL_SUCCESS; +#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"); + + wolfSSL_sk_free(sk); +} +#endif /* OPENSSL_ALL */ + +#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; } - #endif + 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; - #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_get_curve_name"); - WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); + if (ssl == NULL) + return NULL; - 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; - } +#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 + } + } - /* 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; +#endif /* WOLFSSL_TLS13 && HAVE_PQC */ +#ifdef HAVE_FFDHE + if (ssl->namedGroup != 0) { + cName = wolfssl_ffdhe_name(ssl->namedGroup); + } +#endif - 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; - } +#ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) { + cName = "X25519"; + } +#endif - wolfSSL_X509_free(cert); - cert = NULL; - } +#ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) { + cName = "X448"; + } +#endif - CLEAR_ASN_NO_PEM_HEADER_ERROR(err); +#ifdef HAVE_ECC + if (ssl->ecdhCurveOID != 0 && cName == NULL) { + cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, + NULL)); + } +#endif - 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 cName; +} +#endif #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} + }; - #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; -#endif - - WOLFSSL_ENTER("wolfSSL_CTX_set_default_verify_paths"); + const char* authStr; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; -#ifdef XGETENV - certDir = XGETENV("SSL_CERT_DIR"); - certFile = XGETENV("SSL_CERT_FILE"); - flags = WOLFSSL_LOAD_FLAG_PEM_CA_ONLY; + if (GetCipherSegment(cipher, n) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; + } - 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; - } + authStr = GetCipherAuthStr(n); - 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; + 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 ret; - } -#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; } -#endif - - WOLFSSL_LEAVE("wolfSSL_CTX_set_default_verify_paths", ret); - - return ret; } - #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 + 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} }; - 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]; + const char* encStr; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; - WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username"); - if (ctx == NULL || ctx->srp == NULL || username==NULL) - return WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_CIPHER_get_cipher_nid"); - 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 (GetCipherSegment(cipher, n) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; + } - 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; - } + encStr = GetCipherEncStr(n); - /* 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; + 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; } - 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; } - int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password) - { - int r; - byte salt[SRP_SALT_SIZE]; + 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} + }; - WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password"); - if (ctx == NULL || ctx->srp == NULL || password == NULL) - return WOLFSSL_FAILURE; + const char* name; + const char* macStr; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; + (void)name; - 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); + WOLFSSL_ENTER("wolfSSL_CIPHER_get_digest_nid"); - 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 ((name = GetCipherSegment(cipher, n)) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; } - /** - * 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) - { - (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; + /* in MD5 case, NID will be NID_md5 */ + if (XSTRSTR(name, "MD5") != NULL) { + return NID_md5; } - char* wolfSSL_get_srp_username(WOLFSSL *ssl) - { - if (ssl && ssl->ctx && ssl->ctx->srp) { - return (char*) ssl->ctx->srp->user; + macStr = GetCipherMacStr(n); + + 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; } - #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */ - /* keyblock size in bytes or -1 */ - int wolfSSL_get_keyblock_size(WOLFSSL* ssl) - { - if (ssl == NULL) - return WOLFSSL_FATAL_ERROR; + 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} + }; - return 2 * (ssl->specs.key_size + ssl->specs.iv_size + - ssl->specs.hash_size); + const char* keaStr; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; + + WOLFSSL_ENTER("wolfSSL_CIPHER_get_kx_nid"); + + if (GetCipherSegment(cipher, n) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; } -#endif /* OPENSSL_EXTRA */ + /* in TLS 1.3 case, NID will be NID_kx_any */ + if (XSTRCMP(n[0], "TLS13") == 0) { + return NID_kx_any; + } -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + keaStr = GetCipherKeaStr(n); - /* 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; + if (keaStr != NULL) { + const struct kxnid* k; + for(k = kxnid_table; k->name != NULL; k++) { + if (XSTRCMP(k->name, keaStr) == 0) { + return k->nid; + } + } + } - *ms = ssl->arrays->masterSecret; - *sr = ssl->arrays->serverRandom; - *cr = ssl->arrays->clientRandom; + 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}}; - *msLen = SECRET_LEN; - *srLen = RAN_LEN; - *crLen = RAN_LEN; + WOLFSSL_ENTER("wolfSSL_CIPHER_is_aead"); - return WOLFSSL_SUCCESS; + if (GetCipherSegment(cipher, n) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; } - void wolfSSL_set_accept_state(WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_set_accept_state"); + 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"); - if (ssl == NULL) - return; + if (cipher == NULL) + return WOLFSSL_FAILURE; - 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; + dp = cipher->description; + if (dp == NULL) + return WOLFSSL_FAILURE; - #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_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 - } - - if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error initializing server side"); - } - } - -#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - - /* return true if connection established */ - int wolfSSL_is_init_finished(const WOLFSSL* ssl) - { - if (ssl == NULL) - return 0; - - /* 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; + cipher_names = GetCipherNames(); - return 0; - } + 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); -#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; + if ((name = GetCipherSegment(cipher, n)) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return WOLFSSL_FAILURE; } - - 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; - } - - ssl->options.sentNotify = (opt&WOLFSSL_SENT_SHUTDOWN) > 0; - ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0; + /* 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); - 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; - } - /* forward declaration */ - static long wolf_set_options(long old_op, long op); + /* 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; - long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_options"); + 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; - if (ctx == NULL) - return BAD_FUNC_ARG; + 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; - 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; - } + 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; - 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; - } + 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; -#ifdef OPENSSL_EXTRA + XSTRNCPY(dp, " Mac=", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; + XSTRNCPY(dp, macStr, len); + dp[len-1] = '\0'; - int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd) - { - WOLFSSL_ENTER("wolfSSL_set_rfd"); - ssl->rfd = rfd; /* not used directly to allow IO callbacks */ + return WOLFSSL_SUCCESS; +} +#endif /* OPENSSL_ALL || WOLFSSL_QT */ - ssl->IOCB_ReadCtx = &ssl->rfd; +static WC_INLINE const char* wolfssl_kea_to_string(int kea) +{ + const char* keaStr; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; - ssl->buffers.dtlsCtx.rfd = rfd; - } + 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 - - 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; + #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; } -#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; + return keaStr; +} - WOLFSSL_ENTER("wolfSSL_get0_verified_chain"); +static WC_INLINE const char* wolfssl_sigalg_to_string(int sig_algo) +{ + const char* authStr; - 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; - } - wolfSSL_X509_STORE_CTX_free(storeCtx); - return chain; + 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; } -#endif /* SESSION_CERTS && OPENSSL_EXTRA */ - WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx) - { - if (ctx == NULL) { - return NULL; - } + return authStr; +} - if (ctx->x509_store_pt != NULL) - return ctx->x509_store_pt; - return &ctx->x509_store; +static WC_INLINE const char* wolfssl_cipher_to_string(int cipher, int key_size) +{ + const char* encStr; + + (void)key_size; + + 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; } - 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; - } + return encStr; +} - 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; +static WC_INLINE const char* wolfssl_mac_to_string(int mac) +{ + const char* macStr; - /* 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*/ + 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; } -#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"); + return macStr; +} - if (ctx == NULL || str == NULL) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } +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"); - /* NO-OP when setting existing store */ - if (str == CTX_STORE(ctx)) - return WOLFSSL_SUCCESS; + if (cipher == NULL || in == NULL) + return NULL; - if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error"); - return WOLFSSL_FAILURE; - } - - /* 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; +#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 - int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) - { - WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store"); - - 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; - } + /* 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; - int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) - { - WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store"); + 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 (ssl == NULL || str == NULL) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } + 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; - /* NO-OP when setting existing store */ - if (str == SSL_STORE(ssl)) - return WOLFSSL_SUCCESS; + 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; - if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error"); - return WOLFSSL_FAILURE; - } + 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; - /* 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 /* !NO_CERTS && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */ + XSTRNCPY(in, " Mac=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, macStr, len); + in[len-1] = '\0'; -#ifdef WOLFSSL_ENCRYPTED_KEYS + return ret; +} - 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; - } +#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 - 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; - } +#ifndef NO_WOLFSSL_STUB +WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void) +{ + WOLFSSL_STUB("COMP_zlib"); + return 0; +} +#endif - wc_pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx) - { - if (ctx == NULL || ctx->passwd_cb == NULL) { - return NULL; - } +#ifndef NO_WOLFSSL_STUB +WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) +{ + WOLFSSL_STUB("COMP_rle"); + return 0; +} +#endif - return ctx->passwd_cb; - } +#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 +/* 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; +} - void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx) - { - if (ctx == NULL) { - return NULL; - } - return ctx->passwd_userdata; - } +#endif /* OPENSSL_EXTRA */ -#endif /* WOLFSSL_ENCRYPTED_KEYS */ +#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) +{ + return wolfSSL_EVP_PKEY_get_der(key, der); +} -#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 - } +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; -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - - int wolfSSL_num_locks(void) - { - return 0; + if (key == NULL) { + return WOLFSSL_FATAL_ERROR; } - void wolfSSL_set_locking_callback(mutex_cb* f) - { - WOLFSSL_ENTER("wolfSSL_set_locking_callback"); + key_type = key->type; + if ((key_type != EVP_PKEY_EC) && (key_type != EVP_PKEY_RSA)) { + return WOLFSSL_FATAL_ERROR; + } - if (wc_SetMutexCb(f) != 0) { - WOLFSSL_MSG("Error when setting mutex call back"); - } +#ifndef NO_RSA + if (key_type == EVP_PKEY_RSA) { + return wolfSSL_i2d_RSAPublicKey(key->rsa, der); } +#endif - mutex_cb* wolfSSL_get_locking_callback(void) - { - WOLFSSL_ENTER("wolfSSL_get_locking_callback"); + /* Now that RSA is taken care of, we only need to consider the ECC case. */ - return wc_GetMutexCb(); - } - - - typedef unsigned long (idCb)(void); - static idCb* inner_idCb = NULL; +#ifdef HAVE_ECC - unsigned long wolfSSL_thread_id(void) - { - if (inner_idCb != NULL) { - return inner_idCb(); + /* 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 { - return 0; + } else { + local_derSz = ret; + ret = 0; + } + + 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); + } - void wolfSSL_set_id_callback(unsigned long (*f)(void)) - { - inner_idCb = f; + 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_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 (ret == 0) { + pub_derSz = wc_EccPublicKeyDerSize(eccKey, 0); + if ((int)pub_derSz <= 0) { + ret = WOLFSSL_FAILURE; + } + } - WOLFSSL_ENTER("wolfSSL_ERR_print_errors"); + 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 (bio == NULL) { - WOLFSSL_MSG("BIO passed in was null"); - return; + if (ret == 0) { + pub_derSz = wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 0); + if ((int)pub_derSz <= 0) { + ret = WOLFSSL_FATAL_ERROR; } + } - 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"); + /* 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 (ret == 0) { + XMEMCPY(*der, pub_der, pub_derSz); } - 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"); + else { + XMEMCPY(*der, pub_der, pub_derSz); + *der += pub_derSz; } } -#endif /* !NO_BIO */ -#endif /* WOLFSSL_HAVE_ERROR_QUEUE */ - -#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ - -#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 - */ -size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, - size_t outSz) -{ - size_t size; - /* return max size of buffer */ - if (outSz == 0) { - return RAN_LEN; - } + XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(local_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - if (ssl == NULL || out == NULL) { - return 0; - } + wc_ecc_free(eccKey); + XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC); - if (ssl->arrays == NULL) { - WOLFSSL_MSG("Arrays struct not saved after handshake"); - return 0; - } +#else + ret = WOLFSSL_FATAL_ERROR; +#endif /* HAVE_ECC */ - if (outSz > RAN_LEN) { - size = RAN_LEN; - } - else { - size = outSz; + if (ret == 0) { + return pub_derSz; } - XMEMCPY(out, ssl->arrays->serverRandom, size); - return size; + return ret; +#else + return WOLFSSL_FATAL_ERROR; +#endif /* !NO_RSA || HAVE_ECC */ } -#endif /* !NO_WOLFSSL_SERVER */ -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ +#endif /* !NO_ASN && !NO_PWDBASED */ -#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; +#endif /* !NO_CERTS */ +#endif /* OPENSSL_EXTRA */ - WOLFSSL_ENTER("wolfSSL_get_server_tmp_key"); +#ifdef OPENSSL_EXTRA - if (ssl == NULL || pkey == NULL) { - WOLFSSL_MSG("Bad argument passed in"); +/* 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; } -#ifdef HAVE_ECC - if (ssl->peerEccKey != NULL) { - unsigned char* der; - const unsigned char* pt; - unsigned int derSz = 0; - int sz; + return wolfSSL_X509_VERIFY_PARAM_set1_host(ssl->param, name, 0); +} - 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(); +/****************************************************************************** +* 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; - 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; - } + return wolfSSL_X509_VERIFY_PARAM_set1(ctx->param, vpm); +} - 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; - } - pt = der; /* in case pointer gets advanced */ - ret = wolfSSL_d2i_PUBKEY(NULL, &pt, sz); - XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY); +/****************************************************************************** +* 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; } -#endif - *pkey = ret; -#ifdef HAVE_ECC - if (ret != NULL) - return WOLFSSL_SUCCESS; - else -#endif - return WOLFSSL_FAILURE; + return ctx->param; } -#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_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl) { - int sanityConfirmed = 0; - - (void)options; - - 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 (!sanityConfirmed) { - WOLFSSL_MSG("All compiled in TLS versions disabled"); - return WOLFSSL_FAILURE; + if (ssl == NULL) { + return NULL; } - return WOLFSSL_SUCCESS; + return ssl->param; } -/** - * 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)) +#endif /* OPENSSL_EXTRA */ -/** - * 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. +#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 */ -static int Set_CTX_min_proto_version(WOLFSSL_CTX* ctx, int version) +int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void) { - WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version_ex"); - - if (ctx == NULL) { - return WOLFSSL_FAILURE; - } - - 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; - } - - 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; - } + WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx"); - return CheckSslMethodVersion(ctx->method->version.major, ctx->mask); + /* store SSL at index 0 */ + return 0; } +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ -/* 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) +#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)) { - int ret; - int proto = 0; - int maxProto = 0; - int i; - int idx = 0; - - WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version"); - + WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback"); 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; - } - } + WOLFSSL_MSG("Bad function argument"); } 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; - } - } + ctx->CBIS = f; } +} - /* 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; - } +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"); } - 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); + else { + ssl->CBIS = f; } +} - ret = Set_CTX_min_proto_version(ctx, proto); - return ret; + +unsigned long wolfSSL_ERR_peek_error(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); + + return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL); } -/** - * 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 wolfSSL_ERR_GET_LIB(unsigned long err) { - int ret; - WOLFSSL_ENTER("Set_CTX_max_proto_version"); - - if (!ctx || !ctx->method) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } + unsigned long value; - 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 + 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: - WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); - return WOLFSSL_FAILURE; - } - - 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 - #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 - #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 0; } - return ret; } - -/* 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) +/* 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 i; - int ret = WOLFSSL_FAILURE; - int minProto; + int ret = (int)err; - WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version"); + WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON"); - if (ctx == NULL) { - return ret; - } +#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 - /* 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); + /* 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; } - - /* 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; - } + else { + WOLFSSL_MSG("Not in range of typical error values"); + ret = (int)err; } return ret; } +/* 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"); + + return AlertTypeToString(alertID); +} + -static int Set_SSL_min_proto_version(WOLFSSL* ssl, int ver) +const char* wolfSSL_alert_desc_string_long(int alertID) { - WOLFSSL_ENTER("Set_SSL_min_proto_version"); + WOLFSSL_ENTER("wolfSSL_alert_desc_string_long"); - if (ssl == NULL) { - return WOLFSSL_FAILURE; + 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}, \ } - 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; - } - - 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; +#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}, \ } - return CheckSslMethodVersion(ssl->version.major, ssl->options.mask); -} - -int wolfSSL_set_min_proto_version(WOLFSSL* ssl, int version) +/* 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) { - int i; - int ret = WOLFSSL_FAILURE;; - - WOLFSSL_ENTER("wolfSSL_set_min_proto_version"); - - 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; -} + 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 + }; -static int Set_SSL_max_proto_version(WOLFSSL* ssl, int ver) -{ + enum IOMode { + SS_READ = 0, + SS_WRITE, + SS_NEITHER + }; - WOLFSSL_ENTER("Set_SSL_max_proto_version"); + 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 + }; - if (!ssl) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } + int protocol = 0; + int cbmode = 0; + int state = 0; - 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_ENTER("wolfSSL_state_string_long"); + if (ssl == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return NULL; } - return CheckSslMethodVersion(ssl->version.major, ssl->options.mask); -} - -int wolfSSL_set_max_proto_version(WOLFSSL* ssl, int version) -{ - int i; - int ret = WOLFSSL_FAILURE;; - - WOLFSSL_ENTER("wolfSSL_set_max_proto_version"); - - if (ssl == NULL) { - return WOLFSSL_FAILURE; + /* Get state of callback */ + if (ssl->cbmode == SSL_CB_MODE_WRITE) { + cbmode = SS_WRITE; } - if (version != 0) { - return Set_SSL_max_proto_version(ssl, version); + else if (ssl->cbmode == SSL_CB_MODE_READ) { + cbmode = SS_READ; } - - /* 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; + else { + cbmode = SS_NEITHER; } - return ret; -} - -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; + /* 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; -#endif - default: - ret = 0; + 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; } - return ret; -} - -int wolfSSL_CTX_get_min_proto_version(WOLFSSL_CTX* ctx) -{ - int ret = 0; - - WOLFSSL_ENTER("wolfSSL_CTX_get_min_proto_version"); - - if (ctx != NULL) { - if (ctx->minProto) { - ret = 0; - } - else { - ret = GetMinProtoVersion(ctx->minDowngrade); + /* 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 { - ret = GetMinProtoVersion(WOLFSSL_MIN_DOWNGRADE); - } + /* Send process */ + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ssl->options.serverState; + else + state = ssl->options.clientState; - WOLFSSL_LEAVE("wolfSSL_CTX_get_min_proto_version", ret); + 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; + } + } - return ret; + if (protocol == UNKNOWN) { + WOLFSSL_MSG("Unknown protocol"); + return ""; + } + else { + return OUTPUT_STR[state][protocol][cbmode]; + } } +#endif /* OPENSSL_EXTRA */ -/* returns the maximum allowed protocol version given the 'options' used - * returns WOLFSSL_FATAL_ERROR on no match */ -static int GetMaxProtoVersion(long options) +static long wolf_set_options(long old_op, long op) { -#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; -} + /* if SSL_OP_ALL then turn all bug workarounds on */ + if ((op & WOLFSSL_OP_ALL) == WOLFSSL_OP_ALL) { + WOLFSSL_MSG("\tSSL_OP_ALL"); + } + /* 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"); + } -/* 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 */ + if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) { + WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); + } - WOLFSSL_ENTER("wolfSSL_CTX_get_max_proto_version"); +#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"); + } +#endif - if (ctx != NULL) { - options = wolfSSL_CTX_get_options(ctx); + if ((op & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); } - if ((ctx != NULL) && ctx->maxProto) { - ret = 0; + if ((op & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1"); } - else { - ret = GetMaxProtoVersion(options); + + if ((op & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); } - WOLFSSL_LEAVE("wolfSSL_CTX_get_max_proto_version", ret); + if ((op & WOLFSSL_OP_NO_SSLv3) == WOLFSSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tSSL_OP_NO_SSLv3"); + } - if (ret == WOLFSSL_FATAL_ERROR) { - WOLFSSL_MSG("Error getting max proto version"); - ret = 0; /* setting ret to 0 to match compat return */ + if ((op & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) == + WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) { + WOLFSSL_MSG("\tWOLFSSL_OP_CIPHER_SERVER_PREFERENCE"); } - return ret; + + 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; } -#endif /* OPENSSL_EXTRA */ -#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) +long wolfSSL_set_options(WOLFSSL* ssl, long op) { - size_t size; + word16 haveRSA = 1; + word16 havePSK = 0; + int keySz = 0; - /* return max size of buffer */ - if (outSz == 0) { - return RAN_LEN; - } + WOLFSSL_ENTER("wolfSSL_set_options"); - if (ssl == NULL || out == NULL) { + if (ssl == NULL) { return 0; } - if (ssl->arrays == NULL) { - WOLFSSL_MSG("Arrays struct not saved after handshake"); - return 0; - } + ssl->options.mask = wolf_set_options(ssl->options.mask, op); - if (outSz > RAN_LEN) { - size = RAN_LEN; - } - else { - size = outSz; + 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; } - XMEMCPY(out, ssl->arrays->clientRandom, size); - return size; -} -#endif /* !NO_WOLFSSL_CLIENT */ -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ - -#ifdef OPENSSL_EXTRA - - unsigned long wolfSSLeay(void) - { - return SSLEAY_VERSION_NUMBER; + 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; } - unsigned long wolfSSL_OpenSSL_version_num(void) - { - return OPENSSL_VERSION_NUMBER; + 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; } - 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 + if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) { + if (ssl->version.minor == TLSv1_MINOR) + ssl->version.minor = SSLv3_MINOR; } -#endif /* OPENSSL_EXTRA */ -#ifdef OPENSSL_EXTRA - void wolfSSL_ERR_free_strings(void) - { - /* handled internally */ + if ((ssl->options.mask & WOLFSSL_OP_NO_COMPRESSION) + == WOLFSSL_OP_NO_COMPRESSION) { + #ifdef HAVE_LIBZ + ssl->options.usingCompression = 0; + #endif } - void wolfSSL_cleanup_all_ex_data(void) - { - /* nothing to do here */ +#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_EXTRA */ -#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 - } + /* 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 defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) - int wolfSSL_clear(WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_clear"); + if (ssl->options.side != WOLFSSL_NEITHER_END) { + if (AllocateSuites(ssl) != 0) + 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 (ssl == NULL) { - return WOLFSSL_FAILURE; - } + return ssl->options.mask; +} - 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; - } - } - /* reset error */ - ssl->error = 0; +long wolfSSL_get_options(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_options"); + if(ssl == NULL) + return WOLFSSL_FAILURE; + return ssl->options.mask; +} - /* 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 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 defined(HAVE_TLS_EXTENSIONS) && !defined(NO_TLS) - TLSX_FreeAll(ssl->extensions, ssl->heap); - ssl->extensions = NULL; - #endif + WOLFSSL_ENTER("wolfSSL_clear_num_renegotiations"); + if (s == NULL) + return 0; - 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; + total = s->secure_rene_count; + s->secure_rene_count = 0; + return total; +} - if (InitHandshakeHashes(ssl) != 0) - return WOLFSSL_FAILURE; -#ifdef KEEP_PEER_CERT - FreeX509(&ssl->peerCert); - InitX509(&ssl->peerCert, 0, ssl->heap); -#endif +/* return the number of renegotiations since wolfSSL_new */ +long wolfSSL_total_renegotiations(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_total_renegotiations"); + return wolfSSL_num_renegotiations(s); +} -#ifdef WOLFSSL_QUIC - wolfSSL_quic_clear(ssl); -#endif - return WOLFSSL_SUCCESS; +/* return the number of renegotiations since wolfSSL_new */ +long wolfSSL_num_renegotiations(WOLFSSL* s) +{ + if (s == NULL) { + return 0; } -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - -#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 */ + return s->secure_rene_count; +} - 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"); - } - /* SSL_MODE_AUTO_RETRY - * Should not return -1 with renegotiation on read/write */ +/* 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 */ - return mode; - } +#ifdef OPENSSL_EXTRA - long wolfSSL_CTX_clear_mode(WOLFSSL_CTX* ctx, long mode) - { - /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */ +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; +} - 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"); - } +#ifdef HAVE_PK_CALLBACKS +long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } - /* SSL_MODE_AUTO_RETRY - * Should not return -1 with renegotiation on read/write */ + ssl->loggingCtx = arg; + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_PK_CALLBACKS */ - return 0; - } +/*** 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 -#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; +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) +{ + WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type"); - return WOLFSSL_SUCCESS; + 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; + } +} - /* 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"); +long wolfSSL_get_tlsext_status_type(WOLFSSL *s) +{ + TLSX* extension; - if (len > ID_LEN || ssl == NULL || id == NULL) { - return WOLFSSL_FAILURE; - } - XMEMCPY(ssl->sessionCtx, id, len); - ssl->sessionCtxSz = (byte)len; + 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 WOLFSSL_SUCCESS; - } +#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 -#ifdef OPENSSL_EXTRA +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); + return WOLFSSL_FAILURE; +} +#endif - #ifndef NO_WOLFSSL_STUB - long wolfSSL_SSL_get_mode(WOLFSSL* ssl) - { - /* TODO: */ - (void)ssl; - WOLFSSL_STUB("SSL_get_mode"); - return 0; - } - #endif +/*** 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 NO_WOLFSSL_STUB - long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx) - { - /* TODO: */ - (void)ctx; - WOLFSSL_STUB("SSL_CTX_get_mode"); - return 0; - } - #endif +/*** 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 - #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 +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) +{ + (void)ssl; + WOLFSSL_STUB("SSL_get_privatekey"); + return NULL; +} +#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 - 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 +#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; +} +#endif + + +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; } + return (int)p->num; +} +WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(WOLFSSL_STACK* sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_value"); + return (WOLFSSL_CIPHER*)wolfSSL_sk_value(sk, i); +} - /* 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 */ +#if !defined(NETOS) +void ERR_load_SSL_strings(void) +{ - /* panic and try to clear out nodes */ - wc_ClearErrorNodes(); - } - return (unsigned long)ret; - #else - (void)file; - (void)line; +} +#endif +#ifdef HAVE_OCSP +long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp) +{ + if (s == NULL || resp == NULL) return 0; - #endif - } - -#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"; + *resp = s->ocspResp; + return s->ocspRespSz; +} - /* 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 */ +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; - void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file, - int line) - { - WOLFSSL_ENTER("wolfSSL_ERR_put_error"); + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_OCSP */ - #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; - } +#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; + 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; - /* 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; + return wolfSSL_UseMaxFragment(s, mode); +} +#endif /* NO_WOLFSSL_CLIENT */ +#endif /* HAVE_MAX_FRAGMENT */ - WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data"); +#endif /* OPENSSL_EXTRA */ - if (flags != NULL) - *flags = ERR_TXT_STRING; /* Clear the flags */ +#ifdef WOLFSSL_HAVE_TLS_UNIQUE +size_t wolfSSL_get_finished(const WOLFSSL *ssl, void *buf, size_t count) +{ + byte len = 0; - 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 */ + WOLFSSL_ENTER("wolfSSL_get_finished"); - /* panic and try to clear out nodes */ - wc_ClearErrorNodes(); - } + if (!ssl || !buf || count < TLS_FINISHED_SZ) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } - 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 + 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; +} -#endif /* 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"); + if (!ssl || !buf || count < TLS_FINISHED_SZ) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } -#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; + if (ssl->options.side == WOLFSSL_CLIENT_END) { + len = ssl->serverFinished_len; + XMEMCPY(buf, ssl->serverFinished, len); + } + else { + len = ssl->clientFinished_len; + XMEMCPY(buf, ssl->clientFinished, len); + } - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_DCERT); - if (cert == NULL) - return MEMORY_E; - #endif - - /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object. - */ - InitDecodedCert(cert, (byte*)in, len, NULL); - if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) { - /* 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 + return len; +} +#endif /* WOLFSSL_HAVE_TLS_UNIQUE */ - return ret; +#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 /* (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); - } - } + return ssl->peerVerifyRet; +} #endif - } - WOLFSSL_LEAVE("wolfSSL_get_peer_certificate", ret != NULL); - return ret; - } -#endif /* KEEP_PEER_CERT */ +#ifdef OPENSSL_EXTRA -#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) +#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_ENTER("wolfSSL_get_peer_cert_chain"); - - if (ssl == NULL) - return NULL; - - /* 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; + WOLFSSL_STUB("wolfSSL_CTX_sess_accept"); + (void)ctx; + return 0; } +#endif -#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) +#ifndef NO_WOLFSSL_STUB +/* shows the number of connects attempted CTX in it's lifetime */ +long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) { - 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]); - } - } - return ret; + WOLFSSL_STUB("wolfSSL_CTX_sess_connect"); + (void)ctx; + return 0; } -#endif /* !WOLFSSL_QT */ +#endif -/* 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) + +#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_STACK* sk; - WOLFSSL_X509* x509; - int i = 0; - int ret; + WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good"); + (void)ctx; + return 0; +} +#endif - WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain"); - if ((ssl == NULL) || (ssl->session->chain.count == 0)) - return NULL; - 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; - } - } +#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 (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; - } - } - if (sk == NULL) { - WOLFSSL_MSG("Null session chain"); - } -#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; +#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 /* SESSION_CERTS && OPENSSL_EXTRA */ +#endif -#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) +#ifndef NO_WOLFSSL_STUB +/* shows the number of renegotiation accepts attempted by CTX */ +long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx) { - WOLFSSL_STACK* sk; - WOLFSSL_ENTER("wolfSSL_sk_new_node"); + WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate"); + (void)ctx; + return 0; +} +#endif - sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap, - DYNAMIC_TYPE_OPENSSL); - if (sk != NULL) { - XMEMSET(sk, 0, sizeof(*sk)); - sk->heap = heap; - } - return sk; +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_hits"); + (void)ctx; + return 0; } +#endif -/* free's node but does not free internal data such as in->data.x509 */ -void wolfSSL_sk_free_node(WOLFSSL_STACK* in) + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx) { - if (in != NULL) { - XFREE(in, in->heap, DYNAMIC_TYPE_OPENSSL); - } + WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits"); + (void)ctx; + return 0; } +#endif -/* 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) + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx) { - if (stack == NULL || in == NULL) { - return WOLFSSL_FAILURE; - } + WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full"); + (void)ctx; + return 0; +} +#endif - if (*stack == NULL) { - in->num = 1; - *stack = in; - return WOLFSSL_SUCCESS; + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_misses"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts"); + (void)ctx; + return 0; +} +#endif + +#ifndef NO_CERTS + +long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg) +{ + if (ctx == NULL || ctx->cm == NULL) { + return WOLFSSL_FAILURE; } - in->num = (*stack)->num + 1; - in->next = *stack; - *stack = in; + ctx->cm->ocspIOCtx = arg; return WOLFSSL_SUCCESS; } -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) -static WC_INLINE int compare_WOLFSSL_CIPHER( - WOLFSSL_CIPHER *a, - WOLFSSL_CIPHER *b) +#endif /* !NO_CERTS */ + +int wolfSSL_get_read_ahead(const WOLFSSL* ssl) { - 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; + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + return ssl->readAhead; } -#endif /* OPENSSL_ALL || WOLFSSL_QT */ -/* return 1 on success 0 on fail */ -int wolfSSL_sk_push(WOLFSSL_STACK* sk, const void *data) +int wolfSSL_set_read_ahead(WOLFSSL* ssl, int v) { - WOLFSSL_STACK* node; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - WOLFSSL_CIPHER ciph; -#endif - WOLFSSL_ENTER("wolfSSL_sk_push"); + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } - if (!sk) { + ssl->readAhead = (byte)v; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) { return WOLFSSL_FAILURE; } - /* 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; + return ctx->readAhead; +} + + +int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; } - /* 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"); + ctx->readAhead = (byte)v; + + return WOLFSSL_SUCCESS; +} + + +long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx, + void* arg) +{ + if (ctx == NULL) { return WOLFSSL_FAILURE; } - /* push new x509 onto head of stack */ - node->next = sk->next; - node->type = sk->type; - sk->next = node; - sk->num += 1; + ctx->userPRFArg = arg; + return WOLFSSL_SUCCESS; +} + +#endif /* OPENSSL_EXTRA */ + +#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"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + if (sk == NULL) + return NULL; -#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: + 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: - /* 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; + return (void*)sk->data.generic; } - - return WOLFSSL_SUCCESS; } -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +/* copies over data of "in" to "out" */ +static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out) +{ + if (in == NULL || out == NULL) + return; -#ifdef OPENSSL_EXTRA + *out = *in; +} -/* returns the node at index "idx", NULL if not found */ -WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx) +WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk) { - int i; + WOLFSSL_STACK* ret = NULL; - WOLFSSL_STACK* current; + WOLFSSL_STACK* last = NULL; - current = sk; - for (i = 0; i <= idx && current != NULL; i++) { - if (i == idx) { - ret = current; - break; - } - current = current->next; - } - return ret; -} - - -#endif /* OPENSSL_EXTRA */ - -#ifdef OPENSSL_EXTRA + WOLFSSL_ENTER("wolfSSL_sk_dup"); -#if defined(OPENSSL_ALL) + while (sk) { + WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap); -void *wolfSSL_lh_retrieve(WOLFSSL_STACK *sk, void *data) -{ - unsigned long hash; + if (!cur) { + WOLFSSL_MSG("wolfSSL_sk_new_node error"); + goto error; + } - WOLFSSL_ENTER("wolfSSL_lh_retrieve"); + if (!ret) { + /* Set first node */ + ret = cur; + } - if (!sk || !data) { - WOLFSSL_MSG("Bad parameters"); - return NULL; - } + if (last) { + last->next = cur; + } - if (!sk->hash_fn) { - WOLFSSL_MSG("No hash function defined"); - return NULL; - } + XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK)); - hash = sk->hash_fn(data); + /* We will allocate new memory for this */ + XMEMSET(&cur->data, 0, sizeof(cur->data)); + cur->next = NULL; - 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); + switch (sk->type) { + case STACK_TYPE_X509: + if (!sk->data.x509) 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); + 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; - } - } - 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; - } + 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 /* OPENSSL_ALL */ - -#endif /* OPENSSL_EXTRA */ -/* 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) +WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* sk) { - if (ssl == NULL) { - return NULL; - } - 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; + WOLFSSL_STACK* ret = NULL; + WOLFSSL_STACK** prev = &ret; + + WOLFSSL_ENTER("wolfSSL_shallow_sk_dup"); + + 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; } -WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx) +/* Free the just the stack structure */ +void wolfSSL_sk_free(WOLFSSL_STACK* sk) { - 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; + WOLFSSL_ENTER("wolfSSL_sk_free"); + + while (sk != NULL) { + WOLFSSL_STACK* next = sk->next; + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); + sk = next; } - return NULL; } -#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */ -#endif /* NO_CERTS */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -void wolfSSL_set_connect_state(WOLFSSL* ssl) +/* Frees each node in the stack and frees the stack. + */ +void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, + void (*f) (void*)) { - WOLFSSL_ENTER("wolfSSL_set_connect_state"); - if (ssl == NULL) { - WOLFSSL_MSG("WOLFSSL struct pointer passed in was null"); - return; - } + WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free"); + wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f); +} - #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 +/* return 1 on success 0 on fail */ +int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic) +{ + WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push"); - if (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error initializing client side"); - } + return wolfSSL_sk_push(sk, generic); +} +void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk) +{ + wolfSSL_sk_free(sk); } -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - -int wolfSSL_get_shutdown(const WOLFSSL* ssl) +/* 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) { - int isShutdown = 0; + WOLFSSL_STACK* node; + void* data = NULL; - WOLFSSL_ENTER("wolfSSL_get_shutdown"); + /* 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; - 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; + /* 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 -#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; + 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; + } } - WOLFSSL_LEAVE("wolfSSL_get_shutdown", isShutdown); - return isShutdown; -} - - -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; + return data; } -/* return a new malloc'd session with default settings on success */ -WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) +/* 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_SESSION* ret = NULL; - - WOLFSSL_ENTER("wolfSSL_NewSession"); + WOLFSSL_ENTER("wolfSSL_sk_pop_free"); - 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; + 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 -#ifndef NO_SESSION_CACHE - ret->cacheRow = INVALID_SESSION_ROW; /* not in cache */ + 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 - 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); + 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 - #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); - } + 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; + } } - return ret; -} + while (sk != NULL) { + WOLFSSL_STACK* next = sk->next; -WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap) -{ - return wolfSSL_NewSession(heap); + if (func != NULL) { + if (sk->type != STACK_TYPE_CIPHER) + func(sk->data.generic); + } + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); + sk = next; + } } -WOLFSSL_SESSION* wolfSSL_SESSION_new(void) +/* 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) { - return wolfSSL_SESSION_new_ex(NULL); + WOLFSSL_STACK* sk; + + /* 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; } -/* add one to session reference count - * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */ -int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) +/* Creates and returns a new null stack. */ +WOLFSSL_STACK* wolfSSL_sk_new_null(void) { - int ret; + WOLFSSL_ENTER("wolfSSL_sk_new_null"); - session = ClientSessionToSession(session); + return wolfssl_sk_new_type(STACK_TYPE_NULL); +} - if (session == NULL || session->type != WOLFSSL_SESSION_TYPE_HEAP) - return WOLFSSL_FAILURE; +int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk) +{ + if (sk == NULL) + return 0; + return (int)sk->num; +} - 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 +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - return WOLFSSL_SUCCESS; -} +#ifdef OPENSSL_EXTRA -/** - * 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) +#if defined(HAVE_EX_DATA) && !defined(NO_FILESYSTEM) +int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) { -#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; + int ret = WOLFSSL_FATAL_ERROR; - input = ClientSessionToSession(input); - output = ClientSessionToSession(output); + 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 (input == NULL || output == NULL || input == output) { - WOLFSSL_MSG("input or output are null or same"); - return WOLFSSL_FAILURE; - } + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) + return WOLFSSL_BAD_FILE; -#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; + if (XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; } - - 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; + sz = XFTELL(file); + if (XFSEEK(file, 0, XSEEK_SET) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; } - 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; - } + if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + WOLFSSL_MSG("cmp_peer_cert_to_file size error"); + XFCLOSE(file); + return WOLFSSL_BAD_FILE; } - /* 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; + + if (sz > (long)sizeof(staticBuffer)) { + WOLFSSL_MSG("Getting dynamic buffer"); + myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); + dynamic = 1; } - else { - WOLFSSL_MSG("TicketNonce bigger than static buffer, and we can't " - "do syscalls"); - ret = WOLFSSL_FAILURE; + + 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; } - } -#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ -#endif /* HAVE_SESSION_TICKET */ + FreeDer(&fileDer); -#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); + if (dynamic) + XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); + + XFCLOSE(file); } -#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 +#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"}, - 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 + /* oidCertAuthInfoType */ + { NID_ad_OCSP, AIA_OCSP_OID, oidCertAuthInfoType, "OCSP", + "OCSP"}, + { NID_ad_ca_issuers, AIA_CA_ISSUER_OID, oidCertAuthInfoType, + "caIssuers", "CA Issuers"}, -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS - wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); -#endif + /* oidCertPolicyType */ + { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy", + "X509v3 Any Policy"}, -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (session->peer) { - wolfSSL_X509_free(session->peer); - session->peer = NULL; - } -#endif + /* oidCertAltNameType */ + { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""}, -#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 + /* 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"}, -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS - wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); + /* 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"}, - /* 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); -} - -#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, +#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 - NULL); - - return error == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; -} #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 */ -#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 */ - - -/* 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"); + /* 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 */ - if (version == NULL) { - return "Bad arg"; - } + /* 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"}, - 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"; -} + #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 -const char* wolfSSL_get_version(const WOLFSSL* ssl) -{ - if (ssl == NULL) { - WOLFSSL_MSG("Bad argument"); - return "unknown"; - } + /* 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 */ - return wolfSSL_internal_get_version(&ssl->version); -} + #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 -/* current library version */ -const char* wolfSSL_lib_version(void) -{ - return LIBWOLFSSL_VERSION_STRING; -} + /* 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 -#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 + #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 }, -/* current library version in hex */ -word32 wolfSSL_lib_version_hex(void) + /* "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) { - return LIBWOLFSSL_VERSION_HEX; + WOLFSSL_MSG("wolfSSL_OPENSSL_free"); + + XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); } +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#ifdef OPENSSL_EXTRA -int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl) +void *wolfSSL_OPENSSL_malloc(size_t a) { - WOLFSSL_ENTER("wolfSSL_get_current_cipher_suite"); - if (ssl) - return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite; - return 0; + return (void *)XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL); } -WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl) +int wolfSSL_OPENSSL_hexchar2int(unsigned char c) { - 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; + /* 'char' is unsigned on some platforms. */ + return (int)(signed char)HexCharToByte((char)c); } - -const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher) +unsigned char *wolfSSL_OPENSSL_hexstr2buf(const char *str, long *len) { - WOLFSSL_ENTER("wolfSSL_CIPHER_get_name"); + unsigned char* targetBuf; + int srcDigitHigh = 0; + int srcDigitLow = 0; + size_t srcLen; + size_t srcIdx = 0; + long targetIdx = 0; - if (cipher == NULL) { + srcLen = XSTRLEN(str); + targetBuf = (unsigned char*)XMALLOC(srcLen / 2, NULL, DYNAMIC_TYPE_OPENSSL); + if (targetBuf == NULL) { return NULL; } - #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 -} + while (srcIdx < srcLen) { + if (str[srcIdx] == ':') { + srcIdx++; + continue; + } -const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher) -{ - WOLFSSL_ENTER("wolfSSL_CIPHER_get_version"); + 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; + } - if (cipher == NULL || cipher->ssl == NULL) { - return NULL; + targetBuf[targetIdx++] = (unsigned char)((srcDigitHigh << 4) | + srcDigitLow ); } - return wolfSSL_get_version(cipher->ssl); -} - -const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session) -{ - session = ClientSessionToSession(session); - if (session == NULL) { - return NULL; - } + if (len != NULL) + *len = targetIdx; -#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 targetBuf; } -const char* wolfSSL_get_cipher(WOLFSSL* ssl) +int wolfSSL_OPENSSL_init_ssl(word64 opts, const OPENSSL_INIT_SETTINGS *settings) { - WOLFSSL_ENTER("wolfSSL_get_cipher"); - return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)); + (void)opts; + (void)settings; + return wolfSSL_library_init(); } -/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */ -const char* wolfSSL_get_cipher_name(WOLFSSL* ssl) +int wolfSSL_OPENSSL_init_crypto(word64 opts, + const OPENSSL_INIT_SETTINGS* settings) { - /* get access to cipher_name_idx in internal.c */ - return wolfSSL_get_cipher_name_internal(ssl); + (void)opts; + (void)settings; + return wolfSSL_library_init(); } -const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0, - const byte cipherSuite) +/* Colon separated list of + algorithms. + * Replaces list in context. + */ +int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, const char* list) { - return GetCipherNameInternal(cipherSuite0, cipherSuite); -} + WOLFSSL_MSG("wolfSSL_CTX_set1_sigalg_list"); -const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0, - const byte cipherSuite) -{ - return GetCipherNameIana(cipherSuite0, cipherSuite); -} + if (ctx == NULL || list == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } -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); -} + if (AllocateCtxSuites(ctx) != 0) + return WOLFSSL_FAILURE; + return SetSuitesHashSigAlgo(ctx->suites, list); +} -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) -/* Creates and returns a new WOLFSSL_CIPHER stack. */ -WOLFSSL_STACK* wolfSSL_sk_new_cipher(void) +/* Colon separated list of + algorithms. + * Replaces list in SSL. + */ +int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list) { - WOLFSSL_STACK* sk; - WOLFSSL_ENTER("wolfSSL_sk_new_cipher"); - - sk = wolfSSL_sk_new_null(); - if (sk == NULL) - return NULL; - sk->type = STACK_TYPE_CIPHER; + WOLFSSL_MSG("wolfSSL_set1_sigalg_list"); - return sk; -} + if (ssl == NULL || list == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } -/* 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); -} + if (AllocateSuites(ssl) != 0) + return WOLFSSL_FAILURE; -#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; + return SetSuitesHashSigAlgo(ssl->suites, list); } -#endif /* NO_WOLFSSL_STUB */ -#endif /* WOLFSSL_QT || OPENSSL_ALL */ -word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher) +static int HashToNid(byte hashAlgo, int* nid) { - word16 cipher_id = 0; - - WOLFSSL_ENTER("wolfSSL_CIPHER_get_id"); + int ret = WOLFSSL_SUCCESS; - if (cipher && cipher->ssl) { - cipher_id = (cipher->ssl->options.cipherSuite0 << 8) | - cipher->ssl->options.cipherSuite; + /* 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 cipher_id; + return ret; } -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"); - - /* extract cipher id information */ - cipherSuite = (value & 0xFF); - cipherSuite0 = ((value >> 8) & 0xFF); - - /* TODO: lookup by cipherSuite0 / cipherSuite */ - (void)cipherSuite0; - (void)cipherSuite; - - return cipher; -} - - -#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"); - - wolfSSL_sk_free(sk); -} -#endif /* OPENSSL_ALL */ - -#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \ - !defined(NO_DH) -#ifdef HAVE_FFDHE -static const char* wolfssl_ffdhe_name(word16 group) +static int SaToNid(byte sa, int* nid) { - const char* str = NULL; - switch (group) { - case WOLFSSL_FFDHE_2048: - str = "FFDHE_2048"; + 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 WOLFSSL_FFDHE_3072: - str = "FFDHE_3072"; + case rsa_sa_algo: + *nid = NID_rsaEncryption; break; - case WOLFSSL_FFDHE_4096: - str = "FFDHE_4096"; + case dsa_sa_algo: + *nid = NID_dsa; break; - case WOLFSSL_FFDHE_6144: - str = "FFDHE_6144"; + case ecc_dsa_sa_algo: + *nid = NID_X9_62_id_ecPublicKey; break; - case WOLFSSL_FFDHE_8192: - str = "FFDHE_8192"; + 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 str; + return ret; } -#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) + +/* This API returns the hash selected. */ +int wolfSSL_get_signature_nid(WOLFSSL *ssl, int* nid) { - const char* cName = NULL; + WOLFSSL_MSG("wolfSSL_get_signature_nid"); - WOLFSSL_ENTER("wolfSSL_get_curve_name"); + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } - if (ssl == NULL) - return NULL; + return HashToNid(ssl->options.hashAlgo, nid); +} -#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 - } - } +/* This API returns the signature selected. */ +int wolfSSL_get_signature_type_nid(const WOLFSSL* ssl, int* nid) +{ + WOLFSSL_MSG("wolfSSL_get_signature_type_nid"); -#endif /* WOLFSSL_TLS13 && HAVE_PQC */ -#ifdef HAVE_FFDHE - if (ssl->namedGroup != 0) { - cName = wolfssl_ffdhe_name(ssl->namedGroup); + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; } -#endif -#ifdef HAVE_CURVE25519 - if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) { - cName = "X25519"; - } -#endif + return SaToNid(ssl->options.sigAlgo, nid); +} -#ifdef HAVE_CURVE448 - if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) { - cName = "X448"; - } -#endif +int wolfSSL_get_peer_signature_nid(WOLFSSL* ssl, int* nid) +{ + WOLFSSL_MSG("wolfSSL_get_peer_signature_nid"); -#ifdef HAVE_ECC - if (ssl->ecdhCurveOID != 0 && cName == NULL) { - cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, - NULL)); + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; } -#endif - return cName; + return HashToNid(ssl->options.peerHashAlgo, nid); } -#endif -#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) +int wolfSSL_get_peer_signature_type_nid(const WOLFSSL* ssl, int* nid) { - 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}}; + WOLFSSL_MSG("wolfSSL_get_peer_signature_type_nid"); - if (GetCipherSegment(cipher, n) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; } - authStr = GetCipherAuthStr(n); + return SaToNid(ssl->options.peerSigAlgo, nid); +} - 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; - } - } - } +#ifdef HAVE_ECC - 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) +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) +static int populate_groups(int* groups, int max_count, const char *list) { - 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"); + const char *end; + int count = 0; + const WOLF_EC_NIST_NAME* nist_name; - if (GetCipherSegment(cipher, n) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; + if (!groups || !list) { + return -1; } - encStr = GetCipherEncStr(n); + for (end = list; ; list = ++end) { + int len; - 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; + 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 NID_undef; + return count; } -/* 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} - }; - - const char* name; - const char* macStr; - char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; - (void)name; - WOLFSSL_ENTER("wolfSSL_CIPHER_get_digest_nid"); +int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, const char *list) +{ + int groups[WOLFSSL_MAX_GROUP_COUNT]; + int count = 0; - if ((name = GetCipherSegment(cipher, n)) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; + if (!ctx || !list) { + return WOLFSSL_FAILURE; } - /* in MD5 case, NID will be NID_md5 */ - if (XSTRSTR(name, "MD5") != NULL) { - return NID_md5; + if ((count = populate_groups(groups, + WOLFSSL_MAX_GROUP_COUNT, list)) == -1) { + return WOLFSSL_FAILURE; } - macStr = GetCipherMacStr(n); + return wolfSSL_CTX_set1_groups(ctx, groups, count); +} - 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; - } - } +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; } - return NID_undef; + if ((count = populate_groups(groups, + WOLFSSL_MAX_GROUP_COUNT, list)) == -1) { + return WOLFSSL_FAILURE; + } + + return wolfSSL_set1_groups(ssl, groups, count); } -/* 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} - }; +#endif /* WOLFSSL_TLS13 */ - const char* keaStr; - char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; +#endif /* HAVE_ECC */ - WOLFSSL_ENTER("wolfSSL_CIPHER_get_kx_nid"); +#endif /* OPENSSL_EXTRA */ - if (GetCipherSegment(cipher, n) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; - } +#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 */ - /* in TLS 1.3 case, NID will be NID_kx_any */ - if (XSTRCMP(n[0], "TLS13") == 0) { - return NID_kx_any; - } - keaStr = GetCipherKeaStr(n); +#ifdef SESSION_CERTS - if (keaStr != NULL) { - const struct kxnid* k; - for(k = kxnid_table; k->name != NULL; k++) { - if (XSTRCMP(k->name, keaStr) == 0) { - return k->nid; - } - } - } +#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 NID_undef; + return 0; } -/* 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}}; +#endif /* WOLFSSL_ALT_CERT_CHAINS */ - WOLFSSL_ENTER("wolfSSL_CIPHER_is_aead"); - if (GetCipherSegment(cipher, n) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; - } +/* 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 IsCipherAEAD(n); + return 0; } -/* 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"); - if (cipher == NULL) - return WOLFSSL_FAILURE; - dp = cipher->description; - if (dp == NULL) - return WOLFSSL_FAILURE; +/* 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; - cipher_names = GetCipherNames(); + return 0; +} - 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 ((name = GetCipherSegment(cipher, n)) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return WOLFSSL_FAILURE; - } +/* 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; - /* 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 0; +} - /* 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; - - 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; +/* 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; - 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 0; +} - 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; - 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; +/* 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 - XSTRNCPY(dp, " Mac=", len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; - XSTRNCPY(dp, macStr, len); - dp[len-1] = '\0'; + 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); - return WOLFSSL_SUCCESS; -} -#endif /* OPENSSL_ALL || WOLFSSL_QT */ + 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); -static WC_INLINE const char* wolfssl_kea_to_string(int kea) -{ - const char* keaStr; + if ((ret = CopyDecodedToX509(x509, cert)) != 0) { + WOLFSSL_MSG("Failed to copy decoded"); + wolfSSL_X509_free(x509); + x509 = NULL; + } + } + } - 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; + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + } } + (void)ret; - return keaStr; + return x509; } -static WC_INLINE const char* wolfssl_sigalg_to_string(int sig_algo) + +/* 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) { - const char* authStr; +#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; - 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; + 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; } - return authStr; -} + /* don't even try if inLen too short */ + if (inLen < headerLen + footerLen + chain->certs[idx].length) + return BAD_FUNC_ARG; -static WC_INLINE const char* wolfssl_cipher_to_string(int cipher, int key_size) -{ - const char* encStr; + /* header */ + if (XMEMCPY(buf, header, headerLen) == NULL) + return WOLFSSL_FATAL_ERROR; - (void)key_size; + i = headerLen; - 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 encStr; -} - -static WC_INLINE const char* wolfssl_mac_to_string(int mac) -{ - const char* macStr; + /* 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; - 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; - } + /* footer */ + if ( (i + footerLen) > inLen) + return BAD_FUNC_ARG; + if (XMEMCPY(buf + i, footer, footerLen) == NULL) + return WOLFSSL_FATAL_ERROR; + *outLen += headerLen + footerLen; - return macStr; + 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 */ } -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"); - - if (cipher == NULL || in == NULL) - return NULL; +#endif /* SESSION_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; +#ifdef HAVE_FUZZER +void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx) +{ + if (ssl) { + ssl->fuzzerCb = cbf; + ssl->fuzzerCtx = fCtx; } +} #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'; +#ifndef NO_CERTS +#ifdef HAVE_PK_CALLBACKS - return ret; +#ifdef HAVE_ECC +void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb) +{ + if (ctx) + ctx->EccKeyGenCb = cb; } - - -#ifndef NO_WOLFSSL_STUB -int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, - int* ssl) +void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx) { - (void)url; - (void)host; - (void)port; - (void)path; - (void)ssl; - WOLFSSL_STUB("OCSP_parse_url"); - return 0; + if (ssl) + ssl->EccKeyGenCtx = ctx; } -#endif +void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccKeyGenCtx; -#ifndef NO_WOLFSSL_STUB -void wolfSSL_RAND_screen(void) + return NULL; +} +void wolfSSL_CTX_SetEccSignCtx(WOLFSSL_CTX* ctx, void *userCtx) { - WOLFSSL_STUB("RAND_screen"); + if (ctx) + ctx->EccSignCtx = userCtx; } -#endif - +void* wolfSSL_CTX_GetEccSignCtx(WOLFSSL_CTX* ctx) +{ + if (ctx) + return ctx->EccSignCtx; + return NULL; +} -int wolfSSL_RAND_load_file(const char* fname, long len) +WOLFSSL_ABI +void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb) { - (void)fname; - /* wolfCrypt provides enough entropy internally or will report error */ - if (len == -1) - return 1024; - else - return (int)len; + if (ctx) + ctx->EccSignCb = cb; } - - -#ifndef NO_WOLFSSL_STUB -WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void) +void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx) { - WOLFSSL_STUB("COMP_zlib"); - return 0; + if (ssl) + ssl->EccSignCtx = ctx; } -#endif - -#ifndef NO_WOLFSSL_STUB -WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) +void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl) { - WOLFSSL_STUB("COMP_rle"); - return 0; + if (ssl) + return ssl->EccSignCtx; + + return NULL; } -#endif -#ifndef NO_WOLFSSL_STUB -int wolfSSL_COMP_add_compression_method(int method, void* data) +void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb) { - (void)method; - (void)data; - WOLFSSL_STUB("COMP_add_compression_method"); - return 0; + if (ctx) + ctx->EccVerifyCb = 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)) +void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx) { - WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback"); - (void)f; + if (ssl) + ssl->EccVerifyCtx = ctx; } -/* 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)) +void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl) { - WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback"); - (void)f; + if (ssl) + return ssl->EccVerifyCtx; + + return NULL; } -/* 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_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, + CallbackEccSharedSecret cb) { - WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback"); - (void)f; + 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 */ -#endif /* OPENSSL_EXTRA */ +#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; -#ifdef OPENSSL_EXTRA -#ifndef NO_CERTS + return NULL; +} -#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_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb) { - return wolfSSL_EVP_PKEY_get_der(key, der); + if (ctx) + ctx->Ed25519VerifyCb = cb; } - -int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der) +void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx) { -#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; + if (ssl) + ssl->Ed25519VerifyCtx = ctx; +} +void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519VerifyCtx; - if (key == NULL) { - return WOLFSSL_FATAL_ERROR; - } + return NULL; +} +#endif /* HAVE_ED25519 */ - key_type = key->type; - if ((key_type != EVP_PKEY_EC) && (key_type != EVP_PKEY_RSA)) { - return WOLFSSL_FATAL_ERROR; - } +#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; -#ifndef NO_RSA - if (key_type == EVP_PKEY_RSA) { - return wolfSSL_i2d_RSAPublicKey(key->rsa, der); - } -#endif + return NULL; +} - /* Now that RSA is taken care of, we only need to consider the ECC case. */ +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; -#ifdef HAVE_ECC + return NULL; +} +#endif /* HAVE_CURVE25519 */ - /* 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; - } +#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 (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; - } - } + return NULL; +} - if (ret == 0) { - ret = wc_ecc_init(eccKey); - } +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; - 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); - } - } + return NULL; +} +#endif /* HAVE_ED448 */ - if (ret == 0) { - pub_derSz = wc_EccPublicKeyDerSize(eccKey, 0); - if ((int)pub_derSz <= 0) { - ret = WOLFSSL_FAILURE; - } - } +#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; - 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 (ret == 0) { - pub_derSz = wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 0); - if ((int)pub_derSz <= 0) { - ret = WOLFSSL_FATAL_ERROR; - } - } - - /* 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 (ret == 0) { - XMEMCPY(*der, pub_der, pub_derSz); - } - } - else { - XMEMCPY(*der, pub_der, pub_derSz); - *der += pub_derSz; - } - } - - XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(local_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - - wc_ecc_free(eccKey); - XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC); + return NULL; +} -#else - ret = WOLFSSL_FATAL_ERROR; -#endif /* HAVE_ECC */ +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 (ret == 0) { - return pub_derSz; - } + return NULL; +} +#endif /* HAVE_CURVE448 */ - return ret; -#else - return WOLFSSL_FATAL_ERROR; -#endif /* !NO_RSA || HAVE_ECC */ +#ifndef NO_RSA +void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb) +{ + if (ctx) + ctx->RsaSignCb = cb; } -#endif /* !NO_ASN && !NO_PWDBASED */ +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; -#endif /* !NO_CERTS */ -#endif /* OPENSSL_EXTRA */ + return NULL; +} -#ifdef OPENSSL_EXTRA -/* Sets the DNS hostname to name. - * Hostname is cleared if name is NULL or empty. */ -int wolfSSL_set1_host(WOLFSSL * ssl, const char* name) +void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) { - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } - - return wolfSSL_X509_VERIFY_PARAM_set1_host(ssl->param, name, 0); + if (ctx) + ctx->RsaVerifyCb = cb; } - -/****************************************************************************** -* 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) +void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx) { - if (ctx == NULL || vpm == NULL) - return WOLFSSL_SUCCESS; - - return wolfSSL_X509_VERIFY_PARAM_set1(ctx->param, vpm); + if (ssl) + ssl->RsaVerifyCtx = ctx; } - -/****************************************************************************** -* 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) +void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl) { - if (ctx == NULL) { - return NULL; - } + if (ssl) + return ssl->RsaVerifyCtx; - return ctx->param; + return NULL; } -WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl) +#ifdef WC_RSA_PSS +void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb) { - if (ssl == NULL) { - return NULL; - } - return ssl->param; + 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; -#endif /* OPENSSL_EXTRA */ + return NULL; +} -#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) +void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb) { - WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx"); + 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; - /* store SSL at index 0 */ - return 0; + return NULL; } -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +#endif /* WC_RSA_PSS */ -#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)) +void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb) { - WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback"); - if (ctx == NULL) { - WOLFSSL_MSG("Bad function argument"); - } - else { - ctx->CBIS = f; - } + if (ctx) + ctx->RsaEncCb = cb; } - -void wolfSSL_set_info_callback(WOLFSSL* ssl, - void (*f)(const WOLFSSL* ssl, int type, int val)) +void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx) { - WOLFSSL_ENTER("wolfSSL_set_info_callback"); - if (ssl == NULL) { - WOLFSSL_MSG("Bad function argument"); - } - else { - ssl->CBIS = f; - } + if (ssl) + ssl->RsaEncCtx = ctx; } +void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaEncCtx; + return NULL; +} -unsigned long wolfSSL_ERR_peek_error(void) +void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb) { - WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); + 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 wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL); + return NULL; } +#endif /* NO_RSA */ -int wolfSSL_ERR_GET_LIB(unsigned long err) +/* callback for premaster secret generation */ +void wolfSSL_CTX_SetGenPreMasterCb(WOLFSSL_CTX* ctx, CallbackGenPreMaster cb) { - unsigned long value; - - 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; - } + if (ctx) + ctx->GenPreMasterCb = cb; } - -/* 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) +/* Set premaster secret generation callback context */ +void wolfSSL_SetGenPreMasterCtx(WOLFSSL* ssl, void *ctx) { - int ret = (int)err; - - WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON"); + if (ssl) + ssl->GenPreMasterCtx = ctx; +} +/* Get premaster secret generation callback context */ +void* wolfSSL_GetGenPreMasterCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->GenPreMasterCtx; -#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 NULL; +} - /* 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; - } +/* 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 ret; + return NULL; } -/* returns a string that describes the alert - * - * alertID the alert value to look up - */ -const char* wolfSSL_alert_type_string_long(int alertID) +/* callback for session key generation */ +void wolfSSL_CTX_SetGenSessionKeyCb(WOLFSSL_CTX* ctx, CallbackGenSessionKey cb) { - WOLFSSL_ENTER("wolfSSL_alert_type_string_long"); + 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 AlertTypeToString(alertID); + 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; +} -const char* wolfSSL_alert_desc_string_long(int alertID) +/* 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) { - WOLFSSL_ENTER("wolfSSL_alert_desc_string_long"); + 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 AlertTypeToString(alertID); + 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; } -#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}, \ - } +/* 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; -#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}, \ - } + return NULL; +} +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ -/* 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) +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 */ - 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 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; - enum IOMode { - SS_READ = 0, - SS_WRITE, - SS_NEITHER - }; + return NULL; +} +#endif /* HAVE_PK_CALLBACKS && !NO_DH */ - 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 - }; +#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_HKDF) - int protocol = 0; - int cbmode = 0; - int state = 0; +void wolfSSL_CTX_SetHKDFExtractCb(WOLFSSL_CTX* ctx, CallbackHKDFExtract cb) +{ + if (ctx) + ctx->HkdfExtractCb = cb; +} - WOLFSSL_ENTER("wolfSSL_state_string_long"); - if (ssl == NULL) { - WOLFSSL_MSG("Null argument passed in"); - return NULL; - } +void wolfSSL_SetHKDFExtractCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->HkdfExtractCtx = ctx; +} - /* 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; +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) + + /* 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); } - /* 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; + + 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; } - 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; + } + 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; } - 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; + oid = OidFromId(id, type, &oidSz); - 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; + /* 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; - if (protocol == UNKNOWN) { - WOLFSSL_MSG("Unknown protocol"); - return ""; - } - else { - return OUTPUT_STR[state][protocol][cbmode]; - } -} + obj->sName[0] = '\0'; + if (sName != NULL) { + XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName)); + } -/* - * 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"); + objBuf[0] = ASN_OBJECT_ID; objSz++; + objSz += SetLength(oidSz, objBuf + 1); + if (oidSz) { + XMEMCPY(objBuf + objSz, oid, oidSz); + objSz += oidSz; + } - /* 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 (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); -#endif /* OPENSSL_EXTRA */ + (void)type; -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"); + return obj; } - /* 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"); - } + 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; - if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) { - WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); + for (idx = oid_dict; idx->num != NULL; idx++) { + if (!XSTRCMP(oid, idx->num)) { + return idx->desc; + } + } + return NULL; } -#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"); - } -#endif + static int wolfssl_obj2txt_numeric(char *buf, int bufLen, + const WOLFSSL_ASN1_OBJECT *a) + { + int bufSz; + int length; + word32 idx = 0; + byte tag; - if ((op & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); - } + if (GetASNTag(a->obj, &idx, &tag, a->objSz) != 0) { + return WOLFSSL_FAILURE; + } - if ((op & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1"); - } + if (tag != ASN_OBJECT_ID) { + WOLFSSL_MSG("Bad ASN1 Object"); + return WOLFSSL_FAILURE; + } - if ((op & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); - } + if (GetLength((const byte*)a->obj, &idx, &length, + a->objSz) < 0 || length < 0) { + return ASN_PARSE_E; + } - if ((op & WOLFSSL_OP_NO_SSLv3) == WOLFSSL_OP_NO_SSLv3) { - WOLFSSL_MSG("\tSSL_OP_NO_SSLv3"); - } + if (bufLen < MAX_OID_STRING_SZ) { + bufSz = bufLen - 1; + } + else { + bufSz = MAX_OID_STRING_SZ; + } - if ((op & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) == - WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) { - WOLFSSL_MSG("\tWOLFSSL_OP_CIPHER_SERVER_PREFERENCE"); - } + if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx, + (word32)length)) <= 0) { + WOLFSSL_MSG("Error decoding OID"); + return WOLFSSL_FAILURE; + } - 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 + buf[bufSz] = '\0'; + + return bufSz; } - return old_op | op; -} + /* 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; -long wolfSSL_set_options(WOLFSSL* ssl, long op) -{ - word16 haveRSA = 1; - word16 havePSK = 0; - int keySz = 0; + WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt"); - WOLFSSL_ENTER("wolfSSL_set_options"); + if (buf == NULL || bufLen <= 1 || a == NULL) { + WOLFSSL_MSG("Bad input argument"); + return WOLFSSL_FAILURE; + } - if (ssl == NULL) { - return 0; - } + if (no_name == 1) { + return wolfssl_obj2txt_numeric(buf, bufLen, a); + } - ssl->options.mask = wolf_set_options(ssl->options.mask, op); + /* 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 ((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 (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; + } - 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; - } + buf[bufSz] = '\0'; - 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; + return bufSz; } +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) { - if (ssl->version.minor == TLSv1_MINOR) - ssl->version.minor = SSLv3_MINOR; +#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 ((ssl->options.mask & WOLFSSL_OP_NO_COMPRESSION) - == WOLFSSL_OP_NO_COMPRESSION) { - #ifdef HAVE_LIBZ - ssl->options.usingCompression = 0; - #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) + /* 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 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; + 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; } -#endif - - /* 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; +#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 - if (ssl->options.side != WOLFSSL_NEITHER_END) { - if (AllocateSuites(ssl) != 0) - 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); - } + size_t wolfSSL_OBJ_length(const WOLFSSL_ASN1_OBJECT* o) + { + size_t ret = 0; + int err = 0; + word32 idx = 0; + int len = 0; - return ssl->options.mask; -} + WOLFSSL_ENTER("wolfSSL_OBJ_length"); + if (o == NULL || o->obj == NULL) { + WOLFSSL_MSG("Bad argument."); + err = 1; + } -long wolfSSL_get_options(const WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_options"); - if(ssl == NULL) - return WOLFSSL_FAILURE; - return ssl->options.mask; -} + if (err == 0 && GetASNObjectId(o->obj, &idx, &len, o->objSz)) { + WOLFSSL_MSG("Error parsing ASN.1 header."); + err = 1; + } + if (err == 0) { + ret = len; + } -#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; + WOLFSSL_LEAVE("wolfSSL_OBJ_length", (int)ret); - WOLFSSL_ENTER("wolfSSL_clear_num_renegotiations"); - if (s == NULL) - return 0; + return ret; + } - total = s->secure_rene_count; - s->secure_rene_count = 0; - return total; -} + 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"); -/* return the number of renegotiations since wolfSSL_new */ -long wolfSSL_total_renegotiations(WOLFSSL *s) -{ - WOLFSSL_ENTER("wolfSSL_total_renegotiations"); - return wolfSSL_num_renegotiations(s); -} + 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 the number of renegotiations since wolfSSL_new */ -long wolfSSL_num_renegotiations(WOLFSSL* s) -{ - if (s == NULL) { - return 0; + return ret; } - return s->secure_rene_count; -} - -/* 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 */ - -#ifdef OPENSSL_EXTRA + /* 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; -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 WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid"); +#endif -#ifdef HAVE_PK_CALLBACKS -long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) -{ - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } + if (o == NULL) { + return -1; + } - ssl->loggingCtx = arg; - return WOLFSSL_SUCCESS; -} -#endif /* HAVE_PK_CALLBACKS */ + #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 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; -} + 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; + } + } -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 oid2nid(oid, o->grp); } - return WOLFSSL_SUCCESS; -} + /* 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; -#endif + 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; + } -/*** 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 + /* 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"); -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST -long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) -{ - WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type"); + 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; + } + } + } + } - if (s == NULL){ - return BAD_FUNC_ARG; + 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 - 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_OBJ_txt2nid"); -} + if (s == NULL) { + return NID_undef; + } -long wolfSSL_get_tlsext_status_type(WOLFSSL *s) -{ - TLSX* extension; + #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 */ - 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 */ + /* 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 -#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 + /* 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; + } -/*** TBD ***/ -#ifndef NO_WOLFSSL_STUB -long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) -{ - (void)s; - (void)arg; - WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); - return WOLFSSL_FAILURE; -} -#endif - -/*** 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 - -/*** 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 + /* 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; + } + } -#ifndef NO_WOLFSSL_STUB -/*** TBD ***/ -WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) -{ - (void)ssl; - WOLFSSL_STUB("SSL_get_privatekey"); - return NULL; -} + 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) -#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 + /* 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; -#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; -} -#endif + WOLFSSL_ENTER("wolfSSL_OBJ_txt2obj"); + if (s == NULL) + return NULL; -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; - } - return (int)p->num; -} + /* 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; + } -WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(WOLFSSL_STACK* sk, int i) -{ - WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_value"); - return (WOLFSSL_CIPHER*)wolfSSL_sk_value(sk, i); -} + /* 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 !defined(NETOS) -void ERR_load_SSL_strings(void) -{ + if (nid != NID_undef) + return wolfSSL_OBJ_nid2obj(nid); -} + return NULL; + } #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; -} + /* 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"); + } -long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, - int len) -{ - if (s == NULL) + #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 - s->ocspResp = resp; - s->ocspRespSz = len; + 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 + } - return WOLFSSL_SUCCESS; -} -#endif /* HAVE_OCSP */ +#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || + HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ -#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; +#ifdef 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 +/* wolfSSL uses negative values for error states. This function returns an + * unsigned type so the value returned is the absolute value of the error. */ -int wolfSSL_set_tlsext_max_fragment_length(WOLFSSL *s, unsigned char mode) +unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line) { - if (s == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 )) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); - return wolfSSL_UseMaxFragment(s, mode); + (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 } -#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) -{ - byte len = 0; - - WOLFSSL_ENTER("wolfSSL_get_finished"); +#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 (!ssl || !buf || count < TLS_FINISHED_SZ) { - WOLFSSL_MSG("Bad parameter"); - 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; +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; } -size_t wolfSSL_get_peer_finished(const WOLFSSL *ssl, void *buf, size_t count) +void crypto_ex_cb_free(CRYPTO_EX_cb_ctx* cb_ctx) { - byte len = 0; - WOLFSSL_ENTER("wolfSSL_get_peer_finished"); - - if (!ssl || !buf || count < TLS_FINISHED_SZ) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; + while (cb_ctx != NULL) { + CRYPTO_EX_cb_ctx* next = cb_ctx->next; + XFREE(cb_ctx, NULL, DYNAMIC_TYPE_OPENSSL); + cb_ctx = next; } +} - if (ssl->options.side == WOLFSSL_CLIENT_END) { - len = ssl->serverFinished_len; - XMEMCPY(buf, ssl->serverFinished, len); - } - else { - len = ssl->clientFinished_len; - XMEMCPY(buf, ssl->clientFinished, len); +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); } - - return len; } -#endif /* WOLFSSL_HAVE_TLS_UNIQUE */ -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ - defined(OPENSSL_ALL) -long wolfSSL_get_verify_result(const WOLFSSL *ssl) +int crypto_ex_cb_dup_data(const WOLFSSL_CRYPTO_EX_DATA *in, + WOLFSSL_CRYPTO_EX_DATA *out, CRYPTO_EX_cb_ctx* cb_ctx) { - if (ssl == NULL) { - return WOLFSSL_FAILURE; + 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 ssl->peerVerifyRet; + return WOLFSSL_SUCCESS; } -#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) +void crypto_ex_cb_free_data(void *obj, CRYPTO_EX_cb_ctx* cb_ctx, + WOLFSSL_CRYPTO_EX_DATA* ex_data) { - WOLFSSL_STUB("wolfSSL_CTX_sess_accept"); - (void)ctx; - return 0; + 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); + } } -#endif -#ifndef NO_WOLFSSL_STUB -/* shows the number of connects attempted CTX in it's lifetime */ -long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) +/** + * 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) { - WOLFSSL_STUB("wolfSSL_CTX_sess_connect"); - (void)ctx; - return 0; -} -#endif + /* 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; -#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; + /* 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 - +#endif /* HAVE_EX_DATA || WOLFSSL_WPAS_SMALL */ -#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) +#if defined(HAVE_EX_DATA) || defined(WOLFSSL_WPAS_SMALL) +void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) { - WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good"); + 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; - return 0; -} + (void)idx; #endif + return NULL; +} - -#ifndef NO_WOLFSSL_STUB -/* shows the number of renegotiation accepts attempted by CTX */ -long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx) +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_STUB("wolfSSL_CTX_sess_accept_renegotiate"); - (void)ctx; - return 0; -} -#endif + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); -#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; + return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_CTX, idx, arg, + new_func, dup_func, free_func); } -#endif - -#ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx) +/* 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_STUB("wolfSSL_CTX_sess_hits"); - (void)ctx; - return 0; + WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); + + return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL, argValue, arg, + cb1, cb2, cb3); } -#endif -#ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx) +int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) { - WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits"); + 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; - return 0; + (void)idx; + (void)data; + #endif + return WOLFSSL_FAILURE; } -#endif - -#ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx) +#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_STUB("wolfSSL_CTX_sess_cache_full"); - (void)ctx; - return 0; + 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 */ +#endif /* defined(HAVE_EX_DATA) || defined(WOLFSSL_WPAS_SMALL) */ -#ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx) +#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) { - WOLFSSL_STUB("wolfSSL_CTX_sess_misses"); - (void)ctx; - return 0; + /* checkout exdata stuff... */ + WOLFSSL_ENTER("wolfSSL_get_app_data"); + + return wolfSSL_get_ex_data(ssl, 0); } -#endif -#ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts"); - (void)ctx; - return 0; -} -#endif +/* 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); +} -/* Return the total number of sessions */ -long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) -{ - word32 total = 0; +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - WOLFSSL_ENTER("wolfSSL_CTX_sess_number"); - (void)ctx; +#if defined(HAVE_EX_DATA) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_WPAS_SMALL) -#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"); +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("Please use macro WOLFSSL_SESSION_STATS for session stats"); + WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); + (void)ssl; + (void)idx; + (void)data; #endif - - return (long)total; + return WOLFSSL_FAILURE; } - -#ifndef NO_CERTS -long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) +#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) { - byte* chain = NULL; - int derSz; - const byte* der; - int ret; - DerBuffer *derBuffer = NULL; - - WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert"); - - if (ctx == NULL || x509 == NULL) { - WOLFSSL_MSG("Bad Argument"); - return WOLFSSL_FAILURE; - } - - der = wolfSSL_X509_get_der(x509, &derSz); - if (der == NULL || derSz <= 0) { - WOLFSSL_MSG("Error getting X509 DER"); - return WOLFSSL_FAILURE; - } - - 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; - } - } - 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; - } - - /* adding cert to existing chain */ - if (ctx->certChain != NULL && ctx->certChain->length > 0) { - chainSz += ctx->certChain->length; - } - chainSz += OPAQUE24_LEN + derSz; - - chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER); - if (chain == NULL) { - WOLFSSL_MSG("Memory Error"); - return WOLFSSL_FAILURE; - } - - if (ctx->certChain != NULL && ctx->certChain->length > 0) { - XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); - idx = ctx->certChain->length; - } - 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); - } + 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); } - - /* on success WOLFSSL_X509 memory is responsibility of ctx */ - wolfSSL_X509_free(x509); - if (chain != NULL) - XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER); - - return WOLFSSL_SUCCESS; + return WOLFSSL_FAILURE; } +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ - -long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg) +void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) { - if (ctx == NULL || ctx->cm == NULL) { - return WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_get_ex_data"); +#ifdef HAVE_EX_DATA + if (ssl != NULL) { + return wolfSSL_CRYPTO_get_ex_data(&ssl->ex_data, idx); } - - ctx->cm->ocspIOCtx = arg; - return WOLFSSL_SUCCESS; +#else + WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); + (void)ssl; + (void)idx; +#endif + return 0; } -#endif /* !NO_CERTS */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || WOLFSSL_WPAS_SMALL */ -int wolfSSL_get_read_ahead(const WOLFSSL* ssl) +#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) + +/* 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->readAhead; + return ssl->options.handShakeState; } +#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */ - -int wolfSSL_set_read_ahead(WOLFSSL* ssl, int v) +#ifdef OPENSSL_EXTRA +void wolfSSL_certs_clear(WOLFSSL* ssl) { - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } + WOLFSSL_ENTER("wolfSSL_certs_clear"); - ssl->readAhead = (byte)v; + if (ssl == NULL) + return; - return WOLFSSL_SUCCESS; + /* 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) -int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) +long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt) { - if (ctx == NULL) { - return WOLFSSL_FAILURE; - } - - return ctx->readAhead; -} - + WOLFSSL_ENTER("wolfSSL_ctrl"); + if (ssl == NULL) + return BAD_FUNC_ARG; -int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v) -{ - if (ctx == NULL) { - return WOLFSSL_FAILURE; + 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."); } - - ctx->readAhead = (byte)v; - - return WOLFSSL_SUCCESS; + (void)opt; + (void)pt; + return WOLFSSL_FAILURE; } - -long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx, - void* arg) +long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt) { - if (ctx == NULL) { - return WOLFSSL_FAILURE; - } +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + long ctrl_opt; +#endif + long ret = WOLFSSL_SUCCESS; - ctx->userPRFArg = arg; - return WOLFSSL_SUCCESS; -} + WOLFSSL_ENTER("wolfSSL_CTX_ctrl"); + if (ctx == NULL) + return WOLFSSL_FAILURE; -#endif /* OPENSSL_EXTRA */ + 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(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; -} +#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); -void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i) -{ - WOLFSSL_ENTER("wolfSSL_sk_value"); + #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 */ - for (; sk != NULL && i > 0; i--) - sk = sk->next; - if (sk == NULL) - return NULL; + 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); - 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; +#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; } -/* copies over data of "in" to "out" */ -static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out) +#ifndef WOLFSSL_NO_STUB +long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void)) { - if (in == NULL || out == NULL) - return; + (void) ctx; + (void) cmd; + (void) fp; + WOLFSSL_STUB("wolfSSL_CTX_callback_ctrl"); + return WOLFSSL_FAILURE; - *out = *in; } +#endif /* WOLFSSL_NO_STUB */ -WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk) +#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 - WOLFSSL_STACK* ret = NULL; - WOLFSSL_STACK* last = NULL; +/* 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; +} - WOLFSSL_ENTER("wolfSSL_sk_dup"); +#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; - while (sk) { - WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap); + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio"); - if (!cur) { - WOLFSSL_MSG("wolfSSL_sk_new_node error"); - goto error; - } + if (bio == NULL) { + return NULL; + } + (void)out; - if (!ret) { - /* Set first node */ - ret = cur; - } + memSz = wolfSSL_BIO_get_len(bio); + if (memSz <= 0) { + WOLFSSL_MSG("wolfSSL_BIO_get_len() failure"); + return NULL; + } - if (last) { - last->next = cur; - } + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + WOLFSSL_MSG("Malloc failure"); + return NULL; + } - XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK)); - - /* We will allocate new memory for this */ - XMEMSET(&cur->data, 0, sizeof(cur->data)); - cur->next = NULL; + if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) { + int extraBioMemSz; + int derLength; - 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; + /* 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; } - sk = sk->next; - last = cur; - } - return ret; + /* Write extra data back into bio object if necessary. */ + derLength = key->pkey_sz; + extraBioMemSz = (memSz - derLength); + if (extraBioMemSz > 0) { + int i; + int j = 0; -error: - if (ret) { - wolfSSL_sk_GENERAL_NAME_free(ret); + 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; + } } - return NULL; + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return key; } +#endif /* !NO_BIO */ +#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */ -WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* sk) + +#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); +} - WOLFSSL_STACK* ret = NULL; - WOLFSSL_STACK** prev = &ret; +#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT || + * WOLFSSL_WPAS_SMALL*/ - WOLFSSL_ENTER("wolfSSL_shallow_sk_dup"); - for (; sk != NULL; sk = sk->next) { - WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap); +/* 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; +} - if (!cur) { - WOLFSSL_MSG("wolfSSL_sk_new_node error"); - goto error; - } +#ifndef NO_FILESYSTEM +/***TBD ***/ +void wolfSSL_print_all_errors_fp(XFILE fp) +{ + (void)fp; +} +#endif /* !NO_FILESYSTEM */ - XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK)); - cur->next = NULL; +#endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || + HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH */ - *prev = cur; - prev = &cur->next; - } - return ret; +/* 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))) -error: - if (ret) { - wolfSSL_sk_free(ret); - } - return NULL; -} +#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; -/* Free the just the stack structure */ -void wolfSSL_sk_free(WOLFSSL_STACK* sk) +static void* OSSL_Malloc(size_t size) { - WOLFSSL_ENTER("wolfSSL_sk_free"); + if (ossl_malloc != NULL) + return ossl_malloc(size, NULL, 0); + else + return NULL; +} - while (sk != NULL) { - WOLFSSL_STACK* next = sk->next; - XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); - sk = next; - } +static void OSSL_Free(void *ptr) +{ + if (ossl_free != NULL) + ossl_free(ptr, NULL, 0); } -/* Frees each node in the stack and frees the stack. - */ -void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, - void (*f) (void*)) +static void* OSSL_Realloc(void *ptr, size_t size) { - WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free"); - wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f); + if (ossl_realloc != NULL) + return ossl_realloc(ptr, size, NULL, 0); + else + return NULL; } +#endif /* USE_WOLFSSL_MEMORY && !WOLFSSL_DEBUG_MEMORY && + * !WOLFSSL_STATIC_MEMORY */ -/* return 1 on success 0 on fail */ -int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic) +int wolfSSL_CRYPTO_set_mem_functions( + wolfSSL_OSSL_Malloc_cb m, + wolfSSL_OSSL_Realloc_cb r, + wolfSSL_OSSL_Free_cb f) { - WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push"); +#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 +} - return wolfSSL_sk_push(sk, generic); +int wolfSSL_ERR_load_ERR_strings(void) +{ + return WOLFSSL_SUCCESS; } -void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk) + +void wolfSSL_ERR_load_crypto_strings(void) { - wolfSSL_sk_free(sk); + WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); + /* Do nothing */ + return; } -/* 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) +int wolfSSL_FIPS_mode(void) { - 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; +#ifdef HAVE_FIPS + return 1; +#else + return 0; +#endif } -/* 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) +int wolfSSL_FIPS_mode_set(int r) { - WOLFSSL_ENTER("wolfSSL_sk_pop_free"); - - if (sk == NULL) { - /* pop_free can be called with NULL, do not print bad argument */ - return; +#ifdef HAVE_FIPS + if (r == 0) { + WOLFSSL_MSG("Cannot disable FIPS at runtime."); + return WOLFSSL_FAILURE; } - #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; + return WOLFSSL_SUCCESS; +#else + if (r == 0) { + return WOLFSSL_SUCCESS; } - #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; + WOLFSSL_MSG("Cannot enable FIPS. This isn't the wolfSSL FIPS code."); + return WOLFSSL_FAILURE; #endif - break; - case STACK_TYPE_CIPHER: - case STACK_TYPE_NULL: - default: - break; - } - } +} - while (sk != NULL) { - WOLFSSL_STACK* next = sk->next; +int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) +{ + int ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits"); - if (func != NULL) { - if (sk->type != STACK_TYPE_CIPHER) - func(sk->data.generic); + #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; } - XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); - sk = next; } + #endif + return ret; } -/* 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. +/* returns value less than 0 on fail to match + * On a successful match the priority level found is returned */ -WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type) +int wolfSSL_sk_SSL_CIPHER_find( + WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind) { - WOLFSSL_STACK* sk; + WOLFSSL_STACK* next; + int i, sz; - /* 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; + if (sk == NULL || toFind == NULL) { + return WOLFSSL_FATAL_ERROR; } - return sk; + 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; } -/* Creates and returns a new null stack. */ -WOLFSSL_STACK* wolfSSL_sk_new_null(void) +/* 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_new_null"); - - return wolfssl_sk_new_type(STACK_TYPE_NULL); + WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_free"); + wolfSSL_sk_free(sk); } -int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk) +#ifdef HAVE_SNI +int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name) { - if (sk == NULL) - return 0; - return (int)sk->num; + 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; } -#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*)) +#ifndef NO_WOLFSSL_SERVER +const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type) { - if (ctx == NULL) - return; - -#ifdef HAVE_EXT_CACHE - ctx->get_sess_cb = f; -#else - (void)f; -#endif + 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 */ -void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, - int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) +WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) { - if (ctx == NULL) - return; - -#ifdef HAVE_EXT_CACHE - ctx->new_sess_cb = f; -#else - (void)f; + 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; -void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, - WOLFSSL_SESSION*)) -{ - if (ctx == NULL) - return; +#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 -#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) - ctx->rem_sess_cb = f; -#else - (void)f; +#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; } -/* - * - * 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) +VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx) { - int size = 0; -#ifdef HAVE_EXT_CACHE - int idx = 0; -#ifdef SESSION_CERTS - int i; -#endif + WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback"); + if(ctx) + return ctx->verifyCallback; + return NULL; +} - WOLFSSL_ENTER("wolfSSL_i2d_SSL_SESSION"); - sess = ClientSessionToSession(sess); - if (sess == NULL) { - return BAD_FUNC_ARG; - } +#ifdef HAVE_SNI - /* 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 +void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback"); + if (ctx) + ctx->sniRecvCb = cb; +} - if (p != NULL) { - unsigned char *data; +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; +} - 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 +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; } -#endif + return WOLFSSL_FAILURE; +} - (void)sess; - (void)p; -#ifdef HAVE_EXT_CACHE - (void)idx; -#endif +#endif /* HAVE_SNI */ - return size; -} +#ifndef NO_BIO +void wolfSSL_ERR_load_BIO_strings(void) { + WOLFSSL_ENTER("wolfSSL_ERR_load_BIO_strings"); + /* do nothing */ +} +#endif -/* 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) +#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_SESSION* s = NULL; - int ret = 0; -#if defined(HAVE_EXT_CACHE) - int idx = 0; - byte* data; -#ifdef SESSION_CERTS - int j; - word16 length; + WOLFSSL_ENTER("wolfSSL_THREADID_set_callback"); + WOLFSSL_STUB("CRYPTO_THREADID_set_callback"); + (void)threadid_func; + return 1; +} #endif -#endif /* HAVE_EXT_CACHE */ - (void)p; - (void)i; - (void)ret; - (void)sess; +#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 -#ifdef HAVE_EXT_CACHE - if (p == NULL || *p == NULL) - return NULL; +#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || + * HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH || + * HAVE_SBLIM_SFCB)) */ - s = wolfSSL_SESSION_new(); - if (s == NULL) - return NULL; - idx = 0; - data = (byte*)*p; +#if defined(OPENSSL_EXTRA) - /* 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++]; +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); +} - /* 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; +unsigned long wolfSSL_ERR_peek_last_error(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); - /* 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 WOLFSSL_HAVE_ERROR_QUEUE + { + int ret; -#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; + if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; } - 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; + 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; } - s->cipherSuite0 = data[idx++]; - s->cipherSuite = data[idx++]; +#else + return (unsigned long)(0 - NOT_COMPILED_IN); #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++]; +#endif /* OPENSSL_EXTRA */ - /* 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; +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; + } } - s->peerVerifyRet = data[idx++]; -#endif -#ifdef WOLFSSL_TLS13 - if (i - idx < OPAQUE16_LEN) { - ret = BUFFER_ERROR; - goto end; + 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; + } } - 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; + 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_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; } -#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; + 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 - 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) */ + WOLFSSL_LEAVE("wolfSSL_get_verify_mode", mode); + return mode; +} - 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; +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; } - 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 (ctx->verifyNone) { + mode = WOLFSSL_VERIFY_NONE; } - 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; + 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; } - 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; + WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode); + return mode; +} - *p += idx; +#endif -end: - if (ret != 0 && (sess == NULL || *sess != s)) { - wolfSSL_FreeSession(NULL, s); - s = NULL; - } -#endif /* HAVE_EXT_CACHE */ - return s; -} +#ifdef WOLFSSL_JNI -/* 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) +int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr) { - 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; - } + WOLFSSL_ENTER("wolfSSL_set_jobject"); + if (ssl != NULL) + { + ssl->jObjectRef = objPtr; + return WOLFSSL_SUCCESS; } -#else - (void)sess; -#endif return WOLFSSL_FAILURE; } -unsigned long wolfSSL_SESSION_get_ticket_lifetime_hint( - const WOLFSSL_SESSION* sess) +void* wolfSSL_get_jobject(WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_SESSION_get_ticket_lifetime_hint"); - sess = ClientSessionToSession(sess); - if (sess) { - return sess->timeout; - } - return 0; + WOLFSSL_ENTER("wolfSSL_get_jobject"); + if (ssl != NULL) + return ssl->jObjectRef; + return NULL; } -long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) +#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) { - long timeout = 0; - WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); - sess = ClientSessionToSession(sess); - if (sess) - timeout = sess->timeout; - return timeout; + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL, + events, maxEvents, flags, eventCount); } -long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) +int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) { - word32 tmptime; + int ret, eventCount = 0; + WOLF_EVENT* events[1]; - ses = ClientSessionToSession(ses); - if (ses == NULL || t < 0) { + if (ssl == NULL) { return BAD_FUNC_ARG; } - tmptime = t & 0xFFFFFFFF; - ses->timeout = tmptime; + ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl, + events, sizeof(events)/sizeof(events[0]), flags, &eventCount); + if (ret == 0) { + ret = eventCount; + } - return WOLFSSL_SUCCESS; + return ret; } +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef OPENSSL_EXTRA -long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) +static int peek_ignore_err(int err) { - long bornOn = 0; - WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); - sess = ClientSessionToSession(sess); - if (sess) - bornOn = sess->bornOn; - return bornOn; + 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; + } } -long wolfSSL_SESSION_set_time(WOLFSSL_SESSION *ses, long t) +unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) { + unsigned long err; - ses = ClientSessionToSession(ses); - if (ses == NULL || t < 0) { - return 0; - } - ses->bornOn = (word32)t; - return t; -} + WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data"); + err = wc_PeekErrorNodeLineData(file, line, data, flags, peek_ignore_err); -#endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */ + 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 -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) -#if defined(HAVE_EX_DATA) && !defined(NO_FILESYSTEM) -int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) +#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_FATAL_ERROR; + 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_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 (ipa == NULL) + return NULL; - file = XFOPEN(fname, "rb"); - if (file == XBADFILE) - return WOLFSSL_BAD_FILE; + if (XSTRSTR(ipa, ":") != NULL) { + af = WOLFSSL_IP6; + ipaSz = WOLFSSL_IP6_ADDR_LEN; + } - 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; - } + buf[WOLFSSL_IP6_ADDR_LEN] = '\0'; + if (XINET_PTON(af, ipa, (void*)buf) != 1) { + WOLFSSL_MSG("Error parsing IP address"); + return NULL; + } - 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; + 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; } - - FreeDer(&fileDer); - - if (dynamic) - XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); - - XFCLOSE(file); } 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 -#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"}, + return 0; +} - /* oidCertAuthInfoType */ - { NID_ad_OCSP, AIA_OCSP_OID, oidCertAuthInfoType, "OCSP", - "OCSP"}, - { NID_ad_ca_issuers, AIA_CA_ISSUER_OID, oidCertAuthInfoType, - "caIssuers", "CA Issuers"}, +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; + } +} - /* oidCertPolicyType */ - { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy", - "X509v3 Any Policy"}, +/* 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 - /* oidCertAltNameType */ - { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""}, + WOLFSSL_ENTER("wolfSSL_get_ciphers_compat"); + if (ssl == NULL) + return NULL; - /* 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"}, + suites = WOLFSSL_SUITES(ssl); + if (suites == NULL) + return NULL; - /* 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"}, + /* check if stack needs populated */ + if (ssl->suitesStack == NULL) { + int i; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + int j; -#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" }, + /* 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 -#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; + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + /* in_stack is checked in wolfSSL_CIPHER_description */ + add->data.cipher.in_stack = 1; #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; + add->next = ret; + if (ret != NULL) { + add->num = ret->num + 1; + } + else { + add->num = 1; + } + ret = add; } - break; - #endif - - default: - WOLFSSL_MSG("NID not in table"); - /* MSVC warns without the cast */ - return (word32)-1; + } + ((WOLFSSL*)ssl)->suitesStack = ret; } - - /* MSVC warns without the cast */ - return (word32)-1; + return ssl->suitesStack; } +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ -int oid2nid(word32 oid, int grp) +#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) { - 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; + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout"); - #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 (ctx == NULL) + return 0; - /* 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; + return ctx->timeout; +} - /* oidCertAuthInfoType */ - case oidCertAuthInfoType: - switch (oid) { - case AIA_OCSP_OID: - return NID_ad_OCSP; - case AIA_CA_ISSUER_OID: - return NID_ad_ca_issuers; - } - break; - /* oidCertPolicyType */ - case oidCertPolicyType: - switch (oid) { - case CP_ANY_OID: - return NID_any_policy; - } - break; +/* returns the time in seconds of the current timeout */ +long wolfSSL_get_timeout(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_timeout"); - /* oidCertAltNameType */ - case oidCertAltNameType: - switch (oid) { - case HW_NAME_OID: - return NID_hw_name_oid; - } - break; + if (ssl == NULL) + return 0; + return ssl->timeout; +} +#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; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) - /* oidKdfType */ - case oidKdfType: - switch (oid) { - case PBKDF2_OID: - return PBKDF2_OID; - } - break; +#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"); - /* 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; + if (ctx == NULL || ecdh == NULL) + return BAD_FUNC_ARG; - /* 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; + ctx->ecdhCurveOID = ecdh->group->curve_oid; - /* 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; + 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; -#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; + 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; - 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; - } + if (ssl->options.side == WOLFSSL_CLIENT_END) { + return ssl->options.connectState > CONNECT_BEGIN && + ssl->options.connectState < SECOND_REPLY_DONE; } - return -1; + return ssl->options.acceptState > ACCEPT_BEGIN && + ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE; } -/* frees all nodes in the current threads error queue +#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. * - * id thread id. ERR_remove_state is depreciated and id is ignored. The - * current threads queue will be free'd. + * 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. */ -void wolfSSL_ERR_remove_state(unsigned long id) +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) { - WOLFSSL_ENTER("wolfSSL_ERR_remove_state"); - (void)id; - if (wc_ERR_remove_state() != 0) { - WOLFSSL_MSG("Error with removing the state"); - } -} - -#endif /* OPENSSL_EXTRA */ + 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; -#ifdef OPENSSL_ALL + (void)ctx; -#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) -{ - 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; + WOLFSSL_ENTER("wolfSSL_TicketKeyCb"); - keySz = pkey->pkey_sz + 128; - key = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) - ret = MEMORY_E; + if (ssl == NULL || ssl->ctx == NULL || ssl->ctx->ticketEncWrapCb == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_TICKET_RET_FATAL; + } - if (ret == 0 && enc != NULL && passwd == NULL) { - passwdSz = cb(password, sizeof(password), 1, ctx); - if (passwdSz < 0) - ret = WOLFSSL_FAILURE; - passwd = password; +#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 - 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; + /* 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 (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; - } - #ifdef HAVE_ECC - if (ret >= 0) - #endif - { - ret = wc_CreatePKCS8Key(key, &keySz, (byte*)pkey->pkey.ptr, - pkey->pkey_sz, algId, curveOid, oidSz); - keySz = ret; - } + if (wolfSSL_HMAC_size(&hmacCtx) > WOLFSSL_TICKET_MAC_SZ) { + WOLFSSL_MSG("Ticket cipher MAC size error"); + goto end; } - if (password == passwd) - XMEMSET(password, 0, passwdSz); + 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; - if (ret >= 0) { - pemSz = 2 * keySz + 2 * 64; - pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (pem == NULL) - ret = MEMORY_E; + /* 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: - if (ret >= 0) - ret = wc_DerToPemEx(key, keySz, pem, pemSz, NULL, type); + (void)wc_HmacFree(&hmacCtx.hmac); + (void)wolfSSL_EVP_CIPHER_CTX_cleanup(evpCtx); - if (key != NULL) - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif - if (ret >= 0) { - if (wolfSSL_BIO_write(bio, pem, ret) != ret) - ret = -1; - } + return ret; +} - if (pem != NULL) - XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); +/* 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) +{ - return ret < 0 ? 0 : ret; + /* Set the ticket encryption callback to be a wrapper around OpenSSL + * callback. + */ + ctx->ticketEncCb = wolfSSL_TicketKeyCb; + ctx->ticketEncWrapCb = cb; + return WOLFSSL_SUCCESS; } -#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) +#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) { - int ret = WOLFSSL_SUCCESS; - BIO *b; + if (ctx == NULL || keys == NULL) { + return WOLFSSL_FAILURE; + } + if (keylen != WOLFSSL_TICKET_KEYS_SZ) { + return WOLFSSL_FAILURE; + } - WOLFSSL_ENTER("wolfSSL_PEM_write_PKCS8PrivateKey"); + 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); - b = wolfSSL_BIO_new_fp(f, BIO_NOCLOSE); - if (b == NULL) { - ret = WOLFSSL_FAILURE; + 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 (ret == WOLFSSL_SUCCESS) { - ret = wolfSSL_PEM_write_bio_PKCS8PrivateKey(b, pkey, enc, passwd, - passwdSz, cb, ctx); + if (keylen != WOLFSSL_TICKET_KEYS_SZ) { + return WOLFSSL_FAILURE; } - wolfSSL_BIO_free(b); + 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 ret; + return WOLFSSL_SUCCESS; } -#endif /* !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */ +#endif -static int bio_get_data(WOLFSSL_BIO* bio, byte** data) +#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) { - 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; - } - } - } - - *data = mem; - - return ret; + *response = ssl->ocspResp; + return ssl->ocspRespSz; } -/* 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) +/* Not an OpenSSL API. */ +char* wolfSSL_get_ocsp_url(WOLFSSL* ssl) { - 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 - - ret = ToTraditionalEnc(der, len, password, passwordSz, &algId); - if (ret < 0) { - XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); - return NULL; - } + return ssl->url; +} - ForceZero(password, passwordSz); - #ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Check(password, passwordSz); - #endif - } +/* Not an OpenSSL API. */ +int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url) +{ + if (ssl == NULL) + return WOLFSSL_FAILURE; - p = der; - key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len); - XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); - return key; + ssl->url = url; + return WOLFSSL_SUCCESS; } +#endif /* OCSP */ +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ -#endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */ - -/* 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) +#if defined(HAVE_OCSP) && !defined(NO_ASN_TIME) +int wolfSSL_get_ocsp_producedDate( + WOLFSSL *ssl, + byte *producedDate, + size_t producedDate_space, + int *producedDateFormat) { - 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; - - /* 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 ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) && + (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME)) + 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++; - } - } - } - } + if ((producedDate == NULL) || (producedDateFormat == NULL)) + return BAD_FUNC_ARG; - 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; + if (XSTRLEN((char *)ssl->ocspProducedDate) >= producedDate_space) + return BUFFER_E; - key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen); - *pp = der; - } + XSTRNCPY((char *)producedDate, (const char *)ssl->ocspProducedDate, + producedDate_space); + *producedDateFormat = ssl->ocspProducedDateFormat; - return key; + return 0; } -#endif /* OPENSSL_ALL */ -#ifdef WOLFSSL_STATIC_EPHEMERAL -int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr) -{ - int ret; - word32 idx = 0; - DerBuffer* der = NULL; +int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) { + int idx = 0; - if (ssl == NULL || ssl->ctx == NULL || keyPtr == NULL) { + if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) && + (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME)) 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 - - 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; - } -#ifndef SINGLE_THREADED - wc_UnLockMutex(&ssl->ctx->staticKELock); -#endif - return ret; + 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 -static int SetStaticEphemeralKey(WOLFSSL_CTX* ctx, - StaticKeyExchangeInfo_t* staticKE, int keyAlgo, const char* key, - unsigned int keySz, int format, void* heap) + +#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) { - int ret = 0; - DerBuffer* der = NULL; - byte* keyBuf = NULL; -#ifndef NO_FILESYSTEM - const char* keyFile = NULL; -#endif + word32 idx; + word32 length; + WOLFSSL_STACK* node; + WOLFSSL_STACK* last = NULL; - /* allow empty key to free buffer */ - if (staticKE == NULL || (key == NULL && keySz > 0)) { - return BAD_FUNC_ARG; + if (ctx == NULL || chain == NULL) { + chain = NULL; + return WOLFSSL_FAILURE; + } + if (ctx->x509Chain != NULL) { + *chain = ctx->x509Chain; + return WOLFSSL_SUCCESS; } - WOLFSSL_ENTER("SetStaticEphemeralKey"); + /* If there are no chains then success! */ + *chain = NULL; + if (ctx->certChain == NULL || ctx->certChain->length == 0) { + return WOLFSSL_SUCCESS; + } - /* 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; + /* 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; - 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 + /* Add object to the end of the stack. */ + if (last == NULL) { + node->num = 1; + *chain = node; } 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 - - if (keyAlgo != WC_PK_TYPE_NONE) { - ret = AllocDer(&der, keySz, PRIVATEKEY_TYPE, heap); - if (ret == 0) { - XMEMCPY(der->buffer, keyBuf, keySz); - } - } + (*chain)->num++; + last->next = node; } - } -#ifndef NO_FILESYSTEM - /* done with keyFile buffer */ - if (keyFile && keyBuf) { - XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + last = node; } -#endif -#ifndef SINGLE_THREADED - if (ret == 0 && !ctx->staticKELockInit) { - ret = wc_InitMutex(&ctx->staticKELock); - if (ret == 0) { - ctx->staticKELockInit = 1; - } - } + 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 - 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; - } - #ifndef SINGLE_THREADED - wc_UnLockMutex(&ctx->staticKELock); - #endif - } + return WOLFSSL_SUCCESS; - if (ret != 0) { - FreeDer(&der); - } +} - (void)ctx; /* not used for single threaded */ +int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb cb) +{ + if (ctx == NULL || ctx->cm == NULL) + return WOLFSSL_FAILURE; - WOLFSSL_LEAVE("SetStaticEphemeralKey", ret); +#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 ret; + return WOLFSSL_SUCCESS; } -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) +int wolfSSL_CTX_get0_chain_certs(WOLFSSL_CTX *ctx, + WOLF_STACK_OF(WOLFSSL_X509) **sk) { - if (ssl == NULL || ssl->ctx == NULL) { - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_CTX_get0_chain_certs"); + if (ctx == NULL || sk == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; } - return SetStaticEphemeralKey(ssl->ctx, &ssl->staticKE, keyAlgo, - key, keySz, format, ssl->heap); + + /* 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); } -static int GetStaticEphemeralKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - int keyAlgo, const unsigned char** key, unsigned int* keySz) +#ifdef KEEP_OUR_CERT +int wolfSSL_get0_chain_certs(WOLFSSL *ssl, + WOLF_STACK_OF(WOLFSSL_X509) **sk) { - int ret = 0; - DerBuffer* der = NULL; - - if (key) *key = NULL; - if (keySz) *keySz = 0; - -#ifndef SINGLE_THREADED - if (ctx->staticKELockInit && - (ret = wc_LockMutex(&ctx->staticKELock)) != 0) { - return ret; + 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 - 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; - } +WOLF_STACK_OF(WOLFSSL_STRING)* wolfSSL_sk_WOLFSSL_STRING_new(void) +{ + WOLF_STACK_OF(WOLFSSL_STRING)* ret = wolfSSL_sk_new_node(NULL); - if (der) { - if (key) - *key = der->buffer; - if (keySz) - *keySz = der->length; + if (ret) { + ret->type = STACK_TYPE_STRING; } -#ifndef SINGLE_THREADED - wc_UnLockMutex(&ctx->staticKELock); -#endif - return ret; } -/* 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) +void wolfSSL_WOLFSSL_STRING_free(WOLFSSL_STRING s) { - if (ctx == NULL) { - return BAD_FUNC_ARG; - } + WOLFSSL_ENTER("wolfSSL_WOLFSSL_STRING_free"); - return GetStaticEphemeralKey(ctx, NULL, keyAlgo, key, keySz); + if (s != NULL) + XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); } -int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo, - const unsigned char** key, unsigned int* keySz) -{ - if (ssl == NULL || ssl->ctx == NULL) { - return BAD_FUNC_ARG; - } - return GetStaticEphemeralKey(ssl->ctx, ssl, keyAlgo, key, keySz); -} +void wolfSSL_sk_WOLFSSL_STRING_free(WOLF_STACK_OF(WOLFSSL_STRING)* sk) +{ + WOLFSSL_STACK* tmp; + WOLFSSL_ENTER("wolfSSL_sk_WOLFSSL_STRING_free"); -#endif /* WOLFSSL_STATIC_EPHEMERAL */ + if (sk == NULL) + return; -#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; + /* 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_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) + +WOLFSSL_STRING wolfSSL_sk_WOLFSSL_STRING_value( + WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx) { - (void)id; - return 0UL; + for (; idx > 0 && strings != NULL; idx--) + strings = strings->next; + if (strings == NULL) + return NULL; + return strings->data.string; } -/* 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) + +int wolfSSL_sk_WOLFSSL_STRING_num(WOLF_STACK_OF(WOLFSSL_STRING)* strings) { - (void)ctx; - (void)onoff; - return WOLFSSL_SUCCESS; + if (strings) + return (int)strings->num; + return 0; } -/** - * 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) +#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) { - WOLFSSL_ENTER("wolfSSL_CTX_set_security_level"); - (void)ctx; - (void)level; + word16 nameLen; + + if (ssl != NULL && data != NULL && len != NULL) { + TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen); + *len = nameLen; + } } -/** - * 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) + +int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen, + const unsigned char *in, unsigned int inLen, + const unsigned char *clientNames, + unsigned int clientLen) { - WOLFSSL_ENTER("wolfSSL_CTX_get_security_level"); - (void)ctx; - return 0; -} + unsigned int i, j; + byte lenIn, lenClient; + if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL) + return OPENSSL_NPN_UNSUPPORTED; -/** - * 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; + for (i = 0; i < inLen; i += lenIn) { + lenIn = in[i++]; + for (j = 0; j < clientLen; j += lenClient) { + lenClient = clientNames[j++]; -#ifdef HAVE_SESSION_TICKET - if (s->ticketLen > 0) - return 1; -#endif + if (lenIn != lenClient) + continue; - if (s->sessionIDSz > 0) - return 1; + if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) { + *out = (unsigned char *)(in + i); + *outLen = lenIn; + return OPENSSL_NPN_NEGOTIATED; + } + } + } - return 0; + *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; + } } -#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) +void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) { - WOLFSSL_ENTER("wolfSSL_CTX_set_keylog_callback"); - /* stores the callback into WOLFSSL_CTX */ if (ctx != NULL) { - ctx->keyLogCb = cb; + ctx->alpnSelect = cb; + ctx->alpnSelectArg = arg; } } -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 */ - -#ifndef NO_CERT -#define WOLFSSL_X509_INCLUDED -#include "src/x509.c" -#endif -/******************************************************************************* - * 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 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) m; - (void) r; - (void) f; - WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions"); - WOLFSSL_STUB("CRYPTO_set_mem_ex_functions"); - - return WOLFSSL_FAILURE; + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb"); } -#endif -#endif - -#if defined(OPENSSL_EXTRA) -/** - * 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 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)file; - (void)line; - XFREE(str, 0, DYNAMIC_TYPE_TMP_BUFFER); + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb"); } -/** - * 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) + +void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, + const unsigned char **data, unsigned *len) { - (void)file; - (void)line; - return XMALLOC(num, 0, DYNAMIC_TYPE_TMP_BUFFER); + (void)s; + (void)data; + (void)len; + WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated"); } +#endif /* HAVE_ALPN */ -#endif - -/******************************************************************************* - * END OF standard C library wrapping APIs - ******************************************************************************/ - -/******************************************************************************* - * 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 +#endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */ -#ifdef HAVE_EX_DATA -void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx) +#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL) +int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, word16 curve_id) { - 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]; + if (curve_id >= WOLFSSL_FFDHE_START) { + /* DH parameters are never disabled. */ + return 0; } -#else - (void)ex_data; - (void)idx; -#endif - return NULL; + 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; } -int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, void *data) +#if (defined(HAVE_ECC) || \ + defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) +static int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names) { - 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; - } + 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 - (void)ex_data; - (void)idx; - (void)data; + int groups[WOLFSSL_MAX_GROUP_COUNT]; #endif - return WOLFSSL_FAILURE; -} -#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_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; +#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; } - return WOLFSSL_FAILURE; -} -#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ +#endif -/** - * 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"); + for (idx = 1; names[idx-1] != '\0'; idx++) { + if (names[idx] != ':' && names[idx] != '\0') + continue; - return wolfssl_get_ex_new_index(class_index, argl, argp, new_func, - dup_func, free_func); -} -#endif /* HAVE_EX_DATA */ + len = idx - start; + if (len > MAX_CURVE_NAME_SZ - 1) + goto leave; -/******************************************************************************* - * END OF EX_DATA APIs - ******************************************************************************/ + XMEMCPY(name, names + start, len); + name[len++] = 0; -/******************************************************************************* - * START OF BUF_MEM API - ******************************************************************************/ + /* 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) && defined(HAVE_ECC) + int nret; + const ecc_set_type *eccSet; -#if defined(OPENSSL_EXTRA) + nret = wc_ecc_get_curve_idx_from_name(name); + if (nret < 0) { + WOLFSSL_MSG("Could not find name in set"); + goto leave; + } -/* 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)); - } - return buf; -} + eccSet = wc_ecc_get_curve_params(ret); + if (eccSet == NULL) { + WOLFSSL_MSG("NULL set returned"); + goto leave; + } -/* non-compat API returns length of buffer on success */ -int wolfSSL_BUF_MEM_grow_ex(WOLFSSL_BUF_MEM* buf, size_t len, - char zeroFill) -{ + curve = GetCurveByOID(eccSet->oidSum); + #else + WOLFSSL_MSG("API not present to search farther using name"); + goto leave; + #endif + } - int len_int = (int)len; - int mx; - char* tmp; + if (curve >= WOLFSSL_ECC_MAX_AVAIL) { + WOLFSSL_MSG("curve value is not supported"); + goto leave; + } - /* verify provided arguments */ - if (buf == NULL || len_int < 0) { - return 0; /* BAD_FUNC_ARG; */ - } + 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; + } - /* check to see if fits in existing length */ - if (buf->length > len) { - buf->length = len; - return len_int; + start = idx + 1; } - /* 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); + /* 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)); } - buf->length = len; - return len_int; - } - - /* expand size, to handle growth */ - mx = (len_int + 3) / 3 * 4; - - /* use realloc */ - tmp = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_OPENSSL); - if (tmp == NULL) { - return 0; /* ERR_R_MALLOC_FAILURE; */ + 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 */ } - buf->data = tmp; - - buf->max = mx; - if (zeroFill) - XMEMSET(&buf->data[buf->length], 0, len - buf->length); - buf->length = len; - return len_int; - -} + if (ssl) + ssl->disabledCurves = disabled; + else + ctx->disabledCurves = disabled; + ret = WOLFSSL_SUCCESS; -/* returns length of buffer on success */ -int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len) -{ - return wolfSSL_BUF_MEM_grow_ex(buf, len, 1); +leave: +#ifdef WOLFSSL_SMALL_STACK + if (groups) + XFREE((void*)groups, heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } -/* non-compat API returns length of buffer on success */ -int wolfSSL_BUF_MEM_resize(WOLFSSL_BUF_MEM* buf, size_t len) +int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names) { - char* tmp; - int mx; - - /* verify provided arguments */ - if (buf == NULL || len == 0 || (int)len <= 0) { - return 0; /* BAD_FUNC_ARG; */ + if (ctx == NULL || names == NULL) { + WOLFSSL_MSG("ctx or names was NULL"); + return WOLFSSL_FAILURE; } - - if (len == buf->length) - return (int)len; - - if (len > buf->length) - return wolfSSL_BUF_MEM_grow_ex(buf, len, 0); - - /* 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; - - buf->data = tmp; - buf->length = len; - buf->max = mx; - - return (int)len; + return set_curves_list(NULL, ctx, names); } -void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf) +int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names) { - 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); + if (ssl == NULL || names == NULL) { + WOLFSSL_MSG("ssl or names was NULL"); + return WOLFSSL_FAILURE; } + return set_curves_list(ssl, NULL, names); } -/* End Functions for openssl/buffer.h */ - -#endif /* OPENSSL_EXTRA */ - -/******************************************************************************* - * END OF BUF_MEM API - ******************************************************************************/ - -#define WOLFSSL_CONF_INCLUDED -#include - -/******************************************************************************* - * START OF RAND API - ******************************************************************************/ +#endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) */ +#endif /* OPENSSL_EXTRA || HAVE_CURL */ -#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB) -static int wolfSSL_RAND_InitMutex(void) +#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_MUTEX_INITIALIZER - if (gRandMethodsInit == 0) { - if (wc_InitMutex(&gRandMethodMutex) != 0) { - WOLFSSL_MSG("Bad Init Mutex rand methods"); - return BAD_MUTEX_E; - } - gRandMethodsInit = 1; + WOLFSSL_ENTER("wolfSSL_CTX_set_msg_callback"); + if (ctx == NULL) { + WOLFSSL_MSG("Null ctx passed in"); + return WOLFSSL_FAILURE; } -#endif - return 0; + + ctx->protoMsgCb = cb; + return WOLFSSL_SUCCESS; } -#endif -#ifdef OPENSSL_EXTRA -/* Checks if the global RNG has been created. If not then one is created. +/* Sets a callback for when sending and receiving protocol messages. + * + * ssl WOLFSSL structure to set callback in + * cb callback to use * - * Returns WOLFSSL_SUCCESS when no error is encountered. + * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE with error case */ -int wolfSSL_RAND_Init(void) +int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb) { - 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; - } - } - else { - /* GlobalRNG is already initialized */ - ret = WOLFSSL_SUCCESS; - } + WOLFSSL_ENTER("wolfSSL_set_msg_callback"); - wc_UnLockMutex(&globalRNGMutex); + if (ssl == NULL) { + return WOLFSSL_FAILURE; } -#endif - return ret; + + if (cb != NULL) { + ssl->toInfoOn = 1; + } + + ssl->protoMsgCb = cb; + return WOLFSSL_SUCCESS; } -/* WOLFSSL_SUCCESS on ok */ -int wolfSSL_RAND_seed(const void* seed, int len) +/* 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) { -#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_arg"); + if (ctx == NULL) { + WOLFSSL_MSG("Null WOLFSSL_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->protoMsgCtx = arg; + 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 - * - * 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) +int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg) { -#if !defined(NO_FILESYSTEM) && defined(XGETENV) - char* rt; + WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg"); + if (ssl == NULL) + return WOLFSSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_RAND_file_name"); + ssl->protoMsgCtx = arg; + return WOLFSSL_SUCCESS; +} - if (fname == NULL) { - return NULL; - } +void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, + int line) +{ + void *ret; + (void)file; + (void)line; - XMEMSET(fname, 0, len); + if (data == NULL || siz >= INT_MAX) + return NULL; - if ((rt = XGETENV("RANDFILE")) != NULL) { - if (len > XSTRLEN(rt)) { - XMEMCPY(fname, rt, XSTRLEN(rt)); - } - else { - WOLFSSL_MSG("RANDFILE too large for buffer"); - rt = NULL; - } + ret = OPENSSL_malloc(siz); + if (ret == NULL) { + return NULL; } + return XMEMCPY(ret, data, siz); +} - /* $RANDFILE was not set or is too large, check $HOME */ - if (rt == NULL) { - const char ap[] = "/.rnd"; +void wolfSSL_OPENSSL_cleanse(void *ptr, size_t len) +{ + if (ptr) + ForceZero(ptr, (word32)len); +} - WOLFSSL_MSG("Environment variable RANDFILE not set"); - if ((rt = XGETENV("HOME")) == NULL) { - WOLFSSL_MSG("Environment variable HOME not set"); - return NULL; - } +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); + } - 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; - } + 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; - return fname; +#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 - 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; + return WOLFSSL_SUCCESS; #endif } -/* Writes 1024 bytes from the RNG to the given file name. +#ifdef HAVE_ALPN +#ifndef NO_BIO +/* Sets the ALPN extension protos * - * fname name of file to write to + * example format is + * unsigned char p[] = { + * 8, 'h', 't', 't', 'p', '/', '1', '.', '1' + * }; * - * Returns the number of bytes written - */ -int wolfSSL_RAND_write_file(const char* fname) + * returns WOLFSSL_SUCCESS on success */ +int wolfSSL_set_alpn_protos(WOLFSSL* ssl, + const unsigned char* p, unsigned int p_len) { - int bytes = 0; + WOLFSSL_BIO* bio; + char* pt = NULL; - WOLFSSL_ENTER("wolfSSL_RAND_write_file"); + unsigned int sz; + unsigned int idx = 0; + int alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; + WOLFSSL_ENTER("wolfSSL_set_alpn_protos"); - if (fname == NULL) { + 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 } -#ifndef NO_FILESYSTEM - { - #ifndef WOLFSSL_SMALL_STACK - unsigned char buf[1024]; + 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 - 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; } - - if (wc_RNG_GenerateBlock(&globalRNG, buf, bytes) != 0) { - WOLFSSL_MSG("Error generating random buffer"); - bytes = 0; - } - else { - XFILE f; - - #ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("wolfSSL_RAND_write_file buf", buf, bytes); - #endif - - 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); + 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); } - 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 } -#endif + wolfSSL_BIO_write(bio, "\0", 1); - return bytes; + /* 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 */ -#ifndef FREERTOS_TCP +#if defined(OPENSSL_EXTRA) -/* 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 +#ifndef NO_BIO +#define WOLFSSL_BIO_INCLUDED +#include "src/bio.c" #endif -/* 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) +word32 nid2oid(int nid, int grp) { -#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; - } -#endif + /* 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; - 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; - } + /* 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 */ - 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; - } - rem.sun_family = AF_UNIX; - XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path) - 1); - rem.sun_path[sizeof(rem.sun_path)-1] = '\0'; + /* 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; - /* 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; - } + #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 */ -#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; + /* 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; } - WOLFSSL_MSG("error requesting entropy from egd server"); - ret = WOLFSSL_FATAL_ERROR; break; - } - /* 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; + /* oidCertAuthInfoType */ + case oidCertAuthInfoType: + switch (nid) { + case NID_ad_OCSP: + return AIA_OCSP_OID; + case NID_ad_ca_issuers: + return AIA_CA_ISSUER_OID; + } 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; + + /* oidCertPolicyType */ + case oidCertPolicyType: + switch (nid) { + case NID_any_policy: + return CP_ANY_OID; } - XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]); - idx = bytes; - ret = WOLFSSL_SUCCESS; - if (bytes >= 255) { - break; + break; + + /* oidCertAltNameType */ + case oidCertAltNameType: + switch (nid) { + case NID_hw_name_oid: + return HW_NAME_OID; } - } - else { - if (errno == EAGAIN || errno == EINTR) { - WOLFSSL_MSG("EGD would read"); - ret = WOLFSSL_SUCCESS; /* try again */ + 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; } - 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; + break; + + /* oidKdfType */ + case oidKdfType: + switch (nid) { + case PBKDF2_OID: + return PBKDF2_OID; } - else { - WOLFSSL_MSG("Error with read"); - ret = WOLFSSL_FATAL_ERROR; + 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; - 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]); + /* 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 } - printf("\n"); - } - #endif - } + break; - 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); + /* 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 - if (ret == WOLFSSL_SUCCESS) { - return bytes; - } - else { - return ret; + default: + WOLFSSL_MSG("NID not in table"); + /* MSVC warns without the cast */ + return (word32)-1; } -#else - WOLFSSL_MSG("Type of socket needed is not available"); - WOLFSSL_MSG("\tor using mode where DRBG API is not available"); - (void)nm; - return WOLFSSL_FATAL_ERROR; -#endif /* WOLFSSL_EGD_NBLOCK */ + /* MSVC warns without the cast */ + return (word32)-1; } -#endif /* !FREERTOS_TCP */ - -void wolfSSL_RAND_Cleanup(void) +int oid2nid(word32 oid, int grp) { -#ifndef WOLFSSL_NO_OPENSSL_RAND_CB - if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { - if (gRandMethods && gRandMethods->cleanup) - gRandMethods->cleanup(); - wc_UnLockMutex(&gRandMethodMutex); - } + 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; - #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 -} + /* 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; -/* 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 */ + /* 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; -#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 -#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 + #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 */ - /* get secret value from source of entropy */ - ret = wolfSSL_RAND_bytes(secret, DRBG_SEED_LEN); + /* 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; - /* 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; -} + /* oidCertAuthInfoType */ + case oidCertAuthInfoType: + switch (oid) { + case AIA_OCSP_OID: + return NID_ad_OCSP; + case AIA_CA_ISSUER_OID: + return NID_ad_ca_issuers; + } + 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 + /* oidCertPolicyType */ + case oidCertPolicyType: + switch (oid) { + case CP_ANY_OID: + return NID_any_policy; + } + break; - WOLFSSL_ENTER("wolfSSL_RAND_bytes"); - /* sanity check */ - if (buf == NULL || num < 0) - /* return code compliant with OpenSSL */ - return 0; + /* oidCertAltNameType */ + case oidCertAltNameType: + switch (oid) { + case HW_NAME_OID: + return NID_hw_name_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; - } + /* 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; - 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; + /* oidKdfType */ + case oidKdfType: + switch (oid) { + case PBKDF2_OID: + return PBKDF2_OID; + } + break; - while (blockCount--) { - ret = wc_RNG_GenerateBlock(rng, buf, RNG_MAX_BLOCK_LEN); - if (ret != 0) { - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); - break; + /* 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; } - num -= RNG_MAX_BLOCK_LEN; - buf += RNG_MAX_BLOCK_LEN; - } + break; - if (ret == 0 && num) - ret = wc_RNG_GenerateBlock(rng, buf, num); + /* 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 (ret != 0) - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); - else - ret = WOLFSSL_SUCCESS; - } + /* 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; -#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); +#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 - return ret; -} - - -int wolfSSL_RAND_poll(void) -{ - byte entropy[16]; - int ret = 0; - word32 entropy_sz = 16; - - WOLFSSL_ENTER("wolfSSL_RAND_poll"); - if (initGlobalRNG == 0){ - WOLFSSL_MSG("Global RNG no Init"); - return WOLFSSL_FAILURE; + default: + WOLFSSL_MSG("OID not in table"); } - ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz); - if (ret != 0){ - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); - ret = WOLFSSL_FAILURE; - }else - ret = WOLFSSL_SUCCESS; - - return ret; -} - - /* 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; + /* 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; } - #else - (void)methods; - #endif - return WOLFSSL_FAILURE; } - /* 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; - } + return -1; +} - 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 +/* 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"); } +} -#endif /* OPENSSL_EXTRA */ - -/******************************************************************************* - * END OF RAND API - ******************************************************************************/ +#endif /* OPENSSL_EXTRA */ -/******************************************************************************* - * START OF EVP_CIPHER API - ******************************************************************************/ +#ifdef OPENSSL_ALL -#ifdef OPENSSL_EXTRA +#if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) - /* store for external read of iv, WOLFSSL_SUCCESS on success */ - int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_StoreExternalIV"); +static int bio_get_data(WOLFSSL_BIO* bio, byte** data) +{ + int ret = 0; + byte* mem = NULL; - if (ctx == NULL) { - WOLFSSL_MSG("Bad function argument"); - return WOLFSSL_FATAL_ERROR; + 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; + } + } + } - 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 */ - -#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 */ - -#ifndef NO_DES3 - case DES_CBC_TYPE : - WOLFSSL_MSG("DES CBC"); - XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE); - 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; -#endif - case ARC4_TYPE : - WOLFSSL_MSG("ARC4"); - break; + *data = mem; -#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case CHACHA20_POLY1305_TYPE: - break; -#endif + return ret; +} -#ifdef HAVE_CHACHA - case CHACHA20_TYPE: - break; -#endif +/* 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; -#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 + if ((len = bio_get_data(bio, &der)) < 0) + return NULL; - case NULL_CIPHER_TYPE : - WOLFSSL_MSG("NULL"); - break; + 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 - default: { - WOLFSSL_MSG("bad type"); - return WOLFSSL_FATAL_ERROR; - } + ret = ToTraditionalEnc(der, len, password, passwordSz, &algId); + if (ret < 0) { + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return NULL; } - return WOLFSSL_SUCCESS; + + ForceZero(password, passwordSz); + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(password, passwordSz); + #endif } - /* set internal IV from external, WOLFSSL_SUCCESS on success */ - int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) - { + p = der; + key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len); + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return key; +} - WOLFSSL_ENTER("wolfSSL_SetInternalIV"); +#endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */ - if (ctx == NULL) { - WOLFSSL_MSG("Bad function argument"); - return WOLFSSL_FATAL_ERROR; +/* 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; + + /* Take off PKCS#8 wrapper if found. */ + if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) { + der += idx; + keyLen = len; + } + idx = 0; + len = 0; + + /* 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++; + } + } } + } - switch (ctx->cipherType) { + 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; -#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 + key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen); + *pp = der; + } -#endif /* NO_AES */ + return key; +} +#endif /* OPENSSL_ALL */ -#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 */ +#ifdef WOLFSSL_STATIC_EPHEMERAL +int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr) +{ + int ret; + word32 idx = 0; + DerBuffer* der = NULL; -#ifndef NO_DES3 - case DES_CBC_TYPE : - WOLFSSL_MSG("DES CBC"); - XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE); - break; + if (ssl == NULL || ssl->ctx == NULL || keyPtr == NULL) { + return BAD_FUNC_ARG; + } - 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; +#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 - case ARC4_TYPE : - WOLFSSL_MSG("ARC4"); - break; + 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; + } -#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case CHACHA20_POLY1305_TYPE: - break; +#ifndef SINGLE_THREADED + wc_UnLockMutex(&ssl->ctx->staticKELock); #endif + return ret; +} -#ifdef HAVE_CHACHA - case CHACHA20_TYPE: - break; +static int SetStaticEphemeralKey(WOLFSSL_CTX* ctx, + StaticKeyExchangeInfo_t* staticKE, int keyAlgo, const char* key, + unsigned int keySz, int format, void* heap) +{ + int ret = 0; + DerBuffer* der = NULL; + byte* keyBuf = NULL; +#ifndef NO_FILESYSTEM + const char* keyFile = NULL; #endif -#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 + /* allow empty key to free buffer */ + if (staticKE == NULL || (key == NULL && keySz > 0)) { + return BAD_FUNC_ARG; + } - case NULL_CIPHER_TYPE : - WOLFSSL_MSG("NULL"); - break; + WOLFSSL_ENTER("SetStaticEphemeralKey"); - default: { - WOLFSSL_MSG("bad type"); - return WOLFSSL_FATAL_ERROR; + /* 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; } - return WOLFSSL_SUCCESS; - } - -#ifndef NO_DES3 - -void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, - unsigned char* iv, int len) -{ - (void)len; - WOLFSSL_MSG("wolfSSL_3des_iv"); + 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 - if (ctx == NULL || iv == NULL) { - WOLFSSL_MSG("Bad function argument"); - return; + if (keyAlgo != WC_PK_TYPE_NONE) { + ret = AllocDer(&der, keySz, PRIVATEKEY_TYPE, heap); + if (ret == 0) { + XMEMCPY(der->buffer, keyBuf, keySz); + } + } + } } - 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 */ - - -#ifndef NO_AES - -void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, - unsigned char* iv, int len) -{ - (void)len; - - WOLFSSL_MSG("wolfSSL_aes_ctr_iv"); - - 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; + + if (key) *key = NULL; + if (keySz) *keySz = 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); +#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_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 + */ +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) */ -PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len) +int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx) { - return wolfSSL_d2i_PKCS7_ex(p7, in, len, NULL, 0); + WOLFSSL_ENTER("wolfSSL_CTX_get_security_level"); + (void)ctx; + return 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) +#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; + } +} +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_CERT +#define WOLFSSL_X509_INCLUDED +#include "src/x509.c" +#endif - if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == 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 WOLFSSL_FAILURE; +} +#endif +#endif + +#if defined(OPENSSL_EXTRA) + +/** + * 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) +{ + (void)file; + (void)line; + return XMALLOC(num, 0, DYNAMIC_TYPE_TMP_BUFFER); +} - 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); +#endif - if (content != NULL) { - pkcs7->pkcs7.content = content; - pkcs7->pkcs7.contentSz = contentSz; - } +/******************************************************************************* + * END OF standard C library wrapping APIs + ******************************************************************************/ - if (p7 != NULL) - *p7 = (PKCS7*)pkcs7; - *in += pkcs7->len; - return (PKCS7*)pkcs7; +/******************************************************************************* + * 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 - -/***************************************************************************** -* 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) +#ifdef HAVE_EX_DATA +void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx) { - 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; - } + 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]; } - - return (PKCS7*)pkcs7; +#else + (void)ex_data; + (void)idx; +#endif + return NULL; } - -/** - * 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 wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, + void *data) { - 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; + 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; } +#else + (void)ex_data; + (void)idx; + (void)data; +#endif + return WOLFSSL_FAILURE; +} - /* 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); +#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_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 NULL; + return WOLFSSL_FAILURE; } +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ /** - * 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. + * 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. */ -WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs, - int flags) +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_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; + WOLFSSL_ENTER("wolfSSL_CRYPTO_get_ex_new_index"); - return signers; + return wolfssl_get_ex_new_index(class_index, argl, argp, new_func, + dup_func, free_func); } +#endif /* HAVE_EX_DATA */ -#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; +/******************************************************************************* + * 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 = 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 = 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"; +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_RAND_seed(const void* seed, int len) +{ +#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 -/** - * 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. + /* Make sure global shared RNG (globalRNG) is initialized */ + return wolfSSL_RAND_Init(); +} + + +/* Returns the path for reading seed data from. + * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd * - * 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: + * Note uses stdlib by default unless XGETENV macro is overwritten * - * 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. + * fname buffer to hold path + * len length of fname buffer * - * Returns 1 on success, 0 on error + * Returns a pointer to fname on success and NULL on failure */ -int wolfSSL_PKCS7_final(PKCS7* pkcs7, WOLFSSL_BIO* in, int flags) +const char* wolfSSL_RAND_file_name(char* fname, unsigned long 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 !defined(NO_FILESYSTEM) && defined(XGETENV) + char* rt; - if (ret == 1) { - if ((data = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())) == NULL) { - WOLFSSL_MSG("Error in wolfSSL_BIO_new"); - ret = 0; - } - } + WOLFSSL_ENTER("wolfSSL_RAND_file_name"); - /* 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; - } + if (fname == NULL) { + return NULL; } - /* 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; - } - } + XMEMSET(fname, 0, len); - if (mem != NULL) { - XFREE(mem, in->heap, DYNAMIC_TYPE_TMP_BUFFER); - } + if ((rt = XGETENV("RANDFILE")) != NULL) { + if (len > XSTRLEN(rt)) { + XMEMCPY(fname, rt, XSTRLEN(rt)); } 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 + WOLFSSL_MSG("RANDFILE too large for buffer"); + rt = NULL; } } - if ((ret == 1) && ((memSz = wolfSSL_BIO_get_mem_data(data, &mem)) < 0)) { - WOLFSSL_MSG("Error in wolfSSL_BIO_get_mem_data"); - ret = 0; - } + /* $RANDFILE was not set or is too large, check $HOME */ + if (rt == NULL) { + const char ap[] = "/.rnd"; - if (ret == 1) { - if (p7->data != NULL) { - XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7); + WOLFSSL_MSG("Environment variable RANDFILE not set"); + if ((rt = XGETENV("HOME")) == NULL) { + WOLFSSL_MSG("Environment variable HOME not set"); + return NULL; } - p7->data = (byte*)XMALLOC(memSz, NULL, DYNAMIC_TYPE_PKCS7); - if (p7->data == NULL) { - ret = 0; + + if (len > XSTRLEN(rt) + XSTRLEN(ap)) { + fname[0] = '\0'; + XSTRNCAT(fname, rt, len); + XSTRNCAT(fname, ap, len - XSTRLEN(rt)); + return fname; } else { - XMEMCPY(p7->data, mem, memSz); - p7->len = memSz; + WOLFSSL_MSG("HOME too large for buffer"); + return NULL; } } - if (ret == 1) { - p7->pkcs7.content = p7->data; - p7->pkcs7.contentSz = p7->len; - } - - if (data != NULL) { - wolfSSL_BIO_free(data); - } - - return ret; + 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 } -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; - } - - 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 +/* 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_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs, - WOLFSSL_BIO* out) +int wolfSSL_RAND_write_file(const char* fname) { - 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; + 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, 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, 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 + } +#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; + } + else if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes) + != 0) { + WOLFSSL_MSG("Error with reseeding DRBG 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; + #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"); } - } - else { - WOLFSSL_MSG("S/MIME headers not found."); - goto error; + #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 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, 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 */ diff --git a/src/ssl_bn.c b/src/ssl_bn.c index cbb4a92fac..c025755f99 100644 --- a/src/ssl_bn.c +++ b/src/ssl_bn.c @@ -25,7 +25,7 @@ #include - #include +#include #ifndef WC_NO_RNG #include #endif diff --git a/src/ssl_load.c b/src/ssl_load.c new file mode 100644 index 0000000000..085dc0ec82 --- /dev/null +++ b/src/ssl_load.c @@ -0,0 +1,5878 @@ +/* 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_bn.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. + * @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 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, NULL); + 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, 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 (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); + 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 == 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 + 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_PQC) +#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) +/* 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; + 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. */ + ret = wc_dilithium_import_private_only(der->buffer, der->length, key); + 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 */ +#endif /* HAVE_PQC */ + +/* 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_PQC) +#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) + /* 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 */ +#endif /* HAVE_PQC */ + + /* 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 = ret; + } + + /* Ensure password is zeroized. */ + ForceZero(password, 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. + */ +static void ProcessBufferPrivKeyHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer** der, int type) +{ + (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); + } + 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); + } + 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 + } +} + +/* 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. + * @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 ret; + int keyFormat = 0; +#if (defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)) || \ + defined(HAVE_PKCS8) + word32 algId = 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, &algId); + if (ret > 0) { + /* Header stripped inline. */ + der->length = ret; + keyFormat = algId; + } +#endif + + /* Put the data into the SSL or SSL context object. */ + ProcessBufferPrivKeyHandleDer(ctx, ssl, &der, type); + /* Try to decode the DER data. */ + ret = ProcessBufferTryDecode(ctx, ssl, der, &keyFormat, 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) || (keyFormat == 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, &keyFormat, heap, type); + } + } +#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ + + /* Check if we were able to determine key format. */ + if ((ret == 0) && (keyFormat == 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_PQC + #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 */ + #endif /* HAVE_PQC */ + 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_PQC + #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 +#endif + default: + WOLFSSL_MSG("Cert signature not supported"); + break; + } + +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + (defined(HAVE_PQC) && defined(HAVE_LIBOQS)) || !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 baed 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; +#ifdef WOLF_PRIVATE_KEY_ID + byte keyType = 0; +#endif + 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: + #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) && 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 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; + } + 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: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = sm2_sa_algo; + #endif + /* 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: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = ed25519_sa_algo; + #endif + /* 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: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = ed448_sa_algo; + #endif + /* 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_PQC) + #if defined(HAVE_FALCON) + case FALCON_LEVEL1k: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = falcon_level1_sa_algo; + #endif + /* 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: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = falcon_level5_sa_algo; + #endif + /* Falcon is fixed key size */ + keySz = FALCON_MAX_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: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = dilithium_level2_sa_algo; + #endif + /* Dilithium is fixed key size */ + keySz = DILITHIUM_MAX_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: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = dilithium_level3_sa_algo; + #endif + /* Dilithium is fixed key size */ + keySz = DILITHIUM_MAX_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: + #ifdef WOLF_PRIVATE_KEY_ID + keyType = dilithium_level5_sa_algo; + #endif + /* Dilithium is fixed key size */ + keySz = DILITHIUM_MAX_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 */ + #endif /* HAVE_PQC */ + + default: + WOLFSSL_MSG("No key size check done on public key in certificate"); + break; + } + +#ifdef WOLF_PRIVATE_KEY_ID + /* 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; + } +#endif + + 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_PQC) + #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 */ + #endif /* HAVE_PQC */ + + 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 + + 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); + 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); + #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 == 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); + } + } + + /* 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 == 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 == 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, 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 == 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; +} + +#ifdef WOLFSSL_WIN_USER_CA_CERTS +static int LoadUserCaCertsWindows(WOLFSSL_CTX* ctx, const char* userStore, + const char* userDwFlags, const char* userPvPara) { + int ret = WOLFSSL_SUCCESS; + HANDLE handle = NULL; + PCCERT_CONTEXT certCtx = NULL; + LPCSTR storeProvider = (LPCSTR)userStore; + DWORD dwFlags; + const void* pvPara = userPvPara; + + dwFlags = WinStrToDwFlags(userDwFlags); + if (!dwFlags) { + WOLFSSL_MSG("Invalid/unsupported dwFlags passed to LoadUserCaCertsWindows."); + return WOLFSSL_FAILURE; + } + + handle = CertOpenStore(userStores, X509_ASN_ENCODING, NULL, dwFlags, + userPvPara); + if (handle != NULL) { + while ((certCtx = CertEnumCertificatesInStore(handle, certCtx)) + != NULL) { + if (certCtx->dwCertEncodingType == X509_ASN_ENCODING) { + if (ret = ProcessBuffer(ctx, certCtx->pbCertEncoded, + certCtx->cbCertEncoded, WOLFSSL_FILETYPE_ASN1, + CA_TYPE, NULL, NULL, 0, + GET_VERIFY_SETTING_CTX(ctx)) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG_EX("Failed to process user cert: %d.", ret); + } + } + } + } + else { + WOLFSSL_MSG_EX("Failed to open user cert store. Error: 0x%x.", GetLastError()); + ret = WOLFSSL_FAILURE; + } + + if (handle != NULL && !CertCloseStore(handle, 0)) { + WOLFSSL_MSG_EX("Failed to close user cert store."); + ret = WOLFSSL_FAILURE; + } + + return ret; +} + +DWORD WinStrToDwFlags(const char* dwFlags) { + if (!XSTRCMP(dwFlags, "CERT_SYSTEM_STORE_CURRENT_SERVICE")) { + return CERT_SYSTEM_STORE_CURRENT_SERVICE; + } + else if (!XSTRCMP(dwFlags, "CERT_SYSTEM_STORE_CURRENT_USER")) { + return CERT_SYSTEM_STORE_CURRENT_USER; + } + else if (!XSTRCMP(dwFlags, "CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY")) { + return CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY; + } + else if (!XSTRCMP(dwFlags, "CERT_SYSTEM_STORE_LOCAL_MACHINE")) { + return CERT_SYSTEM_STORE_LOCAL_MACHINE; + } + else if (!XSTRCMP(dwFlags, "CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE")) { + return CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE; + } + else if (!XSTRCMP(dwFlags, "CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY")) { + return CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY; + } + else if (!XSTRCMP(dwFlags, "CERT_SYSTEM_STORE_SERVICES")) { + return CERT_SYSTEM_STORE_SERVICES; + } + else if (!XSTRCMP(dwFlags, "CERT_SYSTEM_STORE_USERS")) { + return CERT_SYSTEM_STORE_USERS; + } + + return NULL; +} + +int wolfSSL_CTX_load_windows_user_CA_certs(WOLFSSL_CTX* ctx, const char* userStore, + const char* userDwFlags, const char* userPvPara) { + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_load_windows_user_CA_certs"); + ret = LoadUserCaCertsWindows(ctx, userStore, userDwFlags, userPvPara); + WOLFSSL_LEAVE("wolfSSL_CTX_load_windows_user_CA_certs", ret); + + return ret; +} +#endif + +#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 = (word32)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); + } + 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 = (word32)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); + } + 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); + } + 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); + 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, 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, 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 + +#ifdef WOLFSSL_SYS_CA_CERTS + +/* 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; +#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; + #else + /* 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; + } + #endif + } + + WOLFSSL_LEAVE("wolfSSL_CTX_set_default_verify_paths", ret); + + return ret; +} + +#endif /* WOLFSSL_SYS_CA_CERTS */ + +#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 = pSz; + ssl->buffers.serverDH_G.length = 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)) { + 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)) { + XFREE(pAlloc, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(gAlloc, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + 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) { + /* 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, 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 = pSz; + ctx->serverDH_G.length = 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) { + /* 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) { + /* 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. + * @oaram [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, pSz, g, gSz); + } + else { + /* Set p and g into SSL context. */ + res = wolfssl_ctx_set_tmp_dh(ctx, p, 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. + * @oaram [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. + * @oaram [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 paramters into SSL. */ + res = wolfSSL_SetTmpDH_buffer(ssl, dhFile.buffer, sz, format); + } + else { + /* Set encoded DH paramters 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/ssl_misc.c b/src/ssl_misc.c index 9bc42ddd9b..397dba6b2c 100644 --- a/src/ssl_misc.c +++ b/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, 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/ssl_p7p12.c b/src/ssl_p7p12.c new file mode 100644 index 0000000000..5c45407b0c --- /dev/null +++ b/src/ssl_p7p12.c @@ -0,0 +1,2122 @@ +/* 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, 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 = 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 = 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; + } + + 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 = 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; + } + 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 = 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--; + } + } + + 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 = ((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, 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, outLen, + bcontMem, 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, len, NULL, &sigBase64Len) != 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, 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(); + 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 = wc_i2d_PKCS12(pkcs12, &certDer, NULL); + if ((certSz > 0) && (certDer != NULL)) { + if (wolfSSL_BIO_write(bio, certDer, 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 = 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 = curDerSz; + cur->next = list; + list = cur; + + sk = sk->next; + numCerts--; + } + } + + pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz, + certDer, 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) != 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) != 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, 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/ssl_sess.c b/src/ssl_sess.c new file mode 100644 index 0000000000..4a2b1f7c27 --- /dev/null +++ b/src/ssl_sess.c @@ -0,0 +1,4535 @@ +/* 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 + } + +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; +} + + +/* + * 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, 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 +/* 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, to); + } + } +#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"); + + if (ssl->ctx->sessionCacheOff) { + WOLFSSL_MSG("Session Cache off"); + return NULL; + } + + 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 */ + + row = HashObject(id, 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 = 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 = 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 = 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 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) +{ + 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 = i; + break; + } + } + + 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; + +#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, 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/tls.c b/src/tls.c index a28568c69e..2db3c6ff74 100644 --- a/src/tls.c +++ b/src/tls.c @@ -586,47 +586,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); } @@ -6120,8 +6086,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 */ @@ -8437,7 +8407,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; @@ -9583,7 +9553,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 +9588,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); @@ -11212,8 +11182,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 { @@ -13570,7 +13542,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 +13772,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; @@ -14914,7 +14886,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 +14895,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/tls13.c b/src/tls13.c index 9a2e240cdd..fb07314dad 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1910,10 +1910,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 +2203,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 @@ -4234,7 +4238,7 @@ typedef struct Sch13Args { byte* output; word32 idx; int sendSz; - word16 length; + word32 length; #if defined(HAVE_ECH) int clientRandomOffset; int preXLength; @@ -4439,7 +4443,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) { #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 @@ -5285,6 +5289,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) { @@ -5386,7 +5391,10 @@ 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); #else @@ -7622,7 +7630,7 @@ 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; @@ -7821,9 +7829,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 +7864,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; @@ -7972,39 +8021,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; } @@ -8668,7 +8752,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 +8768,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 +8789,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); @@ -8813,11 +8908,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; @@ -8827,24 +8921,21 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) FreeDer(&ssl->buffers.key); } - /* 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; + 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); } @@ -8917,7 +9008,7 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) 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 +9017,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 +9026,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 +9054,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 + * temporarly, 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 + * temporarly, 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 = 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 +9146,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,23 +9155,60 @@ 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 (ssl->hsType == DYNAMIC_TYPE_FALCON) { - sig->length = FALCON_MAX_SIG_SIZE; + args->sigLen = FALCON_MAX_SIG_SIZE; } - #endif + #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_DILITHIUM */ #endif /* HAVE_PQC */ + #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; } /* case TLS_ASYNC_BUILD */ @@ -9061,21 +9216,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 +9247,62 @@ 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 (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 + #endif /* HAVE_FALCON */ #if defined(HAVE_DILITHIUM) 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_DILITHIUM */ #endif /* HAVE_PQC */ #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 +9312,78 @@ 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_PQC) + #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) + 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 */ + #endif /* HAVE_PQC */ + + /* 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 +9399,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 +9483,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; @@ -9442,8 +9643,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 +9667,54 @@ static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs) } #ifdef WOLFSSL_DUAL_ALG_CERTS +/* 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; +} + +/* 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; +} + /* 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 +9731,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; @@ -9514,10 +9759,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 +9771,7 @@ static int decodeFalconKey(WOLFSSL* ssl, int level) return 0; } -#endif +#endif /* WOLFSSL_DUAL_ALG_CERTS */ /* handle processing TLS v1.3 certificate_verify (15) */ /* Parse and handle a TLS v1.3 CertificateVerify message. @@ -9547,7 +9788,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); @@ -9634,8 +9879,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 +9913,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 +9923,12 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, sa = args->altSigAlgo; switch(sa) { + case rsa_pss_sa_algo: + ret = decodeRsaKey(ssl); + break; + case ecc_dsa_sa_algo: + ret = decodeEccKey(ssl); + break; case dilithium_level2_sa_algo: ret = decodeDilithiumKey(ssl, 2); break; @@ -9697,62 +9946,43 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, break; 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. */ + if (ssl->peerRsaKeyPresent && sa != rsa_pss_sa_algo) { FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); ssl->peerRsaKeyPresent = 0; } - else if (ssl->peerEccDsaKeyPresent) { + 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); + 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; + 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) { + 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 */ @@ -9831,61 +10061,86 @@ 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; + ato32(input + tmpIdx, &args->sigSz); + + tmpIdx += OPAQUE16_LEN + args->sigSz; + ato32(input + tmpIdx, &args->altSignatureSz); + + 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 +10153,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,16 +10176,31 @@ 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; ret = 0; @@ -9985,18 +10208,20 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } #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 +10229,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 +10254,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, #else NULL #endif - ); + ); if (ret >= 0) { /* CLIENT/SERVER: data verified with public key from @@ -10039,8 +10267,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 @@ -10061,44 +10291,19 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } #endif #if defined(HAVE_PQC) && defined(HAVE_FALCON) - if (ssl->peerFalconKeyPresent) { + 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); @@ -10107,44 +10312,20 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } #endif /* HAVE_PQC && HAVE_FALCON */ #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) - if (ssl->peerDilithiumKeyPresent) { + 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); @@ -10158,6 +10339,110 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, 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_PQC) && 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_PQC && HAVE_FALCON */ + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + 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_PQC && 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 +10452,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 +10470,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 +10491,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; @@ -14474,6 +14776,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/wolfio.c b/src/wolfio.c index 041e0b77d8..c7962f47f7 100644 --- a/src/wolfio.c +++ b/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 diff --git a/src/x509.c b/src/x509.c index eefa69cb27..56fd9aa402 100644 --- a/src/x509.c +++ b/src/x509.c @@ -10171,6 +10171,15 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( #endif #ifndef NO_DSA DsaKey* dsa = NULL; + #endif + #if defined(HAVE_PQC) && defined(HAVE_FALCON) + falcon_key* falcon = NULL; + #endif + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + dilithium_key* dilithium = NULL; + #endif + #if defined(HAVE_PQC) && defined(HAVE_SPHINCS) + sphincs_key* sphincs = NULL; #endif WC_RNG rng; word32 idx = 0; @@ -10297,6 +10306,148 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( } key = (void*)dsa; } + #endif + #if defined(HAVE_PQC) && 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_PQC) && 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_PQC) && 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 +10548,32 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( wc_FreeDsaKey(dsa); XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); } + #endif + #if defined(HAVE_PQC) && 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_PQC) && 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_PQC) && 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); @@ -11085,6 +11262,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) diff --git a/tests/api.c b/tests/api.c index c6c6cc90b4..e336f6877d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -348,9 +348,15 @@ #ifdef HAVE_PKCS7 #include #endif +#ifdef HAVE_CURVE25519 + #include +#endif #ifdef HAVE_ED25519 #include #endif +#ifdef HAVE_CURVE448 + #include +#endif #ifdef HAVE_ED448 #include #endif @@ -666,6 +672,93 @@ static int test_wolfCrypt_Cleanup(void) return EXPECT_RESULT(); } +static int test_wc_LoadStaticMemory_ex(void) +{ + EXPECT_DECLS; +#ifdef WOLFSSL_STATIC_MEMORY + byte staticMemory[440000]; + word32 sizeList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + word32 distList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; + WOLFSSL_HEAP_HINT* heap; + + /* Pass in zero everything. */ + ExpectIntEQ(wc_LoadStaticMemory_ex(NULL, 0, NULL, NULL, NULL, 0, 0, 0), + BAD_FUNC_ARG); + + /* Set the heap pointer to NULL. */ + ExpectIntEQ(wc_LoadStaticMemory_ex(NULL, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + + /* Set other pointer values to NULL one at a time. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, NULL, distList, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, NULL, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + NULL, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + /* Set the size of the static buffer to 0. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, 0, + 0, 1), + BUFFER_E); + + /* Set the size of the static buffer to one less than minimum allowed. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, + (word32)(sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) - 1, + 0, 1), + BUFFER_E); + + /* Set the number of buckets to 1 too many allowed. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_MAX_BUCKETS+1, sizeList, distList, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + BAD_FUNC_ARG); + + /* Set the size of the static buffer to exactly the minimum size. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, + (word32)(sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)), + 0, 1), + 0); + wc_UnloadStaticMemory(heap); + + /* Success case. */ + heap = NULL; + ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + staticMemory, (word32)sizeof(staticMemory), + 0, 1), + 0); + wc_UnloadStaticMemory(heap); +#endif /* WOLFSSL_STATIC_MEMORY */ + return EXPECT_RESULT(); +} + + /*----------------------------------------------------------------------------* | Platform dependent function test *----------------------------------------------------------------------------*/ @@ -878,7 +971,10 @@ static int do_dual_alg_root_certgen(byte **out, char *caKeyFile, XMEMSET(caKeyBuf, 0, caKeySz); ExpectNotNull(file = fopen(caKeyFile, "rb")); ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0); - fclose(file); + if (file) { + fclose(file); + file = NULL; + } ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0); idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey, caKeySz), @@ -886,11 +982,17 @@ static int do_dual_alg_root_certgen(byte **out, char *caKeyFile, XMEMSET(sapkiBuf, 0, sapkiSz); ExpectNotNull(file = fopen(sapkiFile, "rb")); ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0); - fclose(file); + if (file) { + fclose(file); + file = NULL; + } XMEMSET(altPrivBuf, 0, altPrivSz); ExpectNotNull(file = fopen(altPrivFile, "rb")); ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0); - fclose(file); + if (file) { + fclose(file); + file = NULL; + } wc_ecc_init(&altCaKey); idx = 0; ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey, @@ -938,6 +1040,7 @@ static int do_dual_alg_root_certgen(byte **out, char *caKeyFile, *out = outBuf; wc_FreeRsaKey(&caKey); wc_FreeRng(&rng); + wc_FreeDecodedCert(&preTBS); return outSz; } @@ -981,7 +1084,10 @@ static int do_dual_alg_server_certgen(byte **out, char *caKeyFile, ExpectNotNull(file = fopen(serverKeyFile, "rb")); ExpectIntGT(serverKeySz = (word32)fread(serverKeyBuf, 1, serverKeySz, file), 0); - fclose(file); + if (file) { + fclose(file); + file = NULL; + } ExpectIntEQ(wc_InitRsaKey_ex(&serverKey, NULL, INVALID_DEVID), 0); idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(serverKeyBuf, &idx, &serverKey, @@ -989,7 +1095,10 @@ static int do_dual_alg_server_certgen(byte **out, char *caKeyFile, XMEMSET(caKeyBuf, 0, caKeySz); ExpectNotNull(file = fopen(caKeyFile, "rb")); ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0); - fclose(file); + if (file) { + fclose(file); + file = NULL; + } ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0); idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey, @@ -997,11 +1106,17 @@ static int do_dual_alg_server_certgen(byte **out, char *caKeyFile, XMEMSET(sapkiBuf, 0, sapkiSz); ExpectNotNull(file = fopen(sapkiFile, "rb")); ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0); - fclose(file); + if (file) { + fclose(file); + file = NULL; + } XMEMSET(altPrivBuf, 0, altPrivSz); ExpectNotNull(file = fopen(altPrivFile, "rb")); ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0); - fclose(file); + if (file) { + fclose(file); + file = NULL; + } wc_ecc_init(&altCaKey); idx = 0; ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey, @@ -1052,6 +1167,7 @@ static int do_dual_alg_server_certgen(byte **out, char *caKeyFile, wc_FreeRsaKey(&caKey); wc_FreeRsaKey(&serverKey); wc_FreeRng(&rng); + wc_FreeDecodedCert(&preTBS); return outSz; } @@ -1136,7 +1252,9 @@ static int test_dual_alg_support(void) /* Now we try a negative case. Note that we use wrongPrivFile to generate * the alternative signature and then set negative_test to true for the * call to do_dual_alg_tls13_connection(). Its expecting a failed connection - * because the signature won't verify. */ + * because the signature won't verify. The exception is if + * WOLFSSL_TRUST_PEER_CERT is defined. In that case, no verfication happens + * and this is no longer a negative test. */ rootSz = do_dual_alg_root_certgen(&root, keyFile, sapkiFile, wrongPrivFile); ExpectNotNull(root); ExpectIntGT(rootSz, 0); @@ -1144,9 +1262,15 @@ static int test_dual_alg_support(void) wrongPrivFile, keyFile, root, rootSz); ExpectNotNull(server); ExpectIntGT(serverSz, 0); +#ifdef WOLFSSL_TRUST_PEER_CERT + ExpectIntEQ(do_dual_alg_tls13_connection(root, rootSz, + server, serverSz, serverKey, (word32)serverKeySz, 0), + TEST_SUCCESS); +#else ExpectIntEQ(do_dual_alg_tls13_connection(root, rootSz, server, serverSz, serverKey, (word32)serverKeySz, 1), TEST_SUCCESS); +#endif /* Lets see if CertManager can find the new extensions */ extCount = 0; @@ -1156,7 +1280,7 @@ static int test_dual_alg_support(void) SSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, server, serverSz, SSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); - /* There is only 1 unknown exension (1.2.3.4.5). The other ones are known + /* There is only 1 unknown extension (1.2.3.4.5). The other ones are known * because they are for the dual alg extensions. */ ExpectIntEQ(extCount, 1); wolfSSL_CertManagerFree(cm); @@ -2304,7 +2428,9 @@ static int test_wolfSSL_CertManagerAPI(void) #endif ExpectIntEQ(wolfSSL_CertManager_up_ref(cm), 1); - wolfSSL_CertManagerFree(cm); + if (EXPECT_SUCCESS()) { + wolfSSL_CertManagerFree(cm); + } wolfSSL_CertManagerFree(cm); cm = NULL; @@ -4971,6 +5097,90 @@ static int test_wolfSSL_SetMinVersion(void) #ifdef OPENSSL_EXTRA +static int test_EC25519(void) +{ + EXPECT_DECLS; +#if defined(HAVE_CURVE25519) && defined(WOLFSSL_KEY_GEN) + byte priv[CURVE25519_KEYSIZE]; + unsigned int privSz = CURVE25519_KEYSIZE; + byte pub[CURVE25519_KEYSIZE]; + unsigned int pubSz = CURVE25519_KEYSIZE; + byte priv2[CURVE25519_KEYSIZE]; + unsigned int priv2Sz = CURVE25519_KEYSIZE; + byte pub2[CURVE25519_KEYSIZE]; + unsigned int pub2Sz = CURVE25519_KEYSIZE; + byte shared[CURVE25519_KEYSIZE]; + unsigned int sharedSz = CURVE25519_KEYSIZE; + byte shared2[CURVE25519_KEYSIZE]; + unsigned int shared2Sz = CURVE25519_KEYSIZE; + + /* Bad parameter testing of key generation. */ + ExpectIntEQ(wolfSSL_EC25519_generate_key(NULL, NULL, NULL, NULL), 0); + ExpectIntEQ(wolfSSL_EC25519_generate_key(NULL, &privSz, NULL, &pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_generate_key(NULL, &privSz, pub, &pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_generate_key(priv, NULL, pub, &pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_generate_key(priv, &privSz, NULL, &pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_generate_key(priv, &privSz, pub, NULL), 0); + /* Bad length */ + privSz = 1; + ExpectIntEQ(wolfSSL_EC25519_generate_key(priv, &privSz, pub, &pubSz), 0); + privSz = CURVE25519_KEYSIZE; + pubSz = 1; + ExpectIntEQ(wolfSSL_EC25519_generate_key(priv, &privSz, pub, &pubSz), 0); + pubSz = CURVE25519_KEYSIZE; + + /* Good case of generating key. */ + ExpectIntEQ(wolfSSL_EC25519_generate_key(priv, &privSz, pub, &pubSz), 1); + ExpectIntEQ(wolfSSL_EC25519_generate_key(priv2, &priv2Sz, pub2, &pub2Sz), + 1); + ExpectIntEQ(privSz, CURVE25519_KEYSIZE); + ExpectIntEQ(pubSz, CURVE25519_KEYSIZE); + + /* Bad parameter testing of shared key. */ + ExpectIntEQ(wolfSSL_EC25519_shared_key( NULL, NULL, NULL, privSz, + NULL, pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_shared_key( NULL, &sharedSz, NULL, privSz, + NULL, pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_shared_key( NULL, &sharedSz, priv, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared, &sharedSz, NULL, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared, &sharedSz, priv, privSz, + NULL, pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_shared_key( NULL, &sharedSz, priv, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared, NULL, priv, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared, &sharedSz, NULL, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared, &sharedSz, priv, privSz, + NULL, pubSz), 0); + /* Bad length. */ + sharedSz = 1; + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared, &sharedSz, priv, privSz, + pub, pubSz), 0); + sharedSz = CURVE25519_KEYSIZE; + privSz = 1; + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared, &sharedSz, priv, privSz, + pub, pubSz), 0); + privSz = CURVE25519_KEYSIZE; + pubSz = 1; + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared, &sharedSz, priv, privSz, + pub, pubSz), 0); + pubSz = CURVE25519_KEYSIZE; + + /* Good case of shared key. */ + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared, &sharedSz, priv, privSz, + pub2, pub2Sz), 1); + ExpectIntEQ(wolfSSL_EC25519_shared_key(shared2, &shared2Sz, priv2, priv2Sz, + pub, pubSz), 1); + ExpectIntEQ(sharedSz, CURVE25519_KEYSIZE); + ExpectIntEQ(shared2Sz, CURVE25519_KEYSIZE); + ExpectIntEQ(XMEMCMP(shared, shared2, sharedSz), 0); +#endif /* HAVE_CURVE25519 && WOLFSSL_KEY_GEN */ + return EXPECT_RESULT(); +} + static int test_ED25519(void) { EXPECT_DECLS; @@ -4987,25 +5197,189 @@ static int test_ED25519(void) unsigned int sigSz = (unsigned int)sizeof(sig); #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_IMPORT */ + /* Bad parameter testing of key generation. */ + ExpectIntEQ(wolfSSL_ED25519_generate_key(NULL, NULL, NULL, NULL), 0); + ExpectIntEQ(wolfSSL_ED25519_generate_key(priv, NULL, NULL, NULL), 0); + ExpectIntEQ(wolfSSL_ED25519_generate_key(NULL, &privSz, NULL, NULL), 0); + ExpectIntEQ(wolfSSL_ED25519_generate_key(NULL, NULL, pub, NULL), 0); + ExpectIntEQ(wolfSSL_ED25519_generate_key(NULL, NULL, NULL, &pubSz), 0); + ExpectIntEQ(wolfSSL_ED25519_generate_key(NULL, &privSz, pub, &pubSz), 0); + ExpectIntEQ(wolfSSL_ED25519_generate_key(priv, NULL, pub, &pubSz), 0); + ExpectIntEQ(wolfSSL_ED25519_generate_key(priv, &privSz, NULL, &pubSz), 0); + ExpectIntEQ(wolfSSL_ED25519_generate_key(priv, &privSz, pub, NULL), 0); + /* Bad length. */ + privSz = 1; + ExpectIntEQ(wolfSSL_ED25519_generate_key(priv, &privSz, pub, &pubSz), 0); + privSz = ED25519_PRV_KEY_SIZE; + pubSz = 1; + ExpectIntEQ(wolfSSL_ED25519_generate_key(priv, &privSz, pub, &pubSz), 0); + pubSz = ED25519_PUB_KEY_SIZE; + + /* Good case of generating key. */ ExpectIntEQ(wolfSSL_ED25519_generate_key(priv, &privSz, pub, &pubSz), - WOLFSSL_SUCCESS); + 1); ExpectIntEQ(privSz, ED25519_PRV_KEY_SIZE); ExpectIntEQ(pubSz, ED25519_PUB_KEY_SIZE); #if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_IMPORT) + /* Bad parameter testing of signing. */ + ExpectIntEQ(wolfSSL_ED25519_sign( NULL, msglen, NULL, privSz, NULL, + NULL), 0); + ExpectIntEQ(wolfSSL_ED25519_sign((byte*)msg, msglen, NULL, privSz, NULL, + NULL), 0); + ExpectIntEQ(wolfSSL_ED25519_sign( NULL, msglen, priv, privSz, NULL, + NULL), 0); + ExpectIntEQ(wolfSSL_ED25519_sign( NULL, msglen, NULL, privSz, sig, + NULL), 0); + ExpectIntEQ(wolfSSL_ED25519_sign( NULL, msglen, NULL, privSz, NULL, + &sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_sign( NULL, msglen, priv, privSz, sig, + &sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_sign((byte*)msg, msglen, NULL, privSz, sig, + &sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_sign((byte*)msg, msglen, priv, privSz, NULL, + &sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_sign((byte*)msg, msglen, priv, privSz, sig, + NULL), 0); + /* Bad length. */ + privSz = 1; + ExpectIntEQ(wolfSSL_ED25519_sign((byte*)msg, msglen, priv, privSz, sig, + &sigSz), 0); + privSz = ED25519_PRV_KEY_SIZE; + sigSz = 1; ExpectIntEQ(wolfSSL_ED25519_sign((byte*)msg, msglen, priv, privSz, sig, - &sigSz), WOLFSSL_SUCCESS); + &sigSz), 0); + sigSz = ED25519_SIG_SIZE; + + /* Good case of signing. */ + ExpectIntEQ(wolfSSL_ED25519_sign((byte*)msg, msglen, priv, privSz, sig, + &sigSz), 1); ExpectIntEQ(sigSz, ED25519_SIG_SIZE); #ifdef HAVE_ED25519_VERIFY + /* Bad parameter testing of verification. */ + ExpectIntEQ(wolfSSL_ED25519_verify( NULL, msglen, NULL, pubSz, NULL, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_verify((byte*)msg, msglen, NULL, pubSz, NULL, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_verify( NULL, msglen, pub, pubSz, NULL, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_verify( NULL, msglen, NULL, pubSz, sig, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_verify( NULL, msglen, pub, pubSz, sig, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_verify((byte*)msg, msglen, NULL, pubSz, sig, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED25519_verify((byte*)msg, msglen, pub, pubSz, NULL, + sigSz), 0); + /* Bad length. */ + pubSz = 1; + ExpectIntEQ(wolfSSL_ED25519_verify((byte*)msg, msglen, pub, pubSz, sig, + sigSz), 0); + pubSz = ED25519_PUB_KEY_SIZE; + sigSz = 1; + ExpectIntEQ(wolfSSL_ED25519_verify((byte*)msg, msglen, pub, pubSz, sig, + sigSz), 0); + sigSz = ED25519_SIG_SIZE; + + /* Good case of verification. */ ExpectIntEQ(wolfSSL_ED25519_verify((byte*)msg, msglen, pub, pubSz, sig, - sigSz), WOLFSSL_SUCCESS); + sigSz), 1); + /* Bad signature. */ + if (EXPECT_SUCCESS()) { + sig[1] ^= 0x80; + } + ExpectIntEQ(wolfSSL_ED25519_verify((byte*)msg, msglen, pub, pubSz, sig, + sigSz), 0); #endif /* HAVE_ED25519_VERIFY */ #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_IMPORT */ #endif /* HAVE_ED25519 && HAVE_ED25519_KEY_EXPORT && WOLFSSL_KEY_GEN */ return EXPECT_RESULT(); } +static int test_EC448(void) +{ + EXPECT_DECLS; +#if defined(HAVE_CURVE448) && defined(WOLFSSL_KEY_GEN) + byte priv[CURVE448_KEY_SIZE]; + unsigned int privSz = CURVE448_KEY_SIZE; + byte pub[CURVE448_KEY_SIZE]; + unsigned int pubSz = CURVE448_KEY_SIZE; + byte priv2[CURVE448_KEY_SIZE]; + unsigned int priv2Sz = CURVE448_KEY_SIZE; + byte pub2[CURVE448_KEY_SIZE]; + unsigned int pub2Sz = CURVE448_KEY_SIZE; + byte shared[CURVE448_KEY_SIZE]; + unsigned int sharedSz = CURVE448_KEY_SIZE; + byte shared2[CURVE448_KEY_SIZE]; + unsigned int shared2Sz = CURVE448_KEY_SIZE; + + /* Bad parameter testing of key generation. */ + ExpectIntEQ(wolfSSL_EC448_generate_key(NULL, NULL, NULL, NULL), 0); + ExpectIntEQ(wolfSSL_EC448_generate_key(NULL, &privSz, NULL, &pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_generate_key(NULL, &privSz, pub, &pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_generate_key(priv, NULL, pub, &pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_generate_key(priv, &privSz, NULL, &pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_generate_key(priv, &privSz, pub, NULL), 0); + /* Bad length. */ + privSz = 1; + ExpectIntEQ(wolfSSL_EC448_generate_key(priv, &privSz, pub, &pubSz), 0); + privSz = CURVE448_KEY_SIZE; + pubSz = 1; + ExpectIntEQ(wolfSSL_EC448_generate_key(priv, &privSz, pub, &pubSz), 0); + pubSz = CURVE448_KEY_SIZE; + + /* Good case of generating key. */ + ExpectIntEQ(wolfSSL_EC448_generate_key(priv, &privSz, pub, &pubSz), 1); + ExpectIntEQ(wolfSSL_EC448_generate_key(priv2, &priv2Sz, pub2, &pub2Sz), 1); + ExpectIntEQ(privSz, CURVE448_KEY_SIZE); + ExpectIntEQ(pubSz, CURVE448_KEY_SIZE); + + /* Bad parameter testing of shared key. */ + ExpectIntEQ(wolfSSL_EC448_shared_key( NULL, NULL, NULL, privSz, + NULL, pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_shared_key( NULL, &sharedSz, NULL, privSz, + NULL, pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_shared_key( NULL, &sharedSz, priv, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_shared_key(shared, &sharedSz, NULL, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_shared_key(shared, &sharedSz, priv, privSz, + NULL, pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_shared_key( NULL, &sharedSz, priv, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_shared_key(shared, NULL, priv, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_shared_key(shared, &sharedSz, NULL, privSz, + pub, pubSz), 0); + ExpectIntEQ(wolfSSL_EC448_shared_key(shared, &sharedSz, priv, privSz, + NULL, pubSz), 0); + /* Bad length. */ + sharedSz = 1; + ExpectIntEQ(wolfSSL_EC448_shared_key(shared, &sharedSz, priv, privSz, + pub, pubSz), 0); + sharedSz = CURVE448_KEY_SIZE; + privSz = 1; + ExpectIntEQ(wolfSSL_EC448_shared_key(shared, &sharedSz, priv, privSz, + pub, pubSz), 0); + privSz = CURVE448_KEY_SIZE; + pubSz = 1; + ExpectIntEQ(wolfSSL_EC448_shared_key(shared, &sharedSz, priv, privSz, + pub, pubSz), 0); + pubSz = CURVE448_KEY_SIZE; + + /* Good case of shared key. */ + ExpectIntEQ(wolfSSL_EC448_shared_key(shared, &sharedSz, priv, privSz, + pub2, pub2Sz), 1); + ExpectIntEQ(wolfSSL_EC448_shared_key(shared2, &shared2Sz, priv2, priv2Sz, + pub, pubSz), 1); + ExpectIntEQ(sharedSz, CURVE448_KEY_SIZE); + ExpectIntEQ(shared2Sz, CURVE448_KEY_SIZE); + ExpectIntEQ(XMEMCMP(shared, shared2, sharedSz), 0); +#endif /* HAVE_CURVE448 && WOLFSSL_KEY_GEN */ + return EXPECT_RESULT(); +} + static int test_ED448(void) { EXPECT_DECLS; @@ -5022,19 +5396,99 @@ static int test_ED448(void) unsigned int sigSz = (unsigned int)sizeof(sig); #endif /* HAVE_ED448_SIGN && HAVE_ED448_KEY_IMPORT */ - ExpectIntEQ(wolfSSL_ED448_generate_key(priv, &privSz, pub, &pubSz), - WOLFSSL_SUCCESS); + /* Bad parameter testing of key generation. */ + ExpectIntEQ(wolfSSL_ED448_generate_key(NULL, NULL, NULL, NULL), 0); + ExpectIntEQ(wolfSSL_ED448_generate_key(priv, NULL, NULL, NULL), 0); + ExpectIntEQ(wolfSSL_ED448_generate_key(NULL, &privSz, NULL, NULL), 0); + ExpectIntEQ(wolfSSL_ED448_generate_key(NULL, NULL, pub, NULL), 0); + ExpectIntEQ(wolfSSL_ED448_generate_key(NULL, NULL, NULL, &pubSz), 0); + ExpectIntEQ(wolfSSL_ED448_generate_key(NULL, &privSz, pub, &pubSz), 0); + ExpectIntEQ(wolfSSL_ED448_generate_key(priv, NULL, pub, &pubSz), 0); + ExpectIntEQ(wolfSSL_ED448_generate_key(priv, &privSz, NULL, &pubSz), 0); + ExpectIntEQ(wolfSSL_ED448_generate_key(priv, &privSz, pub, NULL), 0); + /* Bad length. */ + privSz = 1; + ExpectIntEQ(wolfSSL_ED448_generate_key(priv, &privSz, pub, &pubSz), 0); + privSz = ED448_PRV_KEY_SIZE; + pubSz = 1; + ExpectIntEQ(wolfSSL_ED448_generate_key(priv, &privSz, pub, &pubSz), 0); + pubSz = ED448_PUB_KEY_SIZE; + + /* Good case of generating key. */ + ExpectIntEQ(wolfSSL_ED448_generate_key(priv, &privSz, pub, &pubSz), 1); ExpectIntEQ(privSz, ED448_PRV_KEY_SIZE); ExpectIntEQ(pubSz, ED448_PUB_KEY_SIZE); #if defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_KEY_IMPORT) + /* Bad parameter testing of signing. */ + ExpectIntEQ(wolfSSL_ED448_sign( NULL, msglen, NULL, privSz, NULL, + NULL), 0); + ExpectIntEQ(wolfSSL_ED448_sign((byte*)msg, msglen, NULL, privSz, NULL, + NULL), 0); + ExpectIntEQ(wolfSSL_ED448_sign( NULL, msglen, priv, privSz, NULL, + NULL), 0); + ExpectIntEQ(wolfSSL_ED448_sign( NULL, msglen, NULL, privSz, sig, + NULL), 0); + ExpectIntEQ(wolfSSL_ED448_sign( NULL, msglen, NULL, privSz, NULL, + &sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_sign( NULL, msglen, priv, privSz, sig, + &sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_sign((byte*)msg, msglen, NULL, privSz, sig, + &sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_sign((byte*)msg, msglen, priv, privSz, NULL, + &sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_sign((byte*)msg, msglen, priv, privSz, sig, + NULL), 0); + /* Bad length. */ + privSz = 1; ExpectIntEQ(wolfSSL_ED448_sign((byte*)msg, msglen, priv, privSz, sig, - &sigSz), WOLFSSL_SUCCESS); + &sigSz), 0); + privSz = ED448_PRV_KEY_SIZE; + sigSz = 1; + ExpectIntEQ(wolfSSL_ED448_sign((byte*)msg, msglen, priv, privSz, sig, + &sigSz), 0); + sigSz = ED448_SIG_SIZE; + + /* Good case of signing. */ + ExpectIntEQ(wolfSSL_ED448_sign((byte*)msg, msglen, priv, privSz, sig, + &sigSz), 1); ExpectIntEQ(sigSz, ED448_SIG_SIZE); #ifdef HAVE_ED448_VERIFY + /* Bad parameter testing of verification. */ + ExpectIntEQ(wolfSSL_ED448_verify( NULL, msglen, NULL, pubSz, NULL, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_verify((byte*)msg, msglen, NULL, pubSz, NULL, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_verify( NULL, msglen, pub, pubSz, NULL, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_verify( NULL, msglen, NULL, pubSz, sig, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_verify( NULL, msglen, pub, pubSz, sig, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_verify((byte*)msg, msglen, NULL, pubSz, sig, + sigSz), 0); + ExpectIntEQ(wolfSSL_ED448_verify((byte*)msg, msglen, pub, pubSz, NULL, + sigSz), 0); + /* Bad length. */ + pubSz = 1; + ExpectIntEQ(wolfSSL_ED448_verify((byte*)msg, msglen, pub, pubSz, sig, + sigSz), 0); + pubSz = ED448_PUB_KEY_SIZE; + sigSz = 1; + ExpectIntEQ(wolfSSL_ED448_verify((byte*)msg, msglen, pub, pubSz, sig, + sigSz), 0); + sigSz = ED448_SIG_SIZE; + + /* Good case of verification. */ ExpectIntEQ(wolfSSL_ED448_verify((byte*)msg, msglen, pub, pubSz, sig, - sigSz), WOLFSSL_SUCCESS); + sigSz), 1); + /* Bad signature. */ + if (EXPECT_SUCCESS()) { + sig[1] ^= 0x80; + } + ExpectIntEQ(wolfSSL_ED448_verify((byte*)msg, msglen, pub, pubSz, sig, + sigSz), 0); #endif /* HAVE_ED448_VERIFY */ #endif /* HAVE_ED448_SIGN && HAVE_ED448_KEY_IMPORT */ #endif /* HAVE_ED448 && HAVE_ED448_KEY_EXPORT && WOLFSSL_KEY_GEN */ @@ -6983,8 +7437,8 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) !defined(WOLFSSL_NO_TLS12) static THREAD_RETURN WOLFSSL_THREAD test_server_loop(void* args) { - SOCKET_T sockfd = 0; - SOCKET_T clientfd = 0; + SOCKET_T sockfd; + SOCKET_T clientfd = -1; word16 port; callback_functions* cbf; @@ -7147,6 +7601,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_loop(void* args) wolfSSL_shutdown(ssl); wolfSSL_free(ssl); ssl = NULL; CloseSocket(clientfd); + clientfd = -1; count++; } @@ -7164,7 +7619,8 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_loop(void* args) if (!sharedCtx) wolfSSL_CTX_free(ctx); - CloseSocket(clientfd); + if (clientfd >= 0) + CloseSocket(clientfd); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); @@ -12138,7 +12594,7 @@ static int test_wolfSSL_PKCS8(void) XFILE f = XBADFILE; int bytes = 0; WOLFSSL_CTX* ctx = NULL; -#if defined(HAVE_ECC) && !defined(NO_CODING) +#if defined(HAVE_ECC) && !defined(NO_CODING) && !defined(WOLFSSL_NO_PEM) int ret; ecc_key key; word32 x = 0; @@ -12298,7 +12754,7 @@ static int test_wolfSSL_PKCS8(void) ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); -#ifndef NO_CODING +#if !defined(NO_CODING) && !defined(WOLFSSL_NO_PEM) /* decrypt PKCS8 PEM to key in DER format */ ExpectIntGT((bytes = wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), NULL)), 0); @@ -22438,7 +22894,9 @@ static int test_wc_ed25519_import_private_key(void) ExpectIntEQ(XMEMCMP(privKey, key.k, pubKeySz), 0); #ifdef HAVE_ED25519_KEY_EXPORT + PRIVATE_KEY_UNLOCK(); ExpectIntEQ(wc_ed25519_export_private(&key, bothKeys, &bothKeysSz), 0); + PRIVATE_KEY_LOCK(); ExpectIntEQ(wc_ed25519_import_private_key_ex(bothKeys, bothKeysSz, NULL, 0, &key, 1), 0); ExpectIntEQ(XMEMCMP(pubKey, key.p, privKeySz), 0); @@ -22505,6 +22963,7 @@ static int test_wc_ed25519_export(void) pubKey, sizeof(pubKey), &key, 1), 0); #endif + PRIVATE_KEY_UNLOCK(); ExpectIntEQ(wc_ed25519_export_public(&key, pub, &pubSz), 0); ExpectIntEQ(pubSz, ED25519_KEY_SIZE); ExpectIntEQ(XMEMCMP(key.p, pub, pubSz), 0); @@ -22523,6 +22982,7 @@ static int test_wc_ed25519_export(void) BAD_FUNC_ARG); ExpectIntEQ(wc_ed25519_export_private_only(&key, priv, NULL), BAD_FUNC_ARG); + PRIVATE_KEY_LOCK(); DoExpectIntEQ(wc_FreeRng(&rng), 0); wc_ed25519_free(&key); @@ -22630,6 +23090,7 @@ static int test_wc_ed25519_exportKey(void) pubKey, sizeof(pubKey), &key, 1), 0); #endif + PRIVATE_KEY_UNLOCK(); ExpectIntEQ(wc_ed25519_export_private(&key, privOnly, &privOnlySz), 0); /* Test bad args. */ ExpectIntEQ(wc_ed25519_export_private(NULL, privOnly, &privOnlySz), @@ -22650,6 +23111,7 @@ static int test_wc_ed25519_exportKey(void) BAD_FUNC_ARG); ExpectIntEQ(wc_ed25519_export_key(&key, priv, &privSz, pub, NULL), BAD_FUNC_ARG); + PRIVATE_KEY_LOCK(); /* Cross check output. */ ExpectIntEQ(XMEMCMP(priv, privOnly, privSz), 0); @@ -23383,7 +23845,9 @@ static int test_wc_ed448_import_private_key(void) ExpectIntEQ(XMEMCMP(privKey, key.k, pubKeySz), 0); #ifdef HAVE_ED448_KEY_EXPORT + PRIVATE_KEY_UNLOCK(); ExpectIntEQ(wc_ed448_export_private(&key, bothKeys, &bothKeysSz), 0); + PRIVATE_KEY_LOCK(); ExpectIntEQ(wc_ed448_import_private_key_ex(bothKeys, bothKeysSz, NULL, 0, &key, 1), 0); ExpectIntEQ(XMEMCMP(pubKey, key.p, privKeySz), 0); @@ -23439,6 +23903,7 @@ static int test_wc_ed448_export(void) ExpectIntEQ(wc_ed448_export_public(&key, NULL, &pubSz), BAD_FUNC_ARG); ExpectIntEQ(wc_ed448_export_public(&key, pub, NULL), BAD_FUNC_ARG); + PRIVATE_KEY_UNLOCK(); ExpectIntEQ(wc_ed448_export_private_only(&key, priv, &privSz), 0); ExpectIntEQ(privSz, ED448_KEY_SIZE); ExpectIntEQ(XMEMCMP(key.k, priv, privSz), 0); @@ -23448,6 +23913,7 @@ static int test_wc_ed448_export(void) ExpectIntEQ(wc_ed448_export_private_only(&key, NULL, &privSz), BAD_FUNC_ARG); ExpectIntEQ(wc_ed448_export_private_only(&key, priv, NULL), BAD_FUNC_ARG); + PRIVATE_KEY_LOCK(); DoExpectIntEQ(wc_FreeRng(&rng), 0); wc_ed448_free(&key); @@ -23517,6 +23983,7 @@ static int test_wc_ed448_exportKey(void) ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &key), 0); + PRIVATE_KEY_UNLOCK(); ExpectIntEQ(wc_ed448_export_private(&key, privOnly, &privOnlySz), 0); /* Test bad args. */ ExpectIntEQ(wc_ed448_export_private(NULL, privOnly, &privOnlySz), @@ -23536,6 +24003,7 @@ static int test_wc_ed448_exportKey(void) BAD_FUNC_ARG); ExpectIntEQ(wc_ed448_export_key(&key, priv, &privSz, pub, NULL), BAD_FUNC_ARG); + PRIVATE_KEY_LOCK(); /* Cross check output. */ ExpectIntEQ(XMEMCMP(priv, privOnly, privSz), 0); @@ -24398,10 +24866,15 @@ static int test_wc_ecc_import_x963(void) ExpectIntEQ(wc_ecc_init(&pubKey), 0); ExpectIntEQ(wc_ecc_init(&key), 0); ExpectIntEQ(wc_InitRng(&rng), 0); +#if FIPS_VERSION3_GE(6,0,0) + ret = wc_ecc_make_key(&rng, KEY32, &key); +#else ret = wc_ecc_make_key(&rng, KEY24, &key); +#endif #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE); #endif + ExpectIntEQ(ret, 0); PRIVATE_KEY_UNLOCK(); @@ -25099,7 +25572,11 @@ static int test_wc_ecc_shared_secret_ssh(void) WC_RNG rng; int ret; int keySz = KEY32; +#if FIPS_VERSION3_GE(6,0,0) + int key2Sz = KEY28; +#else int key2Sz = KEY24; +#endif byte secret[KEY32]; word32 secretLen = keySz; @@ -25398,9 +25875,17 @@ static int test_wc_ecc_sig_size_calc(void) #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE); #endif +#if FIPS_VERSION3_GE(6,0,0) + ExpectIntEQ(ret, BAD_FUNC_ARG); +#else ExpectIntEQ(ret, 0); +#endif +#if FIPS_VERSION3_LT(6,0,0) sz = key.dp->size; ExpectIntGT(wc_ecc_sig_size_calc(sz), 0); +#else + (void) sz; +#endif DoExpectIntEQ(wc_FreeRng(&rng), 0); wc_ecc_free(&key); @@ -27035,7 +27520,7 @@ static int test_wc_PKCS7_EncodeSignedData(void) /* reinitialize and test setting stream mode */ { - int signedSz; + int signedSz = 0; encodeSignedDataStream strm; ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); @@ -29939,7 +30424,7 @@ static int test_wc_i2d_PKCS12(void) EXPECT_DECLS; #if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) \ && !defined(NO_FILESYSTEM) && !defined(NO_RSA) \ - && !defined(NO_AES) && !defined(NO_DES3) && !defined(NO_SHA) + && !defined(NO_AES) && !defined(NO_SHA) WC_PKCS12* pkcs12 = NULL; unsigned char der[FOURK_BUF * 2]; unsigned char* pt; @@ -34283,29 +34768,79 @@ static int test_wolfSSL_private_keys(void) return EXPECT_RESULT(); } +static int test_wolfSSL_PEM_def_callback(void) +{ + EXPECT_DECLS; +#ifdef OPENSSL_EXTRA + char buf[10]; + const char* defpwd = "DEF PWD"; + int defpwdLen = (int)XSTRLEN(defpwd); + int smallLen = 1; + + /* Bad parameters. */ + ExpectIntEQ(wolfSSL_PEM_def_callback(NULL, sizeof(buf), 0, NULL), 0); + ExpectIntEQ(wolfSSL_PEM_def_callback(NULL, sizeof(buf), 0, (void*)defpwd), + 0); + ExpectIntEQ(wolfSSL_PEM_def_callback(buf, sizeof(buf), 0, NULL), 0); + + XMEMSET(buf, 0, sizeof(buf)); + ExpectIntEQ(wolfSSL_PEM_def_callback(buf, sizeof(buf), 0, (void*)defpwd), + defpwdLen); + ExpectIntEQ(XMEMCMP(buf, defpwd, defpwdLen), 0); + ExpectIntEQ(buf[defpwdLen], 0); + /* Size of buffer is smaller than default password. */ + XMEMSET(buf, 0, sizeof(buf)); + ExpectIntEQ(wolfSSL_PEM_def_callback(buf, smallLen, 0, (void*)defpwd), + smallLen); + ExpectIntEQ(XMEMCMP(buf, defpwd, smallLen), 0); + ExpectIntEQ(buf[smallLen], 0); +#endif /* OPENSSL_EXTRA */ + return EXPECT_RESULT(); +} + static int test_wolfSSL_PEM_read_PrivateKey(void) { EXPECT_DECLS; -#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) \ - && !defined(NO_FILESYSTEM) +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && (!defined(NO_RSA) || \ + !defined(NO_DSA) || defined(HAVE_ECC) || !defined(NO_DH)) XFILE file = XBADFILE; - const char* fname = "./certs/server-key.pem"; - EVP_PKEY* pkey = NULL; +#if !defined(NO_RSA) + const char* fname_rsa = "./certs/server-key.pem"; RSA* rsa = NULL; WOLFSSL_EVP_PKEY_CTX* ctx = NULL; unsigned char* sig = NULL; size_t sigLen = 0; const unsigned char tbs[] = {0, 1, 2, 3, 4, 5, 6, 7}; size_t tbsLen = sizeof(tbs); +#endif +#if !defined(NO_DSA) + const char* fname_dsa = "./certs/dsa2048.pem"; +#endif +#if defined(HAVE_ECC) + const char* fname_ec = "./certs/ecc-key.pem"; +#endif +#if !defined(NO_DH) + const char* fname_dh = "./certs/dh-priv-2048.pem"; +#endif + EVP_PKEY* pkey = NULL; /* Check error case. */ ExpectNull(pkey = PEM_read_PrivateKey(NULL, NULL, NULL, NULL)); + /* not a PEM key. */ + ExpectTrue((file = XFOPEN("./certs/ecc-key.der", "rb")) != XBADFILE); + ExpectNull(PEM_read_PrivateKey(file, NULL, NULL, NULL)); + if (file != XBADFILE) + XFCLOSE(file); + file = XBADFILE; + +#ifndef NO_RSA /* Read in an RSA key. */ - ExpectTrue((file = XFOPEN(fname, "rb")) != XBADFILE); + ExpectTrue((file = XFOPEN(fname_rsa, "rb")) != XBADFILE); ExpectNotNull(pkey = PEM_read_PrivateKey(file, NULL, NULL, NULL)); if (file != XBADFILE) XFCLOSE(file); + file = XBADFILE; /* Make sure the key is usable by signing some data with it. */ ExpectNotNull(rsa = EVP_PKEY_get0_RSA(pkey)); @@ -34320,6 +34855,52 @@ static int test_wolfSSL_PEM_read_PrivateKey(void) XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); + pkey = NULL; +#endif + +#ifndef NO_DSA + /* Read in a DSA key. */ + ExpectTrue((file = XFOPEN(fname_dsa, "rb")) != XBADFILE); +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) + ExpectNotNull(pkey = PEM_read_PrivateKey(file, NULL, NULL, NULL)); + EVP_PKEY_free(pkey); + pkey = NULL; +#else + ExpectNull(PEM_read_PrivateKey(file, NULL, NULL, NULL)); +#endif + if (file != XBADFILE) + XFCLOSE(file); + file = XBADFILE; +#endif + +#ifdef HAVE_ECC + /* Read in an EC key. */ + ExpectTrue((file = XFOPEN(fname_ec, "rb")) != XBADFILE); + ExpectNotNull(pkey = EVP_PKEY_new()); + ExpectPtrEq(PEM_read_PrivateKey(file, &pkey, NULL, NULL), pkey); + if (file != XBADFILE) + XFCLOSE(file); + file = XBADFILE; + EVP_PKEY_free(pkey); + pkey = NULL; +#endif + +#ifndef NO_DH + /* Read in a DH key. */ + ExpectTrue((file = XFOPEN(fname_dh, "rb")) != XBADFILE); +#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || \ + defined(WOLFSSL_OPENSSH)) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + ExpectNotNull(pkey = PEM_read_PrivateKey(file, NULL, NULL, NULL)); + EVP_PKEY_free(pkey); + pkey = NULL; +#else + ExpectNull(PEM_read_PrivateKey(file, NULL, NULL, NULL)); +#endif + if (file != XBADFILE) + XFCLOSE(file); + file = XBADFILE; +#endif #endif return EXPECT_RESULT(); } @@ -34340,280 +34921,440 @@ static int test_wolfSSL_PEM_read_PUBKEY(void) ExpectTrue((file = XFOPEN(fname, "rb")) != XBADFILE); ExpectNotNull(pkey = PEM_read_PUBKEY(file, NULL, NULL, NULL)); EVP_PKEY_free(pkey); + pkey = NULL; + if (file != XBADFILE) + XFCLOSE(file); + file = XBADFILE; + ExpectTrue((file = XFOPEN(fname, "rb")) != XBADFILE); + ExpectNotNull(pkey = EVP_PKEY_new()); + ExpectPtrEq(PEM_read_PUBKEY(file, &pkey, NULL, NULL), pkey); + EVP_PKEY_free(pkey); if (file != XBADFILE) XFCLOSE(file); #endif return EXPECT_RESULT(); } -static int test_wolfSSL_PEM_PrivateKey(void) +/* test loading RSA key using BIO */ +static int test_wolfSSL_PEM_PrivateKey_rsa(void) { EXPECT_DECLS; -#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ - (!defined(NO_RSA) || defined(HAVE_ECC)) && defined(USE_CERT_BUFFERS_2048) -#ifndef NO_BIO +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_RSA) && \ + defined(USE_CERT_BUFFERS_2048) && !defined(NO_FILESYSTEM) && \ + !defined(NO_BIO) BIO* bio = NULL; -#endif + XFILE file = XBADFILE; + const char* fname = "./certs/server-key.pem"; + const char* fname_rsa_p8 = "./certs/server-keyPkcs8.pem"; EVP_PKEY* pkey = NULL; + size_t sz = 0; + byte* buf = NULL; + EVP_PKEY* pkey2 = NULL; + EVP_PKEY* pkey3 = NULL; + RSA* rsa_key = NULL; +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) + unsigned char extra[10]; + int i; + BIO* pub_bio = NULL; const unsigned char* server_key = (const unsigned char*)server_key_der_2048; +#endif -#ifndef NO_BIO + ExpectTrue((file = XFOPEN(fname, "rb")) != XBADFILE); + ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); + ExpectIntGT(sz = XFTELL(file), 0); + ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); + ExpectNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + if (buf != NULL) { + ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); + } + if (file != XBADFILE) { + XFCLOSE(file); + file = XBADFILE; + } - /* test creating new EVP_PKEY with bad arg */ - ExpectNull((pkey = PEM_read_bio_PrivateKey(NULL, NULL, NULL, NULL))); + /* Test using BIO new mem and loading PEM private key */ + ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + ExpectNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + buf = NULL; + BIO_free(bio); + bio = NULL; - /* test loading RSA key using BIO */ -#if !defined(NO_RSA) && !defined(NO_FILESYSTEM) - { - XFILE file = XBADFILE; - const char* fname = "./certs/server-key.pem"; - const char* fname_rsa_p8 = "./certs/server-keyPkcs8.pem"; + /* New empty EVP_PKEY */ + ExpectNotNull(pkey2 = EVP_PKEY_new()); + if (pkey2 != NULL) { + pkey2->type = EVP_PKEY_RSA; + } + /* Test parameter copy */ + ExpectIntEQ(EVP_PKEY_copy_parameters(pkey2, pkey), 0); + EVP_PKEY_free(pkey2); + EVP_PKEY_free(pkey); + pkey = NULL; - size_t sz = 0; - byte* buf = NULL; - EVP_PKEY* pkey2 = NULL; - EVP_PKEY* pkey3 = NULL; - RSA* rsa_key = NULL; + /* Qt unit test case : rsa pkcs8 key */ + ExpectTrue((file = XFOPEN(fname_rsa_p8, "rb")) != XBADFILE); + ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); + ExpectIntGT(sz = XFTELL(file), 0); + ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); + ExpectNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + if (buf) { + ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); + } + if (file != XBADFILE) { + XFCLOSE(file); + file = XBADFILE; + } - ExpectTrue((file = XFOPEN(fname, "rb")) != XBADFILE); - ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); - ExpectIntGT(sz = XFTELL(file), 0); - ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); - ExpectNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); - if (buf != NULL) { - ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); - } - if (file != XBADFILE) { - XFCLOSE(file); - file = XBADFILE; - } + ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + ExpectNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + buf = NULL; + BIO_free(bio); + bio = NULL; + ExpectNotNull(pkey3 = EVP_PKEY_new()); - /* Test using BIO new mem and loading PEM private key */ - ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); - ExpectNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); - XFREE(buf, NULL, DYNAMIC_TYPE_FILE); - buf = NULL; - BIO_free(bio); - bio = NULL; - ExpectNotNull(pkey2 = EVP_PKEY_new()); - if (pkey2 != NULL) { - pkey2->type = EVP_PKEY_RSA; - } - /* Test parameter copy */ - ExpectIntEQ(EVP_PKEY_copy_parameters(pkey2, pkey), 0); - EVP_PKEY_free(pkey2); - EVP_PKEY_free(pkey); - pkey = NULL; + ExpectNotNull(rsa_key = EVP_PKEY_get1_RSA(pkey)); + ExpectIntEQ(EVP_PKEY_set1_RSA(pkey3, rsa_key), WOLFSSL_SUCCESS); - /* Qt unit test case : rsa pkcs8 key */ - ExpectTrue((file = XFOPEN(fname_rsa_p8, "rb")) != XBADFILE); - ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); - ExpectIntGT(sz = XFTELL(file), 0); - ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); - ExpectNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); - if (buf) { - ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); - } - if (file != XBADFILE) { - XFCLOSE(file); - file = XBADFILE; - } +#ifdef WOLFSSL_ERROR_CODE_OPENSSL + ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 1/* match */); +#else + ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 0); +#endif - ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); - ExpectNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); - XFREE(buf, NULL, DYNAMIC_TYPE_FILE); - buf = NULL; - BIO_free(bio); - bio = NULL; - ExpectNotNull(pkey3 = EVP_PKEY_new()); + RSA_free(rsa_key); + EVP_PKEY_free(pkey3); + EVP_PKEY_free(pkey); + pkey = NULL; + pkey2 = NULL; - ExpectNotNull(rsa_key = EVP_PKEY_get1_RSA(pkey)); - ExpectIntEQ(EVP_PKEY_set1_RSA(pkey3, rsa_key), WOLFSSL_SUCCESS); +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) + #define BIO_PEM_TEST_CHAR 'a' + XMEMSET(extra, BIO_PEM_TEST_CHAR, sizeof(extra)); - #ifdef WOLFSSL_ERROR_CODE_OPENSSL - ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 1/* match */); - #else - ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 0); - #endif + ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + ExpectIntEQ(BIO_set_write_buf_size(bio, 4096), SSL_FAILURE); + ExpectNotNull(pub_bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + ExpectIntEQ(BIO_set_write_buf_size(pub_bio, 4096), SSL_FAILURE); - RSA_free(rsa_key); - EVP_PKEY_free(pkey3); - EVP_PKEY_free(pkey); - pkey = NULL; - } + ExpectNull(d2i_PrivateKey(EVP_PKEY_EC, &pkey, &server_key, + (long)sizeof_server_key_der_2048)); + ExpectNull(pkey); + + ExpectNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, + (long)sizeof_server_key_der_2048)); + ExpectIntEQ(PEM_write_bio_PrivateKey(NULL, pkey, NULL, NULL, 0, NULL, NULL), + WOLFSSL_FAILURE); + ExpectIntEQ(PEM_write_bio_PrivateKey(bio, NULL, NULL, NULL, 0, NULL, NULL), + WOLFSSL_FAILURE); + ExpectIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), + WOLFSSL_SUCCESS); + ExpectIntGT(BIO_pending(bio), 0); + ExpectIntEQ(BIO_pending(bio), 1679); + /* Check if the pubkey API writes only the public key */ +#ifdef WOLFSSL_KEY_GEN + ExpectIntEQ(PEM_write_bio_PUBKEY(NULL, pkey), WOLFSSL_FAILURE); + ExpectIntEQ(PEM_write_bio_PUBKEY(pub_bio, NULL), WOLFSSL_FAILURE); + ExpectIntEQ(PEM_write_bio_PUBKEY(pub_bio, pkey), WOLFSSL_SUCCESS); + ExpectIntGT(BIO_pending(pub_bio), 0); + /* Previously both the private key and the pubkey calls would write + * out the private key and the PEM header was the only difference. + * The public PEM should be significantly shorter than the + * private key versison. */ + ExpectIntEQ(BIO_pending(pub_bio), 451); +#else + /* Not supported. */ + ExpectIntEQ(PEM_write_bio_PUBKEY(pub_bio, pkey), 0); #endif - /* test loading ECC key using BIO */ -#if defined(HAVE_ECC) && !defined(NO_FILESYSTEM) - { - XFILE file = XBADFILE; - const char* fname = "./certs/ecc-key.pem"; - const char* fname_ecc_p8 = "./certs/ecc-keyPkcs8.pem"; + /* test creating new EVP_PKEY with good args */ + ExpectNotNull((pkey2 = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + if (pkey && pkey->pkey.ptr && pkey2 && pkey2->pkey.ptr) { + ExpectIntEQ((int)XMEMCMP(pkey->pkey.ptr, pkey2->pkey.ptr, + pkey->pkey_sz), 0); + } - size_t sz = 0; - byte* buf = NULL; - EVP_PKEY* pkey2 = NULL; - EVP_PKEY* pkey3 = NULL; - EC_KEY* ec_key = NULL; - int nid = 0; + /* test of reuse of EVP_PKEY */ + ExpectNull(PEM_read_bio_PrivateKey(bio, &pkey, NULL, NULL)); + ExpectIntEQ(BIO_pending(bio), 0); + ExpectIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), + SSL_SUCCESS); + /* add 10 extra bytes after PEM */ + ExpectIntEQ(BIO_write(bio, extra, 10), 10); + ExpectNotNull(PEM_read_bio_PrivateKey(bio, &pkey, NULL, NULL)); + ExpectNotNull(pkey); + if (pkey && pkey->pkey.ptr && pkey2 && pkey2->pkey.ptr) { + ExpectIntEQ((int)XMEMCMP(pkey->pkey.ptr, pkey2->pkey.ptr, + pkey->pkey_sz), 0); + } + /* check 10 extra bytes still there */ + ExpectIntEQ(BIO_pending(bio), 10); + ExpectIntEQ(BIO_read(bio, extra, 10), 10); + for (i = 0; i < 10; i++) { + ExpectIntEQ(extra[i], BIO_PEM_TEST_CHAR); + } - ExpectTrue((file = XFOPEN(fname, "rb")) != XBADFILE); - ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); - ExpectIntGT(sz = XFTELL(file), 0); - ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); - ExpectNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); - if (buf) { - ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); - } - if (file != XBADFILE) { - XFCLOSE(file); - file = XBADFILE; - } + BIO_free(pub_bio); + BIO_free(bio); + bio = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + EVP_PKEY_free(pkey2); +#endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN */ +#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_RSA && USE_CERT_BUFFERS_2048 && + * !NO_FILESYSTEM && !NO_BIO */ + return EXPECT_RESULT(); +} - /* Test using BIO new mem and loading PEM private key */ - ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); - ExpectNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); - XFREE(buf, NULL, DYNAMIC_TYPE_FILE); - buf = NULL; - BIO_free(bio); - bio = NULL; - ExpectNotNull(pkey2 = EVP_PKEY_new()); - ExpectNotNull(pkey3 = EVP_PKEY_new()); - if (pkey2 != NULL) { - pkey2->type = EVP_PKEY_EC; - } - /* Test parameter copy */ - ExpectIntEQ(EVP_PKEY_copy_parameters(pkey2, pkey), 1); - /* Qt unit test case 1*/ - ExpectNotNull(ec_key = EVP_PKEY_get1_EC_KEY(pkey)); - ExpectIntEQ(EVP_PKEY_set1_EC_KEY(pkey3, ec_key), WOLFSSL_SUCCESS); - #ifdef WOLFSSL_ERROR_CODE_OPENSSL - ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 1/* match */); - #else - ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 0); - #endif - /* Test default digest */ - ExpectIntEQ(EVP_PKEY_get_default_digest_nid(pkey, &nid), 1); - ExpectIntEQ(nid, NID_sha256); - EC_KEY_free(ec_key); - ec_key = NULL; - EVP_PKEY_free(pkey3); - pkey3 = NULL; - EVP_PKEY_free(pkey2); - pkey2 = NULL; - EVP_PKEY_free(pkey); - pkey = NULL; +/* test loading ECC key using BIO */ +static int test_wolfSSL_PEM_PrivateKey_ecc(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && defined(HAVE_ECC) && \ + !defined(NO_FILESYSTEM) && !defined(NO_BIO) + BIO* bio = NULL; + EVP_PKEY* pkey = NULL; + XFILE file = XBADFILE; + const char* fname = "./certs/ecc-key.pem"; + const char* fname_ecc_p8 = "./certs/ecc-keyPkcs8.pem"; + + size_t sz = 0; + byte* buf = NULL; + EVP_PKEY* pkey2 = NULL; + EVP_PKEY* pkey3 = NULL; + EC_KEY* ec_key = NULL; + int nid = 0; + BIO* pub_bio = NULL; - /* Qt unit test case ec pkcs8 key */ - ExpectTrue((file = XFOPEN(fname_ecc_p8, "rb")) != XBADFILE); - ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); - ExpectIntGT(sz = XFTELL(file), 0); - ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); - ExpectNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); - if (buf) { - ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); - } - if (file != XBADFILE) { - XFCLOSE(file); - file = XBADFILE; - } + ExpectTrue((file = XFOPEN(fname, "rb")) != XBADFILE); + ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); + ExpectIntGT(sz = XFTELL(file), 0); + ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); + ExpectNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + if (buf) { + ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); + } + if (file != XBADFILE) { + XFCLOSE(file); + file = XBADFILE; + } - ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); - ExpectNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); - XFREE(buf, NULL, DYNAMIC_TYPE_FILE); - buf = NULL; - BIO_free(bio); - bio = NULL; - ExpectNotNull(pkey3 = EVP_PKEY_new()); - /* Qt unit test case */ - ExpectNotNull(ec_key = EVP_PKEY_get1_EC_KEY(pkey)); - ExpectIntEQ(EVP_PKEY_set1_EC_KEY(pkey3, ec_key), WOLFSSL_SUCCESS); - #ifdef WOLFSSL_ERROR_CODE_OPENSSL - ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 1/* match */); - #else - ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 0); - #endif - EC_KEY_free(ec_key); - EVP_PKEY_free(pkey3); - EVP_PKEY_free(pkey); - pkey = NULL; + /* Test using BIO new mem and loading PEM private key */ + ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + ExpectNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + BIO_free(bio); + bio = NULL; + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + buf = NULL; + ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + ExpectNotNull(pub_bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + ExpectIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), + WOLFSSL_SUCCESS); + ExpectIntGT(BIO_pending(bio), 0); + /* No parmeters. */ + ExpectIntEQ(BIO_pending(bio), 227); + /* Check if the pubkey API writes only the public key */ +#ifdef WOLFSSL_KEY_GEN + ExpectIntEQ(PEM_write_bio_PUBKEY(pub_bio, pkey), WOLFSSL_SUCCESS); + ExpectIntGT(BIO_pending(pub_bio), 0); + /* Previously both the private key and the pubkey calls would write + * out the private key and the PEM header was the only difference. + * The public PEM should be significantly shorter than the + * private key versison. */ + ExpectIntEQ(BIO_pending(pub_bio), 178); +#endif + BIO_free(pub_bio); + BIO_free(bio); + bio = NULL; + ExpectNotNull(pkey2 = EVP_PKEY_new()); + ExpectNotNull(pkey3 = EVP_PKEY_new()); + if (pkey2 != NULL) { + pkey2->type = EVP_PKEY_EC; + } + /* Test parameter copy */ + ExpectIntEQ(EVP_PKEY_copy_parameters(pkey2, pkey), 1); + + + /* Qt unit test case 1*/ + ExpectNotNull(ec_key = EVP_PKEY_get1_EC_KEY(pkey)); + ExpectIntEQ(EVP_PKEY_set1_EC_KEY(pkey3, ec_key), WOLFSSL_SUCCESS); + #ifdef WOLFSSL_ERROR_CODE_OPENSSL + ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 1/* match */); + #else + ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 0); + #endif + /* Test default digest */ + ExpectIntEQ(EVP_PKEY_get_default_digest_nid(pkey, &nid), 1); + ExpectIntEQ(nid, NID_sha256); + EC_KEY_free(ec_key); + ec_key = NULL; + EVP_PKEY_free(pkey3); + pkey3 = NULL; + EVP_PKEY_free(pkey2); + pkey2 = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + + /* Qt unit test case ec pkcs8 key */ + ExpectTrue((file = XFOPEN(fname_ecc_p8, "rb")) != XBADFILE); + ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); + ExpectIntGT(sz = XFTELL(file), 0); + ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); + ExpectNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + if (buf) { + ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); + } + if (file != XBADFILE) { + XFCLOSE(file); + file = XBADFILE; } + + ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + ExpectNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + buf = NULL; + BIO_free(bio); + bio = NULL; + ExpectNotNull(pkey3 = EVP_PKEY_new()); + /* Qt unit test case */ + ExpectNotNull(ec_key = EVP_PKEY_get1_EC_KEY(pkey)); + ExpectIntEQ(EVP_PKEY_set1_EC_KEY(pkey3, ec_key), WOLFSSL_SUCCESS); +#ifdef WOLFSSL_ERROR_CODE_OPENSSL + ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 1/* match */); +#else + ExpectIntEQ(EVP_PKEY_cmp(pkey, pkey3), 0); #endif + EC_KEY_free(ec_key); + EVP_PKEY_free(pkey3); + EVP_PKEY_free(pkey); + pkey = NULL; +#endif + return EXPECT_RESULT(); +} -#if !defined(NO_BIO) && !defined(NO_RSA) && (defined(WOLFSSL_KEY_GEN) || \ - defined(WOLFSSL_CERT_GEN)) - { - #define BIO_PEM_TEST_CHAR 'a' - EVP_PKEY* pkey2 = NULL; - unsigned char extra[10]; - int i; - BIO* pub_bio = NULL; +/* test loading DSA key using BIO */ +static int test_wolfSSL_PEM_PrivateKey_dsa(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_DSA) && \ + !defined(NO_FILESYSTEM) && !defined(NO_BIO) +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + BIO* bio = NULL; + EVP_PKEY* pkey = NULL; - XMEMSET(extra, BIO_PEM_TEST_CHAR, sizeof(extra)); + ExpectNotNull(bio = BIO_new_file("./certs/dsa2048.pem", "rb")); + /* Private DSA EVP_PKEY */ + ExpectNotNull(pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, NULL, + NULL)); + BIO_free(bio); + bio = NULL; - ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); - ExpectIntEQ(BIO_set_write_buf_size(bio, 4096), SSL_FAILURE); - ExpectNotNull(pub_bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); - ExpectIntEQ(BIO_set_write_buf_size(pub_bio, 4096), SSL_FAILURE); + ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); +#if defined(OPENSSL_ALL) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) + ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, NULL, NULL, 0, NULL, + NULL), 0); +#endif - ExpectNull(d2i_PrivateKey(EVP_PKEY_EC, &pkey, - &server_key, (long)sizeof_server_key_der_2048)); - ExpectNull(pkey); +#ifdef WOLFSSL_KEY_GEN + ExpectIntEQ(PEM_write_bio_PUBKEY(bio, pkey), 1); + ExpectIntEQ(BIO_pending(bio), 1178); + BIO_reset(bio); +#endif - ExpectNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, - &server_key, (long)sizeof_server_key_der_2048)); - ExpectIntEQ(PEM_write_bio_PrivateKey(NULL, pkey, NULL, NULL, 0, NULL, - NULL), WOLFSSL_FAILURE); - ExpectIntEQ(PEM_write_bio_PrivateKey(bio, NULL, NULL, NULL, 0, NULL, - NULL), WOLFSSL_FAILURE); - ExpectIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, - NULL), WOLFSSL_SUCCESS); - ExpectIntGT(BIO_pending(bio), 0); - ExpectIntEQ(BIO_pending(bio), 1679); - /* Check if the pubkey API writes only the public key */ + ExpectIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), + 1); + ExpectIntEQ(BIO_pending(bio), 1196); + + BIO_free(bio); + bio = NULL; + + EVP_PKEY_free(pkey); + pkey = NULL; +#endif +#endif + return EXPECT_RESULT(); +} + +/* test loading DH key using BIO */ +static int test_wolfSSL_PEM_PrivateKey_dh(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_DH) && \ + !defined(NO_FILESYSTEM) && !defined(NO_BIO) +#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || \ + defined(WOLFSSL_OPENSSH)) && (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) + BIO* bio = NULL; + EVP_PKEY* pkey = NULL; + + ExpectNotNull(bio = BIO_new_file("./certs/dh-priv-2048.pem", "rb")); + /* Private DH EVP_PKEY */ + ExpectNotNull(pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, NULL, + NULL)); + BIO_free(bio); + bio = NULL; + + ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + +#if defined(OPENSSL_ALL) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) + ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, NULL, NULL, 0, NULL, + NULL), 0); +#endif #ifdef WOLFSSL_KEY_GEN - ExpectIntEQ(PEM_write_bio_PUBKEY(NULL, pkey), WOLFSSL_FAILURE); - ExpectIntEQ(PEM_write_bio_PUBKEY(pub_bio, NULL), WOLFSSL_FAILURE); - ExpectIntEQ(PEM_write_bio_PUBKEY(pub_bio, pkey), WOLFSSL_SUCCESS); - ExpectIntGT(BIO_pending(pub_bio), 0); - /* Previously both the private key and the pubkey calls would write - * out the private key and the PEM header was the only difference. - * The public PEM should be significantly shorter than the - * private key versison. */ - ExpectIntEQ(BIO_pending(pub_bio), 451); -#endif - - - /* test creating new EVP_PKEY with good args */ - ExpectNotNull((pkey2 = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); - if (pkey && pkey->pkey.ptr && pkey2 && pkey2->pkey.ptr) - ExpectIntEQ((int)XMEMCMP(pkey->pkey.ptr, pkey2->pkey.ptr, pkey->pkey_sz), 0); - - /* test of reuse of EVP_PKEY */ - ExpectNull(PEM_read_bio_PrivateKey(bio, &pkey, NULL, NULL)); - ExpectIntEQ(BIO_pending(bio), 0); - ExpectIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), - SSL_SUCCESS); - ExpectIntEQ(BIO_write(bio, extra, 10), 10); /* add 10 extra bytes after PEM */ - ExpectNotNull(PEM_read_bio_PrivateKey(bio, &pkey, NULL, NULL)); - ExpectNotNull(pkey); - if (pkey && pkey->pkey.ptr && pkey2 && pkey2->pkey.ptr) { - ExpectIntEQ((int)XMEMCMP(pkey->pkey.ptr, pkey2->pkey.ptr, pkey->pkey_sz),0); - } - ExpectIntEQ(BIO_pending(bio), 10); /* check 10 extra bytes still there */ - ExpectIntEQ(BIO_read(bio, extra, 10), 10); - for (i = 0; i < 10; i++) { - ExpectIntEQ(extra[i], BIO_PEM_TEST_CHAR); - } + ExpectIntEQ(PEM_write_bio_PUBKEY(bio, pkey), 0); +#endif - BIO_free(pub_bio); - BIO_free(bio); - bio = NULL; - EVP_PKEY_free(pkey); - pkey = NULL; - EVP_PKEY_free(pkey2); + ExpectIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), + 1); + ExpectIntEQ(BIO_pending(bio), 806); + + BIO_free(bio); + bio = NULL; + + EVP_PKEY_free(pkey); + pkey = NULL; +#endif +#endif + return EXPECT_RESULT(); +} + +static int test_wolfSSL_PEM_PrivateKey(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + (!defined(NO_RSA) || defined(HAVE_ECC)) && defined(USE_CERT_BUFFERS_2048) +#ifndef NO_BIO + BIO* bio = NULL; +#endif + EVP_PKEY* pkey = NULL; + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + +#ifndef NO_BIO + + /* test creating new EVP_PKEY with bad arg */ + ExpectNull((pkey = PEM_read_bio_PrivateKey(NULL, NULL, NULL, NULL))); + + /* Test bad EVP_PKEY type. */ + /* New HMAC EVP_PKEY */ + ExpectNotNull(bio = BIO_new_mem_buf("", 1)); + ExpectNotNull(pkey = EVP_PKEY_new()); + if (pkey != NULL) { + pkey->type = EVP_PKEY_HMAC; } - #endif + ExpectIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), + 0); +#if defined(OPENSSL_ALL) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) + ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, NULL, NULL, 0, NULL, + NULL), 0); +#endif +#ifdef WOLFSSL_KEY_GEN + ExpectIntEQ(PEM_write_bio_PUBKEY(bio, pkey), WOLFSSL_FAILURE); +#endif + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(bio); + bio = NULL; + /* key is DES encrypted */ #if !defined(NO_DES3) && defined(WOLFSSL_ENCRYPTED_KEYS) && \ @@ -35133,7 +35874,7 @@ static int test_wolfSSL_PEM_PUBKEY(void) { XFILE file = XBADFILE; const char* fname = "./certs/ecc-client-keyPub.pem"; - size_t sz; + size_t sz = 0; byte* buf = NULL; EVP_PKEY* pkey2 = NULL; @@ -35154,6 +35895,13 @@ static int test_wolfSSL_PEM_PUBKEY(void) /* Test using BIO new mem and loading PEM private key */ ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); ExpectNotNull((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))); + BIO_free(bio); + bio = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + ExpectNotNull(pkey = EVP_PKEY_new()); + ExpectPtrEq(PEM_read_bio_PUBKEY(bio, &pkey, NULL, NULL), pkey); XFREE(buf, NULL, DYNAMIC_TYPE_FILE); BIO_free(bio); bio = NULL; @@ -35171,7 +35919,7 @@ static int test_wolfSSL_PEM_PUBKEY(void) EC_KEY_free(ec_key); EVP_PKEY_free(pkey2); EVP_PKEY_free(pkey); - pkey = NULL; + pkey = NULL; } #endif @@ -41429,6 +42177,18 @@ static int test_wolfSSL_PKCS8_Compat(void) return EXPECT_RESULT(); } +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_BIO) +static int NoPasswordCallBack(char* passwd, int sz, int rw, void* userdata) +{ + (void)passwd; + (void)sz; + (void)rw; + (void)userdata; + + return -1; +} +#endif + static int test_wolfSSL_PKCS8_d2i(void) { EXPECT_DECLS; @@ -41511,6 +42271,13 @@ static int test_wolfSSL_PKCS8_d2i(void) #endif /* OPENSSL_ALL */ #ifndef NO_FILESYSTEM +#if defined(OPENSSL_ALL) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) + ExpectIntEQ(PEM_write_PKCS8PrivateKey(XBADFILE, pkey, NULL, NULL, 0, NULL, + NULL), 0); + ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, NULL, NULL, NULL, 0, NULL, + NULL), 0); +#endif + #ifndef NO_RSA /* Get DER encoded RSA PKCS#8 data. */ ExpectTrue((file = XFOPEN(rsaDerPkcs8File, "rb")) != XBADFILE); @@ -41541,20 +42308,33 @@ static int test_wolfSSL_PKCS8_d2i(void) #if defined(OPENSSL_ALL) && \ !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) ExpectNotNull(bio = BIO_new(BIO_s_mem())); + ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(NULL, pkey, NULL, NULL, 0, NULL, + NULL), 0); + ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, NULL, NULL, NULL, 0, NULL, + NULL), 0); /* Write PKCS#8 PEM to BIO. */ ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), bytes); + /* Write PKCS#8 PEM to stderr. */ + ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, NULL, NULL, 0, NULL, + NULL), bytes); /* Compare file and written data */ ExpectIntEQ(BIO_get_mem_data(bio, &p), bytes); ExpectIntEQ(XMEMCMP(p, pkcs8_buffer, bytes), 0); BIO_free(bio); bio = NULL; +#if !defined(NO_AES) && defined(HAVE_AESGCM) + ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_aes_128_gcm(), + NULL, 0, PasswordCallBack, (void*)"yassl123"), 0); +#endif #if !defined(NO_DES3) && !defined(NO_SHA) ExpectNotNull(bio = BIO_new(BIO_s_mem())); /* Write Encrypted PKCS#8 PEM to BIO. */ bytes = 1834; ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_des_ede3_cbc(), NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); + ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_des_ede3_cbc(), + NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); ExpectNotNull(evpPkey = PEM_read_bio_PrivateKey(bio, NULL, PasswordCallBack, (void*)"yassl123")); EVP_PKEY_free(evpPkey); @@ -41624,6 +42404,8 @@ static int test_wolfSSL_PKCS8_d2i(void) /* Write PKCS#8 PEM to BIO. */ ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), bytes); + ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, NULL, NULL, 0, NULL, + NULL), bytes); /* Compare file and written data */ ExpectIntEQ(BIO_get_mem_data(bio, &p), bytes); ExpectIntEQ(XMEMCMP(p, pkcs8_buffer, bytes), 0); @@ -41633,6 +42415,14 @@ static int test_wolfSSL_PKCS8_d2i(void) /* Write Encrypted PKCS#8 PEM to BIO. */ bytes = 379; ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_aes_256_cbc(), + NULL, 0, NoPasswordCallBack, (void*)"yassl123"), 0); + ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_aes_256_cbc(), + NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); + ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_aes_128_cbc(), + NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); + ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_aes_128_cbc(), + (char*)"yassl123", 8, PasswordCallBack, NULL), bytes); + ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_aes_256_cbc(), NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); ExpectNotNull(evpPkey = PEM_read_bio_PrivateKey(bio, NULL, PasswordCallBack, (void*)"yassl123")); @@ -51783,6 +52573,7 @@ static int test_wc_CreateEncryptedPKCS8Key(void) XMEMSET(&rng, 0, sizeof(WC_RNG)); ExpectIntEQ(wc_InitRng(&rng), 0); + PRIVATE_KEY_UNLOCK(); /* Call with NULL for out buffer to get necessary length. */ ExpectIntEQ(wc_CreateEncryptedPKCS8Key((byte*)server_key_der_2048, sizeof_server_key_der_2048, NULL, &encKeySz, password, passwordSz, @@ -51803,6 +52594,7 @@ static int test_wc_CreateEncryptedPKCS8Key(void) /* Check that the decrypted key matches the key prior to encryption. */ ExpectIntEQ(XMEMCMP(encKey + tradIdx, server_key_der_2048, sizeof_server_key_der_2048), 0); + PRIVATE_KEY_LOCK(); XFREE(encKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeRng(&rng); @@ -55885,6 +56677,25 @@ static int test_wolfSSL_PEM_read(void) size_t fileDataSz = 0; byte* out; + ExpectNotNull(bio = BIO_new_file(filename, "rb")); + ExpectIntEQ(PEM_read_bio(bio, NULL, &header, &data, &len), 0); + ExpectIntEQ(PEM_read_bio(bio, &name, NULL, &data, &len), 0); + ExpectIntEQ(PEM_read_bio(bio, &name, &header, NULL, &len), 0); + ExpectIntEQ(PEM_read_bio(bio, &name, &header, &data, NULL), 0); + + ExpectIntEQ(PEM_read_bio(bio, &name, &header, &data, &len), 1); + ExpectIntEQ(XSTRNCMP(name, "RSA PRIVATE KEY", 15), 0); + ExpectIntGT(XSTRLEN(header), 0); + ExpectIntGT(len, 0); + XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + name = NULL; + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + header = NULL; + XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + data = NULL; + BIO_free(bio); + bio = NULL; + ExpectTrue((fp = XFOPEN(filename, "rb")) != XBADFILE); /* Fail cases. */ @@ -55922,6 +56733,26 @@ static int test_wolfSSL_PEM_read(void) ExpectIntEQ(wolfSSL_BIO_get_mem_data(bio, &out), fileDataSz); ExpectIntEQ(XMEMCMP(out, fileData, fileDataSz), 0); + /* Fail cases. */ + ExpectIntEQ(PEM_write(XBADFILE, name, header, data, len), 0); + ExpectIntEQ(PEM_write(stderr, NULL, header, data, len), 0); + ExpectIntEQ(PEM_write(stderr, name, NULL, data, len), 0); + ExpectIntEQ(PEM_write(stderr, name, header, NULL, len), 0); + /* Pass case */ + ExpectIntEQ(PEM_write(stderr, name, header, data, len), fileDataSz); + + XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + name = NULL; + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + header = NULL; + XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + data = NULL; + /* Read out of a fixed buffer BIO - forces malloc in PEM_read_bio. */ + ExpectIntEQ(PEM_read_bio(bio, &name, &header, &data, &len), 1); + ExpectIntEQ(XSTRNCMP(name, "RSA PRIVATE KEY", 15), 0); + ExpectIntGT(XSTRLEN(header), 0); + ExpectIntGT(len, 0); + /* Fail cases. */ ExpectIntEQ(PEM_get_EVP_CIPHER_INFO(NULL, &cipher), WOLFSSL_FAILURE); ExpectIntEQ(PEM_get_EVP_CIPHER_INFO(header, NULL), WOLFSSL_FAILURE); @@ -55932,6 +56763,8 @@ static int test_wolfSSL_PEM_read(void) #endif /* Fail cases. */ + ExpectIntEQ(PEM_do_header(NULL, data, &len, PasswordCallBack, + (void*)"yassl123"), WOLFSSL_FAILURE); ExpectIntEQ(PEM_do_header(&cipher, NULL, &len, PasswordCallBack, (void*)"yassl123"), WOLFSSL_FAILURE); ExpectIntEQ(PEM_do_header(&cipher, data, NULL, PasswordCallBack, @@ -55939,9 +56772,14 @@ static int test_wolfSSL_PEM_read(void) ExpectIntEQ(PEM_do_header(&cipher, data, &len, NULL, (void*)"yassl123"), WOLFSSL_FAILURE); + ExpectIntEQ(PEM_do_header(&cipher, data, &len, NoPasswordCallBack, + (void*)"yassl123"), WOLFSSL_FAILURE); #if !defined(NO_DES3) && !defined(NO_MD5) ExpectIntEQ(PEM_do_header(&cipher, data, &len, PasswordCallBack, (void*)"yassl123"), WOLFSSL_SUCCESS); +#else + ExpectIntEQ(PEM_do_header(&cipher, data, &len, PasswordCallBack, + (void*)"yassl123"), WOLFSSL_FAILURE); #endif BIO_free(bio); @@ -62799,7 +63637,8 @@ static int test_wolfSSL_dtls_AEAD_limit(void) #endif #if defined(WOLFSSL_DTLS) && \ - defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(SINGLE_THREADED) + defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(SINGLE_THREADED) && \ + !defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) static void test_wolfSSL_dtls_send_ch(WOLFSSL* ssl) { int fd, ret; @@ -63330,10 +64169,12 @@ static int test_various_pathlen_chains(void) #endif /* NO_WOLFSSL_CLIENT && NO_WOLFSSL_SERVER */ ExpectIntEQ(wolfSSL_CertManagerUnloadCAs(cm), WOLFSSL_SUCCESS); wolfSSL_CertManagerFree(cm); + cm = NULL; ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerUnloadCAs(cm), WOLFSSL_SUCCESS); wolfSSL_CertManagerFree(cm); + cm = NULL; /* Test chain J (Again only first ICA has pathLen set and it's set to 2, * this time followed by 3 ICA's, should fail */ @@ -63341,6 +64182,7 @@ static int test_various_pathlen_chains(void) ExpectIntLT(test_chainJ(cm), 0); ExpectIntEQ(wolfSSL_CertManagerUnloadCAs(cm), WOLFSSL_SUCCESS); wolfSSL_CertManagerFree(cm); + cm = NULL; ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerUnloadCAs(cm), WOLFSSL_SUCCESS); @@ -63722,6 +64564,7 @@ static int test_wolfSSL_CTX_get_min_proto_version(void) wolfSSL_CTX_free(ctx); ctx = NULL; + #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_TLSV10 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_method())); #else @@ -63736,6 +64579,7 @@ static int test_wolfSSL_CTX_get_min_proto_version(void) #endif wolfSSL_CTX_free(ctx); ctx = NULL; + #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION), @@ -66579,7 +67423,7 @@ static int test_extra_alerts_wrong_cs(void) ExpectIntNE(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS); - ExpectIntEQ(h.last_tx.code, illegal_parameter); + ExpectIntEQ(h.last_tx.code, handshake_failure); ExpectIntEQ(h.last_tx.level, alert_fatal); wolfSSL_free(ssl_c); @@ -66795,7 +67639,7 @@ static int test_extra_alerts_bad_psk(void) WOLFSSL_ERROR_WANT_READ); ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS); - ExpectIntEQ( wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR), + ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR), WOLFSSL_ERROR_WANT_READ); ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); @@ -67434,6 +68278,9 @@ static int test_tls13_rpk_handshake(void) int typeCnt_c; int typeCnt_s; int tp; +#if defined(WOLFSSL_ALWAYS_VERIFY_CB) + int isServer; +#endif (void)err; (void)typeCnt_c; @@ -67467,7 +68314,7 @@ static int test_tls13_rpk_handshake(void) certType_s[1] = WOLFSSL_CERT_TYPE_X509; typeCnt_s = 2; - /* both clien and server do not call client/server_cert_type APIs, + /* both client and server do not call client/server_cert_type APIs, * expecting default settings works and no negotiation performed. */ @@ -67489,6 +68336,9 @@ static int test_tls13_rpk_handshake(void) WOLFSSL_SUCCESS); ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN); + (void)typeCnt_c; + (void)typeCnt_s; + wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_s); @@ -67520,7 +68370,7 @@ static int test_tls13_rpk_handshake(void) certType_s[1] = WOLFSSL_CERT_TYPE_X509; typeCnt_s = 2; - /* both clien and server do not call client/server_cert_type APIs, + /* both client and server do not call client/server_cert_type APIs, * expecting default settings works and no negotiation performed. */ @@ -67544,6 +68394,9 @@ static int test_tls13_rpk_handshake(void) WOLFSSL_SUCCESS); ExpectIntEQ(tp, WOLFSSL_CERT_TYPE_UNKNOWN); + (void)typeCnt_c; + (void)typeCnt_s; + wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_s); @@ -67702,12 +68555,9 @@ static int test_tls13_rpk_handshake(void) svrKeyFile, WOLFSSL_FILETYPE_PEM ) , 0); - /* set client certificate type in client end */ - certType_c[0] = WOLFSSL_CERT_TYPE_RPK; - certType_c[1] = WOLFSSL_CERT_TYPE_X509; - typeCnt_c = 2; - - /* client indicates both RPK and x509 certs are available but loaded RPK + /* set client certificate type in client end + * + * client indicates both RPK and x509 certs are available but loaded RPK * cert only. It does not have client add client-cert-type extension in CH. */ certType_c[0] = WOLFSSL_CERT_TYPE_RPK; @@ -68050,7 +68900,7 @@ static int test_tls13_rpk_handshake(void) WOLFSSL_SUCCESS); /* set certificate verify callback to both client and server */ - int isServer = 0; + isServer = 0; wolfSSL_SetCertCbCtx(ssl_c, &isServer); wolfSSL_set_verify(ssl_c, SSL_VERIFY_PEER, MyRpkVerifyCb); @@ -70810,6 +71660,8 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfCrypt_Init), + TEST_DECL(test_wc_LoadStaticMemory_ex), + /* Locking with Compat Mutex */ TEST_DECL(test_wc_SetMutexCb), TEST_DECL(test_wc_LockMutex_ex), @@ -71256,9 +72108,14 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_certs), TEST_DECL(test_wolfSSL_private_keys), + TEST_DECL(test_wolfSSL_PEM_def_callback), TEST_DECL(test_wolfSSL_PEM_read_PrivateKey), TEST_DECL(test_wolfSSL_PEM_read_RSA_PUBKEY), TEST_DECL(test_wolfSSL_PEM_read_PUBKEY), + TEST_DECL(test_wolfSSL_PEM_PrivateKey_rsa), + TEST_DECL(test_wolfSSL_PEM_PrivateKey_ecc), + TEST_DECL(test_wolfSSL_PEM_PrivateKey_dsa), + TEST_DECL(test_wolfSSL_PEM_PrivateKey_dh), TEST_DECL(test_wolfSSL_PEM_PrivateKey), TEST_DECL(test_wolfSSL_PEM_file_RSAKey), TEST_DECL(test_wolfSSL_PEM_file_RSAPrivateKey), @@ -71754,7 +72611,9 @@ TEST_CASE testCases[] = { #endif #ifdef OPENSSL_EXTRA + TEST_DECL(test_EC25519), TEST_DECL(test_ED25519), + TEST_DECL(test_EC448), TEST_DECL(test_ED448), #endif diff --git a/tests/test-dtls13-downgrade.conf b/tests/test-dtls13-downgrade.conf index bda26666cd..931cc6b8c5 100644 --- a/tests/test-dtls13-downgrade.conf +++ b/tests/test-dtls13-downgrade.conf @@ -41,3 +41,16 @@ -7 2 -u -l TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + +# server DTLSv1.2 - PSK +-v 3 +-u +-s +-l ECDHE-PSK-AES128-GCM-SHA256 + +# client DTLS PSK multiversion, allow downgrade +-vd +-7 2 +-u +-s +-l ECDHE-PSK-AES128-GCM-SHA256 diff --git a/tests/test-tls13-down.conf b/tests/test-tls13-down.conf index 02512f4d6d..90f0c4bb43 100644 --- a/tests/test-tls13-down.conf +++ b/tests/test-tls13-down.conf @@ -108,3 +108,14 @@ # client TLSv 1.2 -v 3 -H exitWithRet + +# server TLSv1.2 - PSK +-v 3 +-s +-l ECDHE-PSK-AES128-GCM-SHA256 + +# client TLS PSK multiversion, allow downgrade +-v d +-7 3 +-s +-l ECDHE-PSK-AES128-GCM-SHA256 diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 2f51aeffc4..1b4d12c45a 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -926,7 +926,9 @@ static const bench_alg bench_asym_opt[] = { { "-rsa-kg", BENCH_RSA_KEYGEN }, #endif { "-rsa", BENCH_RSA }, + #ifdef WOLFSSL_KEY_GEN { "-rsa-sz", BENCH_RSA_SZ }, + #endif #endif #ifndef NO_DH { "-dh", BENCH_DH }, @@ -1378,9 +1380,9 @@ static const char* bench_result_words3[][5] = { /* unsigned int max = 4,294,967,295 */ uint64_t thisVal = 0; /* CPU counter, "this current value" as read. */ uint64_t thisIncrement = 0; /* The adjusted increment amount. */ - uint64_t expected_diff = 0; /* FreeRTOS esimated expected CPU diff. */ + uint64_t expected_diff = 0; /* FreeRTOS estimated expected CPU diff.*/ #ifdef DEBUG_WOLFSSL_BENCHMARK_TIMING - uint32_t tickCount = 0; /* Currrent rtos tick counter. */ + uint32_t tickCount = 0; /* Current rtos tick counter. */ uint32_t tickDiff = 0; /* Tick difference from last check. */ uint32_t tickBeginDiff = 0; /* Tick difference from beginning. */ #endif @@ -1459,7 +1461,7 @@ static const char* bench_result_words3[][5] = { if (expected_diff > UINT_MAX) { /* The number of cycles expected from FreeRTOS ticks is * greater than the maximum size of an unsigned 32-bit - * integer, meaning multiple overflows occured. */ + * integer, meaning multiple overflows occurred. */ #ifdef DEBUG_WOLFSSL_BENCHMARK_TIMING ESP_LOGW(TAG, "expected_diff > UINT_MAX (%u)", UINT_MAX); #endif @@ -1538,7 +1540,7 @@ static const char* bench_result_words3[][5] = { _esp_cpu_count_last = esp_cpu_get_cycle_count(); #else /* TODO: Why doesn't esp_cpu_get_cycle_count work for Xtensa - * when resetting CPU cycle counter? FreeRTOS tick collison? + * when resetting CPU cycle counter? FreeRTOS tick collision? * thisVal = esp_cpu_get_cycle_count(); See also, above * or thisVal = xthal_get_ccount(); */ #if ESP_IDF_VERSION_MAJOR < 5 @@ -9860,8 +9862,8 @@ void bench_lms(void) #endif #if defined(WOLFSSL_WC_LMS) && !defined(LMS_PARAMS_BENCHED) - bench_lms_keygen(0x100, pub); - bench_lms_sign_verify(0x100, pub); + bench_lms_keygen(WC_LMS_PARM_L1_H5_W1, pub); + bench_lms_sign_verify(WC_LMS_PARM_L1_H5_W1, pub); #endif return; @@ -10069,12 +10071,10 @@ static void bench_xmss_sign_verify(const char * params) if (freeRng) { wc_FreeRng(&rng); - freeRng = 0; } if (freeKey) { wc_XmssKey_Free(&key); - freeKey = 0; } return; @@ -12801,7 +12801,13 @@ void bench_sphincsKeySign(byte level, byte optim) #elif defined(FREERTOS) - #include "task.h" + #ifdef PLATFORMIO + #include + #include + #else + #include "task.h" + #endif + #if defined(WOLFSSL_ESPIDF) /* prototype definition */ int construct_argv(); @@ -12998,13 +13004,13 @@ void bench_sphincsKeySign(byte level, byte optim) double current_time(int reset) { + int64_t t; (void)reset; - #if defined(CONFIG_ARCH_POSIX) k_cpu_idle(); #endif - - return (double)k_uptime_get() / 1000; + t = k_uptime_get(); /* returns current uptime in milliseconds */ + return (double)(t / 1000); } #elif defined(WOLFSSL_NETBURNER) diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index e9716bcd8b..c4210398e1 100644 --- a/wolfcrypt/src/aes.c +++ b/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 @@ -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 */ @@ -1908,6 +1915,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 +1930,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 +2216,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 +2716,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 +2768,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 +2945,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 +4085,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 +4246,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; @@ -4436,11 +4455,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 +4488,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; @@ -4661,7 +4680,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; \ @@ -6144,7 +6163,7 @@ 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 */ @@ -6381,7 +6400,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 @@ -11863,7 +11882,7 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB1( } if (ret == 0) { - if (bit > 0 && bit < 7) { + if (bit >= 0 && bit < 7) { out[0] = cur; } } @@ -12350,7 +12369,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 +12382,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 +12392,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 @@ -12695,6 +12714,14 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, aes = &xaes->aes; +/* 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_AesXtsEncrypt called with unset encryption key."); return BAD_FUNC_ARG; @@ -12711,19 +12738,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,23 +12757,13 @@ 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); } - -#ifdef WOLFSSL_AESNI - if (aes->use_aesni) - 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; - } -#endif -#endif } return ret; @@ -12923,6 +12929,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 +12953,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 +12972,7 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, (int)aes->rounds); ret = 0; } + RESTORE_VECTOR_REGISTERS(); } else #endif @@ -12976,17 +12980,6 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, ret = AesXtsDecrypt_sw(xaes, out, in, sz, i); } -#ifdef WOLFSSL_AESNI - if (aes->use_aesni) - 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; - } -#endif -#endif - return ret; } } diff --git a/wolfcrypt/src/aes_asm.asm b/wolfcrypt/src/aes_asm.asm index 39d5fdc9bf..ef4e4b9cf2 100644 --- a/wolfcrypt/src/aes_asm.asm +++ b/wolfcrypt/src/aes_asm.asm @@ -40,7 +40,7 @@ IFDEF HAVE_FIPS ENDIF IF fips_version GE 2 - fipsAh SEGMENT ALIAS(".fipsA$h") 'CODE' + fipsAb SEGMENT ALIAS(".fipsA$b") 'CODE' ELSE _text SEGMENT ENDIF @@ -1523,7 +1523,7 @@ MAKE_RK256_b: IF fips_version GE 2 - fipsAh ENDS + fipsAb ENDS ELSE _text ENDS ENDIF diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index ac50995875..6bb8edc127 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1209,8 +1209,8 @@ static int GetASN_ObjectId(const byte* input, word32 idx, int length) #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"); @@ -7770,17 +7770,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 */ @@ -15585,8 +15627,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; @@ -18202,6 +18251,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 +18260,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 */ @@ -21072,7 +21123,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; @@ -23753,6 +23810,45 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) 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, ssl->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, ssl->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 || @@ -23852,6 +23948,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); @@ -24115,14 +24214,25 @@ int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) 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; @@ -25937,11 +26047,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 +26064,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 +26086,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 +26122,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; @@ -27565,6 +27701,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 +28311,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 +28322,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 +28360,41 @@ static int EncodePublicKey(int keyType, byte* output, int outLen, } break; #endif + #if defined(HAVE_PQC) && 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_PQC && HAVE_FALCON */ + #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + 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_PQC && HAVE_DILITHIUM */ + #if defined(HAVE_PQC) && 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_PQC && HAVE_SPHINCS */ default: ret = PUBLIC_KEY_E; break; @@ -29975,7 +30161,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 +30342,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 +30424,7 @@ int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, NULL, NULL, NULL, NULL); } + #ifdef WOLFSSL_CERT_REQ #ifndef WOLFSSL_ASN_TEMPLATE @@ -31022,7 +31211,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 +31326,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)) { @@ -31460,6 +31651,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) diff --git a/wolfcrypt/src/chacha_asm.S b/wolfcrypt/src/chacha_asm.S index 9ca854cb4e..93b3a3fef7 100644 --- a/wolfcrypt/src/chacha_asm.S +++ b/wolfcrypt/src/chacha_asm.S @@ -1,6 +1,6 @@ /* chacha_asm.S */ /* - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -536,9 +536,19 @@ chacha_encrypt_avx1: .p2align 4 _chacha_encrypt_avx1: #endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 subq $0x190, %rsp movq %rsp, %r9 leaq 256(%rsp), %r10 + leaq L_chacha20_avx1_rotl8(%rip), %r12 + leaq L_chacha20_avx1_rotl16(%rip), %r13 + leaq L_chacha20_avx1_add(%rip), %r14 + leaq L_chacha20_avx1_four(%rip), %r15 + addq $15, %r9 + addq $15, %r10 andq $-16, %r9 andq $-16, %r10 movl %ecx, %eax @@ -560,7 +570,7 @@ _chacha_encrypt_avx1: vpshufd $0x00, 52(%rdi), %xmm13 vpshufd $0x00, 56(%rdi), %xmm14 vpshufd $0x00, 60(%rdi), %xmm15 - vpaddd L_chacha20_avx1_add(%rip), %xmm12, %xmm12 + vpaddd (%r14), %xmm12, %xmm12 vmovdqa %xmm0, (%r9) vmovdqa %xmm1, 16(%r9) vmovdqa %xmm2, 32(%r9) @@ -584,22 +594,22 @@ L_chacha20_avx1_loop128: vpaddd %xmm4, %xmm0, %xmm0 vpxor %xmm0, %xmm12, %xmm12 vmovdqa 48(%r10), %xmm11 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm12, %xmm12 + vpshufb (%r13), %xmm12, %xmm12 vpaddd %xmm12, %xmm8, %xmm8 vpxor %xmm8, %xmm4, %xmm4 vpaddd %xmm5, %xmm1, %xmm1 vpxor %xmm1, %xmm13, %xmm13 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm13, %xmm13 + vpshufb (%r13), %xmm13, %xmm13 vpaddd %xmm13, %xmm9, %xmm9 vpxor %xmm9, %xmm5, %xmm5 vpaddd %xmm6, %xmm2, %xmm2 vpxor %xmm2, %xmm14, %xmm14 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm14, %xmm14 + vpshufb (%r13), %xmm14, %xmm14 vpaddd %xmm14, %xmm10, %xmm10 vpxor %xmm10, %xmm6, %xmm6 vpaddd %xmm7, %xmm3, %xmm3 vpxor %xmm3, %xmm15, %xmm15 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm15, %xmm15 + vpshufb (%r13), %xmm15, %xmm15 vpaddd %xmm15, %xmm11, %xmm11 vpxor %xmm11, %xmm7, %xmm7 vmovdqa %xmm11, 48(%r10) @@ -618,22 +628,22 @@ L_chacha20_avx1_loop128: vpaddd %xmm4, %xmm0, %xmm0 vpxor %xmm0, %xmm12, %xmm12 vmovdqa 48(%r10), %xmm11 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm12, %xmm12 + vpshufb (%r12), %xmm12, %xmm12 vpaddd %xmm12, %xmm8, %xmm8 vpxor %xmm8, %xmm4, %xmm4 vpaddd %xmm5, %xmm1, %xmm1 vpxor %xmm1, %xmm13, %xmm13 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm13, %xmm13 + vpshufb (%r12), %xmm13, %xmm13 vpaddd %xmm13, %xmm9, %xmm9 vpxor %xmm9, %xmm5, %xmm5 vpaddd %xmm6, %xmm2, %xmm2 vpxor %xmm2, %xmm14, %xmm14 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm14, %xmm14 + vpshufb (%r12), %xmm14, %xmm14 vpaddd %xmm14, %xmm10, %xmm10 vpxor %xmm10, %xmm6, %xmm6 vpaddd %xmm7, %xmm3, %xmm3 vpxor %xmm3, %xmm15, %xmm15 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm15, %xmm15 + vpshufb (%r12), %xmm15, %xmm15 vpaddd %xmm15, %xmm11, %xmm11 vpxor %xmm11, %xmm7, %xmm7 vmovdqa %xmm11, 48(%r10) @@ -652,22 +662,22 @@ L_chacha20_avx1_loop128: vpaddd %xmm5, %xmm0, %xmm0 vpxor %xmm0, %xmm15, %xmm15 vmovdqa 48(%r10), %xmm11 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm15, %xmm15 + vpshufb (%r13), %xmm15, %xmm15 vpaddd %xmm15, %xmm10, %xmm10 vpxor %xmm10, %xmm5, %xmm5 vpaddd %xmm6, %xmm1, %xmm1 vpxor %xmm1, %xmm12, %xmm12 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm12, %xmm12 + vpshufb (%r13), %xmm12, %xmm12 vpaddd %xmm12, %xmm11, %xmm11 vpxor %xmm11, %xmm6, %xmm6 vpaddd %xmm7, %xmm2, %xmm2 vpxor %xmm2, %xmm13, %xmm13 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm13, %xmm13 + vpshufb (%r13), %xmm13, %xmm13 vpaddd %xmm13, %xmm8, %xmm8 vpxor %xmm8, %xmm7, %xmm7 vpaddd %xmm4, %xmm3, %xmm3 vpxor %xmm3, %xmm14, %xmm14 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm14, %xmm14 + vpshufb (%r13), %xmm14, %xmm14 vpaddd %xmm14, %xmm9, %xmm9 vpxor %xmm9, %xmm4, %xmm4 vmovdqa %xmm11, 48(%r10) @@ -686,22 +696,22 @@ L_chacha20_avx1_loop128: vpaddd %xmm5, %xmm0, %xmm0 vpxor %xmm0, %xmm15, %xmm15 vmovdqa 48(%r10), %xmm11 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm15, %xmm15 + vpshufb (%r12), %xmm15, %xmm15 vpaddd %xmm15, %xmm10, %xmm10 vpxor %xmm10, %xmm5, %xmm5 vpaddd %xmm6, %xmm1, %xmm1 vpxor %xmm1, %xmm12, %xmm12 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm12, %xmm12 + vpshufb (%r12), %xmm12, %xmm12 vpaddd %xmm12, %xmm11, %xmm11 vpxor %xmm11, %xmm6, %xmm6 vpaddd %xmm7, %xmm2, %xmm2 vpxor %xmm2, %xmm13, %xmm13 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm13, %xmm13 + vpshufb (%r12), %xmm13, %xmm13 vpaddd %xmm13, %xmm8, %xmm8 vpxor %xmm8, %xmm7, %xmm7 vpaddd %xmm4, %xmm3, %xmm3 vpxor %xmm3, %xmm14, %xmm14 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm14, %xmm14 + vpshufb (%r12), %xmm14, %xmm14 vpaddd %xmm14, %xmm9, %xmm9 vpxor %xmm9, %xmm4, %xmm4 vmovdqa %xmm11, 48(%r10) @@ -835,7 +845,7 @@ L_chacha20_avx1_loop128: vmovdqa 192(%r9), %xmm12 addq $0x100, %rsi addq $0x100, %rdx - vpaddd L_chacha20_avx1_four(%rip), %xmm12, %xmm12 + vpaddd (%r15), %xmm12, %xmm12 subl $0x100, %ecx vmovdqa %xmm12, 192(%r9) cmpl $0x100, %ecx @@ -876,7 +886,7 @@ L_chacha20_avx1_block_start: L_chacha20_avx1_block_crypt_start: vpaddd %xmm1, %xmm0, %xmm0 vpxor %xmm0, %xmm3, %xmm3 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpshufb (%r13), %xmm3, %xmm3 vpaddd %xmm3, %xmm2, %xmm2 vpxor %xmm2, %xmm1, %xmm1 vpsrld $20, %xmm1, %xmm4 @@ -884,7 +894,7 @@ L_chacha20_avx1_block_crypt_start: vpxor %xmm4, %xmm1, %xmm1 vpaddd %xmm1, %xmm0, %xmm0 vpxor %xmm0, %xmm3, %xmm3 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpshufb (%r12), %xmm3, %xmm3 vpaddd %xmm3, %xmm2, %xmm2 vpxor %xmm2, %xmm1, %xmm1 vpsrld $25, %xmm1, %xmm4 @@ -895,7 +905,7 @@ L_chacha20_avx1_block_crypt_start: vpshufd $0x93, %xmm3, %xmm3 vpaddd %xmm1, %xmm0, %xmm0 vpxor %xmm0, %xmm3, %xmm3 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpshufb (%r13), %xmm3, %xmm3 vpaddd %xmm3, %xmm2, %xmm2 vpxor %xmm2, %xmm1, %xmm1 vpsrld $20, %xmm1, %xmm4 @@ -903,7 +913,7 @@ L_chacha20_avx1_block_crypt_start: vpxor %xmm4, %xmm1, %xmm1 vpaddd %xmm1, %xmm0, %xmm0 vpxor %xmm0, %xmm3, %xmm3 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpshufb (%r12), %xmm3, %xmm3 vpaddd %xmm3, %xmm2, %xmm2 vpxor %xmm2, %xmm1, %xmm1 vpsrld $25, %xmm1, %xmm4 @@ -952,7 +962,7 @@ L_chacha20_avx1_block_done: L_chacha20_avx1_partial_crypt_start: vpaddd %xmm1, %xmm0, %xmm0 vpxor %xmm0, %xmm3, %xmm3 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpshufb (%r13), %xmm3, %xmm3 vpaddd %xmm3, %xmm2, %xmm2 vpxor %xmm2, %xmm1, %xmm1 vpsrld $20, %xmm1, %xmm4 @@ -960,7 +970,7 @@ L_chacha20_avx1_partial_crypt_start: vpxor %xmm4, %xmm1, %xmm1 vpaddd %xmm1, %xmm0, %xmm0 vpxor %xmm0, %xmm3, %xmm3 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpshufb (%r12), %xmm3, %xmm3 vpaddd %xmm3, %xmm2, %xmm2 vpxor %xmm2, %xmm1, %xmm1 vpsrld $25, %xmm1, %xmm4 @@ -971,7 +981,7 @@ L_chacha20_avx1_partial_crypt_start: vpshufd $0x93, %xmm3, %xmm3 vpaddd %xmm1, %xmm0, %xmm0 vpxor %xmm0, %xmm3, %xmm3 - vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpshufb (%r13), %xmm3, %xmm3 vpaddd %xmm3, %xmm2, %xmm2 vpxor %xmm2, %xmm1, %xmm1 vpsrld $20, %xmm1, %xmm4 @@ -979,7 +989,7 @@ L_chacha20_avx1_partial_crypt_start: vpxor %xmm4, %xmm1, %xmm1 vpaddd %xmm1, %xmm0, %xmm0 vpxor %xmm0, %xmm3, %xmm3 - vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpshufb (%r12), %xmm3, %xmm3 vpaddd %xmm3, %xmm2, %xmm2 vpxor %xmm2, %xmm1, %xmm1 vpsrld $25, %xmm1, %xmm4 @@ -1023,7 +1033,12 @@ L_chacha20_avx1_partial_end64: subl %r11d, %r8d movl %r8d, 76(%rdi) L_chacha20_avx1_partial_done: + vzeroupper addq $0x190, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 repz retq #ifndef __APPLE__ .size chacha_encrypt_avx1,.-chacha_encrypt_avx1 @@ -1094,9 +1109,18 @@ chacha_encrypt_avx2: .p2align 4 _chacha_encrypt_avx2: #endif /* __APPLE__ */ - subq $0x310, %rsp + pushq %r12 + pushq %r13 + pushq %r14 + subq $0x320, %rsp movq %rsp, %r9 + leaq L_chacha20_avx2_rotl8(%rip), %r11 + leaq L_chacha20_avx2_rotl16(%rip), %r12 + leaq L_chacha20_avx2_add(%rip), %r13 + leaq L_chacha20_avx2_eight(%rip), %r14 leaq 512(%rsp), %r10 + addq $31, %r9 + addq $31, %r10 andq $-32, %r9 andq $-32, %r10 movl %ecx, %eax @@ -1118,7 +1142,7 @@ _chacha_encrypt_avx2: vpbroadcastd 52(%rdi), %ymm13 vpbroadcastd 56(%rdi), %ymm14 vpbroadcastd 60(%rdi), %ymm15 - vpaddd L_chacha20_avx2_add(%rip), %ymm12, %ymm12 + vpaddd (%r13), %ymm12, %ymm12 vmovdqa %ymm0, (%r9) vmovdqa %ymm1, 32(%r9) vmovdqa %ymm2, 64(%r9) @@ -1142,22 +1166,22 @@ L_chacha20_avx2_loop256: vpaddd %ymm4, %ymm0, %ymm0 vpxor %ymm0, %ymm12, %ymm12 vmovdqa 96(%r10), %ymm11 - vpshufb L_chacha20_avx2_rotl16(%rip), %ymm12, %ymm12 + vpshufb (%r12), %ymm12, %ymm12 vpaddd %ymm12, %ymm8, %ymm8 vpxor %ymm8, %ymm4, %ymm4 vpaddd %ymm5, %ymm1, %ymm1 vpxor %ymm1, %ymm13, %ymm13 - vpshufb L_chacha20_avx2_rotl16(%rip), %ymm13, %ymm13 + vpshufb (%r12), %ymm13, %ymm13 vpaddd %ymm13, %ymm9, %ymm9 vpxor %ymm9, %ymm5, %ymm5 vpaddd %ymm6, %ymm2, %ymm2 vpxor %ymm2, %ymm14, %ymm14 - vpshufb L_chacha20_avx2_rotl16(%rip), %ymm14, %ymm14 + vpshufb (%r12), %ymm14, %ymm14 vpaddd %ymm14, %ymm10, %ymm10 vpxor %ymm10, %ymm6, %ymm6 vpaddd %ymm7, %ymm3, %ymm3 vpxor %ymm3, %ymm15, %ymm15 - vpshufb L_chacha20_avx2_rotl16(%rip), %ymm15, %ymm15 + vpshufb (%r12), %ymm15, %ymm15 vpaddd %ymm15, %ymm11, %ymm11 vpxor %ymm11, %ymm7, %ymm7 vmovdqa %ymm11, 96(%r10) @@ -1176,22 +1200,22 @@ L_chacha20_avx2_loop256: vpaddd %ymm4, %ymm0, %ymm0 vpxor %ymm0, %ymm12, %ymm12 vmovdqa 96(%r10), %ymm11 - vpshufb L_chacha20_avx2_rotl8(%rip), %ymm12, %ymm12 + vpshufb (%r11), %ymm12, %ymm12 vpaddd %ymm12, %ymm8, %ymm8 vpxor %ymm8, %ymm4, %ymm4 vpaddd %ymm5, %ymm1, %ymm1 vpxor %ymm1, %ymm13, %ymm13 - vpshufb L_chacha20_avx2_rotl8(%rip), %ymm13, %ymm13 + vpshufb (%r11), %ymm13, %ymm13 vpaddd %ymm13, %ymm9, %ymm9 vpxor %ymm9, %ymm5, %ymm5 vpaddd %ymm6, %ymm2, %ymm2 vpxor %ymm2, %ymm14, %ymm14 - vpshufb L_chacha20_avx2_rotl8(%rip), %ymm14, %ymm14 + vpshufb (%r11), %ymm14, %ymm14 vpaddd %ymm14, %ymm10, %ymm10 vpxor %ymm10, %ymm6, %ymm6 vpaddd %ymm7, %ymm3, %ymm3 vpxor %ymm3, %ymm15, %ymm15 - vpshufb L_chacha20_avx2_rotl8(%rip), %ymm15, %ymm15 + vpshufb (%r11), %ymm15, %ymm15 vpaddd %ymm15, %ymm11, %ymm11 vpxor %ymm11, %ymm7, %ymm7 vmovdqa %ymm11, 96(%r10) @@ -1210,22 +1234,22 @@ L_chacha20_avx2_loop256: vpaddd %ymm5, %ymm0, %ymm0 vpxor %ymm0, %ymm15, %ymm15 vmovdqa 96(%r10), %ymm11 - vpshufb L_chacha20_avx2_rotl16(%rip), %ymm15, %ymm15 + vpshufb (%r12), %ymm15, %ymm15 vpaddd %ymm15, %ymm10, %ymm10 vpxor %ymm10, %ymm5, %ymm5 vpaddd %ymm6, %ymm1, %ymm1 vpxor %ymm1, %ymm12, %ymm12 - vpshufb L_chacha20_avx2_rotl16(%rip), %ymm12, %ymm12 + vpshufb (%r12), %ymm12, %ymm12 vpaddd %ymm12, %ymm11, %ymm11 vpxor %ymm11, %ymm6, %ymm6 vpaddd %ymm7, %ymm2, %ymm2 vpxor %ymm2, %ymm13, %ymm13 - vpshufb L_chacha20_avx2_rotl16(%rip), %ymm13, %ymm13 + vpshufb (%r12), %ymm13, %ymm13 vpaddd %ymm13, %ymm8, %ymm8 vpxor %ymm8, %ymm7, %ymm7 vpaddd %ymm4, %ymm3, %ymm3 vpxor %ymm3, %ymm14, %ymm14 - vpshufb L_chacha20_avx2_rotl16(%rip), %ymm14, %ymm14 + vpshufb (%r12), %ymm14, %ymm14 vpaddd %ymm14, %ymm9, %ymm9 vpxor %ymm9, %ymm4, %ymm4 vmovdqa %ymm11, 96(%r10) @@ -1244,22 +1268,22 @@ L_chacha20_avx2_loop256: vpaddd %ymm5, %ymm0, %ymm0 vpxor %ymm0, %ymm15, %ymm15 vmovdqa 96(%r10), %ymm11 - vpshufb L_chacha20_avx2_rotl8(%rip), %ymm15, %ymm15 + vpshufb (%r11), %ymm15, %ymm15 vpaddd %ymm15, %ymm10, %ymm10 vpxor %ymm10, %ymm5, %ymm5 vpaddd %ymm6, %ymm1, %ymm1 vpxor %ymm1, %ymm12, %ymm12 - vpshufb L_chacha20_avx2_rotl8(%rip), %ymm12, %ymm12 + vpshufb (%r11), %ymm12, %ymm12 vpaddd %ymm12, %ymm11, %ymm11 vpxor %ymm11, %ymm6, %ymm6 vpaddd %ymm7, %ymm2, %ymm2 vpxor %ymm2, %ymm13, %ymm13 - vpshufb L_chacha20_avx2_rotl8(%rip), %ymm13, %ymm13 + vpshufb (%r11), %ymm13, %ymm13 vpaddd %ymm13, %ymm8, %ymm8 vpxor %ymm8, %ymm7, %ymm7 vpaddd %ymm4, %ymm3, %ymm3 vpxor %ymm3, %ymm14, %ymm14 - vpshufb L_chacha20_avx2_rotl8(%rip), %ymm14, %ymm14 + vpshufb (%r11), %ymm14, %ymm14 vpaddd %ymm14, %ymm9, %ymm9 vpxor %ymm9, %ymm4, %ymm4 vmovdqa %ymm11, 96(%r10) @@ -1409,7 +1433,7 @@ L_chacha20_avx2_loop256: vmovdqa 384(%r9), %ymm12 addq $0x200, %rsi addq $0x200, %rdx - vpaddd L_chacha20_avx2_eight(%rip), %ymm12, %ymm12 + vpaddd (%r14), %ymm12, %ymm12 subl $0x200, %ecx vmovdqa %ymm12, 384(%r9) cmpl $0x200, %ecx @@ -1440,7 +1464,11 @@ L_chacha20_avx2_end256: #else callq _chacha_encrypt_avx1 #endif /* __APPLE__ */ - addq $0x310, %rsp + vzeroupper + addq $0x320, %rsp + popq %r14 + popq %r13 + popq %r12 repz retq #ifndef __APPLE__ .size chacha_encrypt_avx2,.-chacha_encrypt_avx2 diff --git a/wolfcrypt/src/cmac.c b/wolfcrypt/src/cmac.c index c1edfc3abe..49ab1657c2 100644 --- a/wolfcrypt/src/cmac.c +++ b/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 diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index 650c33a369..30f5973869 100644 --- a/wolfcrypt/src/des3.c +++ b/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 diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 6b68601210..041915998a 100644 --- a/wolfcrypt/src/dh.c +++ b/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 diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index f8968c5614..f2e241b54a 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -290,7 +290,7 @@ int wc_dilithium_init_id(dilithium_key* key, const unsigned char* id, int len, key->idLen = len; } - /* Set the maxiumum level here */ + /* Set the maximum level here */ wc_dilithium_set_level(key, 5); return ret; @@ -317,7 +317,7 @@ int wc_dilithium_init_label(dilithium_key* key, const char* label, void* heap, key->labelLen = labelLen; } - /* Set the maxiumum level here */ + /* Set the maximum level here */ wc_dilithium_set_level(key, 5); return ret; @@ -395,7 +395,7 @@ int wc_dilithium_export_public(dilithium_key* key, return BAD_FUNC_ARG; } - if ((key->level != 1) && (key->level != 5)) { + if ((key->level != 2) && (key->level != 3) && (key->level != 5)) { return BAD_FUNC_ARG; } @@ -914,11 +914,11 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, pubKey, &pubKeyLen, keytype); if (ret == 0) { if (pubKeyLen == 0) { - ret = wc_dilithium_import_private_only(input, inSz, key); + ret = wc_dilithium_import_private_key(input, inSz, NULL, 0, key); } else { - ret = wc_dilithium_import_private_key(privKey, privKeyLen, - pubKey, pubKeyLen, key); + ret = wc_dilithium_import_private_key(input, inSz, pubKey, + pubKeyLen, key); } } return ret; @@ -983,7 +983,7 @@ int wc_Dilithium_PublicKeyToDer(dilithium_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/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 78101ed2cb..b29c19ecce 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -180,6 +180,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 @@ -1486,7 +1495,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 +1679,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 +1708,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 +1789,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 +2640,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 +2650,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 +2867,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 */ } @@ -4279,8 +4302,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); @@ -5098,11 +5124,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); } @@ -5539,11 +5587,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 @@ -6041,20 +6108,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 @@ -6108,16 +6166,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) @@ -6169,12 +6228,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 +6257,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) { @@ -7124,7 +7171,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; @@ -10468,6 +10515,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; } @@ -10862,6 +10911,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; } @@ -11168,6 +11219,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; diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index f59b672901..7a708ce627 100644 --- a/wolfcrypt/src/ed25519.c +++ b/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) { @@ -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 */ @@ -1059,7 +1134,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 +1335,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 == 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/wolfcrypt/src/ed448.c b/wolfcrypt/src/ed448.c index e93c212886..de57ba0393 100644 --- a/wolfcrypt/src/ed448.c +++ b/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,90 @@ 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 == 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 == 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/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index eebd4dbc06..58c1869182 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -604,6 +604,27 @@ 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"; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index a365ff6821..8be6246890 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -4275,23 +4275,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 +5484,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) { diff --git a/wolfcrypt/src/ext_lms.c b/wolfcrypt/src/ext_lms.c index a5155076b2..7a59576672 100644 --- a/wolfcrypt/src/ext_lms.c +++ b/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/wolfcrypt/src/ext_xmss.c b/wolfcrypt/src/ext_xmss.c index 84498d9a37..9ce012e255 100644 --- a/wolfcrypt/src/ext_xmss.c +++ b/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/wolfcrypt/src/falcon.c b/wolfcrypt/src/falcon.c index 2645db6393..eef982cad7 100644 --- a/wolfcrypt/src/falcon.c +++ b/wolfcrypt/src/falcon.c @@ -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; @@ -846,11 +846,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 +912,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/wolfcrypt/src/fe_448.c b/wolfcrypt/src/fe_448.c index 73853b79e7..36c6096945 100644 --- a/wolfcrypt/src/fe_448.c +++ b/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/wolfcrypt/src/fe_operations.c b/wolfcrypt/src/fe_operations.c index 18e2b05e80..5f4fd1fdc0 100644 --- a/wolfcrypt/src/fe_operations.c +++ b/wolfcrypt/src/fe_operations.c @@ -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/wolfcrypt/src/fe_x25519_128.i b/wolfcrypt/src/fe_x25519_128.i index eff2d408eb..afeea24b40 100644 --- a/wolfcrypt/src/fe_x25519_128.i +++ b/wolfcrypt/src/fe_x25519_128.i @@ -600,7 +600,7 @@ void fe_sq2(fe r, const fe a) * in An array of bytes. * returns a 64-bit word. */ -word64 load_3(const unsigned char *in) +sword64 load_3(const unsigned char *in) { word64 result; @@ -608,7 +608,7 @@ word64 load_3(const unsigned char *in) (((word64)in[1]) << 8) | (((word64)in[2]) << 16)); - return result; + return (sword64)result; } /* Load 4 little endian bytes into a 64-bit word. @@ -616,7 +616,7 @@ word64 load_3(const unsigned char *in) * in An array of bytes. * returns a 64-bit word. */ -word64 load_4(const unsigned char *in) +sword64 load_4(const unsigned char *in) { word64 result; @@ -625,6 +625,6 @@ word64 load_4(const unsigned char *in) (((word64)in[2]) << 16) | (((word64)in[3]) << 24)); - return result; + return (sword64)result; } diff --git a/wolfcrypt/src/ge_448.c b/wolfcrypt/src/ge_448.c index 5ce8ea75d7..d2033af9a8 100644 --- a/wolfcrypt/src/ge_448.c +++ b/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/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 9a80cb1e2e..0608973552 100644 --- a/wolfcrypt/src/hmac.c +++ b/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) { diff --git a/wolfcrypt/src/kdf.c b/wolfcrypt/src/kdf.c index 55b7ab0c31..15672e8f42 100644 --- a/wolfcrypt/src/kdf.c +++ b/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) @@ -936,7 +942,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 +1099,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 +1111,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 +1151,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 +1178,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). diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index 4b068ce9cd..61fe735b6c 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -521,7 +521,7 @@ struct wc_Memory { /* 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, +static int wc_create_memory_buckets(byte* buffer, word32 bufSz, word32 buckSz, word32 buckNum, wc_Memory** list) { word32 i; byte* pt = buffer; @@ -562,19 +562,79 @@ 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; + word32 memSz = (word32)sizeof(wc_Memory); + word32 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 >= (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 = 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 { + 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 = 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; + } + } + } } + return 1; +} + +static int wc_init_memory_heap(WOLFSSL_HEAP* heap, unsigned int listSz, + const unsigned int* sizeList, const unsigned int* distList) +{ XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP)); - XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz)); - XMEMCPY(heap->distList, wc_Dist, sizeof(wc_Dist)); + XMEMCPY(heap->sizeList, sizeList, listSz * sizeof(sizeList[0])); + XMEMCPY(heap->distList, distList, listSz * sizeof(distList[0])); if (wc_InitMutex(&(heap->memory_mutex)) != 0) { WOLFSSL_MSG("Error creating heap memory mutex"); @@ -584,19 +644,25 @@ int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap) 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) { - int ret; - WOLFSSL_HEAP* heap; - WOLFSSL_HEAP_HINT* hint; + WOLFSSL_HEAP* heap = NULL; + WOLFSSL_HEAP_HINT* hint = NULL; word32 idx = 0; + int ret; - if (pHint == NULL || buf == NULL) { + WOLFSSL_ENTER("wc_LoadStaticMemory_ex"); + + if (pHint == NULL || buf == NULL || listSz > WOLFMEM_MAX_BUCKETS + || sizeList == NULL || distList == NULL) { return BAD_FUNC_ARG; } 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 +673,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,10 +693,10 @@ 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; } /* determine what max applies too */ @@ -644,78 +710,31 @@ int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, heap->flag |= flag; *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); -#endif - - /* 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; - } - - /* check if no more room left for creating IO buffers */ - if (ret == 0) { - break; - } + word32 sizeList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + word32 distList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; + int ret = 0; + + 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; +} - /* 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; } @@ -731,19 +750,19 @@ 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 || listSz > WOLFMEM_MAX_BUCKETS + || sizeList == NULL || distList == NULL) { return BAD_FUNC_ARG; } @@ -764,26 +783,39 @@ int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) else { 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"); diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index 123b2e9db4..e76f1b1a8e 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -1120,7 +1120,7 @@ static WARN_UNUSED_RESULT int freeDecCertList(WC_DerCertList** list, InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap); if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) { - if (wc_CheckPrivateKeyCert(*pkey, *pkeySz, DeCert) == 1) { + if (wc_CheckPrivateKeyCert(*pkey, *pkeySz, DeCert, 0) == 1) { WOLFSSL_MSG("Key Pair found"); *cert = current->buffer; *certSz = current->bufferSz; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 997fd4f067..96a39f3a52 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2517,7 +2517,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 @@ -9746,7 +9746,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) StreamOctetString(NULL, 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, diff --git a/wolfcrypt/src/poly1305_asm.S b/wolfcrypt/src/poly1305_asm.S index ba1d29449c..5eaa6d36fb 100644 --- a/wolfcrypt/src/poly1305_asm.S +++ b/wolfcrypt/src/poly1305_asm.S @@ -1,6 +1,6 @@ /* poly1305_asm.S */ /* - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -699,7 +699,11 @@ _poly1305_blocks_avx2: #endif /* __APPLE__ */ pushq %r12 pushq %rbx + pushq %r13 + pushq %r14 subq $0x140, %rsp + leaq L_poly1305_avx2_blocks_mask(%rip), %r13 + leaq L_poly1305_avx2_blocks_hibit(%rip), %r14 movq %rsp, %rcx andq $-32, %rcx addq $32, %rcx @@ -720,11 +724,11 @@ _poly1305_blocks_avx2: vpunpckhdq %ymm15, %ymm1, %ymm1 vpunpckldq %ymm15, %ymm3, %ymm2 vpunpckhdq %ymm15, %ymm3, %ymm3 - vmovdqu L_poly1305_avx2_blocks_hibit(%rip), %ymm4 + vmovdqu (%r14), %ymm4 vpsllq $6, %ymm1, %ymm1 vpsllq $12, %ymm2, %ymm2 vpsllq $18, %ymm3, %ymm3 - vmovdqu L_poly1305_avx2_blocks_mask(%rip), %ymm14 + vmovdqu (%r13), %ymm14 # Reduce, in place, the message data vpsrlq $26, %ymm0, %ymm10 vpsrlq $26, %ymm3, %ymm11 @@ -811,7 +815,7 @@ L_poly1305_avx2_blocks_mul_5: vmovdqa %ymm7, 64(%rcx) vmovdqa %ymm8, 96(%rcx) vmovdqa %ymm9, 128(%rcx) - vmovdqu L_poly1305_avx2_blocks_mask(%rip), %ymm14 + vmovdqu (%r13), %ymm14 # If not finished then loop over data cmpb $0x01, 616(%rdi) jne L_poly1305_avx2_blocks_start @@ -922,7 +926,7 @@ L_poly1305_avx2_blocks_start: vpunpckhdq %ymm15, %ymm6, %ymm6 vpunpckldq %ymm15, %ymm8, %ymm7 vpunpckhdq %ymm15, %ymm8, %ymm8 - vmovdqu L_poly1305_avx2_blocks_hibit(%rip), %ymm9 + vmovdqu (%r14), %ymm9 vpsllq $6, %ymm6, %ymm6 vpsllq $12, %ymm7, %ymm7 vpsllq $18, %ymm8, %ymm8 @@ -1038,7 +1042,10 @@ L_poly1305_avx2_blocks_end_calc: movq %rcx, 40(%rdi) L_poly1305_avx2_blocks_complete: movb $0x01, 617(%rdi) + vzeroupper addq $0x140, %rsp + popq %r14 + popq %r13 popq %rbx popq %r12 repz retq @@ -1118,6 +1125,7 @@ L_poly1305_avx2_final_cmp_copy: vmovdqu %ymm0, 320(%rdi) movq $0x00, 608(%rdi) movw $0x00, 616(%rdi) + vzeroupper repz retq #ifndef __APPLE__ .size poly1305_final_avx2,.-poly1305_final_avx2 diff --git a/wolfcrypt/src/port/Espressif/esp32_mp.c b/wolfcrypt/src/port/Espressif/esp32_mp.c index 1afda2b832..64959a47f9 100644 --- a/wolfcrypt/src/port/Espressif/esp32_mp.c +++ b/wolfcrypt/src/port/Espressif/esp32_mp.c @@ -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,7 +1839,7 @@ 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*/ ret = esp_mp_mul(X, Y, tmpZ); /* HW X * Y */ if (ret == MP_OKAY) { /* z = tmpZ mod M, 0 <= Z < M */ @@ -1973,13 +1973,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 @@ -2500,15 +2500,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 */ diff --git a/wolfcrypt/src/port/Espressif/esp32_sha.c b/wolfcrypt/src/port/Espressif/esp32_sha.c index 332c532a6c..a2244af173 100644 --- a/wolfcrypt/src/port/Espressif/esp32_sha.c +++ b/wolfcrypt/src/port/Espressif/esp32_sha.c @@ -128,7 +128,7 @@ static const char* TAG = "wolf_hw_sha"; #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; @@ -1130,7 +1130,7 @@ int esp_sha_release_unfinished_lock(WC_ESP32SHA* ctx) #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); diff --git a/wolfcrypt/src/port/Espressif/esp32_util.c b/wolfcrypt/src/port/Espressif/esp32_util.c index 829afa4a60..03e973ee34 100644 --- a/wolfcrypt/src/port/Espressif/esp32_util.c +++ b/wolfcrypt/src/port/Espressif/esp32_util.c @@ -76,7 +76,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 /* diff --git a/wolfcrypt/src/port/Renesas/renesas_common.c b/wolfcrypt/src/port/Renesas/renesas_common.c index 00deff3df9..72210bea5e 100644 --- a/wolfcrypt/src/port/Renesas/renesas_common.c +++ b/wolfcrypt/src/port/Renesas/renesas_common.c @@ -59,7 +59,7 @@ static int gdevId = 7890; /* initial dev Id for Crypt Callback */ defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY) FSPSM_ST *gCbCtx[MAX_FSPSM_CBINDEX]; #elif defined(WOLFSSL_RENESAS_TSIP_TLS) || \ - defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY) + defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY) #define FSPSM_ST TsipUserCtx; #define MAX_FSPSM_CBINDEX 5 TsipUserCtx *gCbCtx[MAX_FSPSM_CBINDEX]; @@ -361,8 +361,14 @@ static int Renesas_cmn_CryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) * in advance. SCE supports 1024 or 2048 bits key size. * otherwise, falls-through happens. */ - if (info->pk.rsa.key->ctx.keySz == 1024 || - info->pk.rsa.key->ctx.keySz == 2048) { + if (cbInfo->keyflgs_crypt.bits.rsapri2048_installedkey_set || + cbInfo->keyflgs_crypt.bits.rsapub2048_installedkey_set || + cbInfo->keyflgs_crypt.bits.rsapri1024_installedkey_set || + cbInfo->keyflgs_crypt.bits.rsapub1024_installedkey_set ) { + + ret = wc_fspsm_MakeRsaKey(info->pk.rsa.key, 0, cbInfo); + if (ret == CRYPTOCB_UNAVAILABLE) + return ret; if (info->pk.rsa.type == RSA_PRIVATE_DECRYPT || info->pk.rsa.type == RSA_PUBLIC_ENCRYPT ) @@ -370,7 +376,7 @@ static int Renesas_cmn_CryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) ret = wc_fspsm_RsaFunction(info->pk.rsa.in, info->pk.rsa.inLen, info->pk.rsa.out, - &info->pk.rsa.outLen, + info->pk.rsa.outLen, info->pk.rsa.type, info->pk.rsa.key, info->pk.rsa.rng); diff --git a/wolfcrypt/src/port/Renesas/renesas_fspsm_aes.c b/wolfcrypt/src/port/Renesas/renesas_fspsm_aes.c index cb0535735f..37a2bedeaf 100644 --- a/wolfcrypt/src/port/Renesas/renesas_fspsm_aes.c +++ b/wolfcrypt/src/port/Renesas/renesas_fspsm_aes.c @@ -72,7 +72,7 @@ typedef fsp_err_t (*aesGcmDecFinalFn) #if defined(WOLFSSL_RENESAS_RSIP) /* wrapper for Gcm encrypt init */ -static fsp_err_t _R_RSIP_AES_GCM_EncryptInit(FSPSM_AESGCM_HANDLE* h, +static fsp_err_t _R_RSIP_AES_GCM_EncryptInit(FSPSM_AESGCM_HANDLE* h, FSPSM_AES_PWKEY k, uint8_t* iv, uint32_t iv_l) { @@ -81,8 +81,8 @@ static fsp_err_t _R_RSIP_AES_GCM_EncryptInit(FSPSM_AESGCM_HANDLE* h, (uint8_t* const)iv, iv_l); } /* wrapper for Gcm encrypt update */ -static fsp_err_t _R_RSIP_AES_GCM_EncryptUpdate(FSPSM_AESGCM_HANDLE* h, - uint8_t* p_plain, uint8_t* p_cipher, uint32_t plain_length, +static fsp_err_t _R_RSIP_AES_GCM_EncryptUpdate(FSPSM_AESGCM_HANDLE* h, + uint8_t* p_plain, uint8_t* p_cipher, uint32_t plain_length, uint8_t* p_add, uint32_t add_len) { (void) h; @@ -93,8 +93,8 @@ static fsp_err_t _R_RSIP_AES_GCM_EncryptUpdate(FSPSM_AESGCM_HANDLE* h, (uint32_t const) add_len); } /* wrapper for Gcm encrypt final */ -static fsp_err_t _R_RSIP_AES_GCM_EncryptFinal(FSPSM_AESGCM_HANDLE* h, - uint8_t* p_cipher, uint32_t* c_len, +static fsp_err_t _R_RSIP_AES_GCM_EncryptFinal(FSPSM_AESGCM_HANDLE* h, + uint8_t* p_cipher, uint32_t* c_len, uint8_t* p_atag) { (void) h; @@ -103,7 +103,7 @@ static fsp_err_t _R_RSIP_AES_GCM_EncryptFinal(FSPSM_AESGCM_HANDLE* h, (uint8_t* const) p_atag); } /* wrapper for Gcm decrypt init */ -static fsp_err_t _R_RSIP_AES_GCM_DecryptInit(FSPSM_AESGCM_HANDLE* h, +static fsp_err_t _R_RSIP_AES_GCM_DecryptInit(FSPSM_AESGCM_HANDLE* h, FSPSM_AES_PWKEY k, uint8_t* iv, uint32_t iv_l) { (void) h; @@ -111,8 +111,8 @@ static fsp_err_t _R_RSIP_AES_GCM_DecryptInit(FSPSM_AESGCM_HANDLE* h, (uint8_t* const)iv, iv_l); } /* wrapper for Gcm decrypt update */ -static fsp_err_t _R_RSIP_AES_GCM_DecryptUpdate(FSPSM_AESGCM_HANDLE* h, - uint8_t* p_cipher, uint8_t* p_plain, uint32_t c_length, +static fsp_err_t _R_RSIP_AES_GCM_DecryptUpdate(FSPSM_AESGCM_HANDLE* h, + uint8_t* p_cipher, uint8_t* p_plain, uint32_t c_length, uint8_t* p_add, uint32_t add_len) { (void) h; @@ -123,8 +123,8 @@ static fsp_err_t _R_RSIP_AES_GCM_DecryptUpdate(FSPSM_AESGCM_HANDLE* h, (uint32_t const) add_len); } /* wrapper for Gcm decrypt final */ -static fsp_err_t _R_RSIP_AES_GCM_DecryptFinal(FSPSM_AESGCM_HANDLE* h, - uint8_t* p_plain, uint32_t* plain_len, +static fsp_err_t _R_RSIP_AES_GCM_DecryptFinal(FSPSM_AESGCM_HANDLE* h, + uint8_t* p_plain, uint32_t* plain_len, uint8_t* p_atag, uint32_t atag_len) { (void) h; @@ -241,7 +241,7 @@ WOLFSSL_LOCAL int wc_fspsm_AesGcmEncrypt(struct Aes* aes, byte* out, FSPSM_AES_PWKEY key_client_aes = NULL; FSPSM_AES_PWKEY key_server_aes = NULL; (void) key_server_aes; - + /* sanity check */ if (aes == NULL || authTagSz > AES_BLOCK_SIZE || ivSz == 0 || ctx == NULL) { return BAD_FUNC_ARG; @@ -282,7 +282,7 @@ WOLFSSL_LOCAL int wc_fspsm_AesGcmEncrypt(struct Aes* aes, byte* out, aTagBuf = XMALLOC(SCE_AES_GCM_AUTH_TAG_SIZE, aes->heap, DYNAMIC_TYPE_AES); - if ((sz > 0 && plainBuf == NULL) || + if ((sz > 0 && plainBuf == NULL) || ((sz + delta) > 0 && cipherBuf == NULL) || aTagBuf == NULL) { WOLFSSL_MSG("wc_fspsm_AesGcmEncrypt: buffer allocation failed"); ret = -1; @@ -293,7 +293,7 @@ WOLFSSL_LOCAL int wc_fspsm_AesGcmEncrypt(struct Aes* aes, byte* out, XMEMSET((void*)cipherBuf, 0, sz + delta); XMEMSET((void*)authTag, 0, authTagSz); } - + #if defined(WOLFSSL_RENESAS_FSPSM_TLS) if (ret == 0 && info->keyflgs_tls.bits.session_key_set == 1) { @@ -310,7 +310,7 @@ WOLFSSL_LOCAL int wc_fspsm_AesGcmEncrypt(struct Aes* aes, byte* out, XFREE(aTagBuf, aes->heap, DYNAMIC_TYPE_AES); return MEMORY_E; } - + ret = FSPSM_SESSIONKEY_GEN_FUNC( info->cipher, (uint32_t*)info->masterSecret, @@ -514,7 +514,7 @@ WOLFSSL_LOCAL int wc_fspsm_AesGcmDecrypt(struct Aes* aes, byte* out, XFREE(aTagBuf, aes->heap, DYNAMIC_TYPE_AES); return MEMORY_E; } - + ret = FSPSM_SESSIONKEY_GEN_FUNC( info->cipher, (uint32_t*)info->masterSecret, @@ -547,7 +547,7 @@ WOLFSSL_LOCAL int wc_fspsm_AesGcmDecrypt(struct Aes* aes, byte* out, ret = -1; } } - + if (ret == 0) { /* since key_index has iv and ivSz in it, no need to pass them init * func. Pass NULL and 0 as 3rd and 4th parameter respectively. @@ -769,7 +769,7 @@ WOLFSSL_LOCAL void wc_fspsm_Aesfree(Aes* aes) } #else if (aes->ctx.wrapped_key) { - /* aes ctx just points user created wrapped key + /* aes ctx just points user created wrapped key * in the case of CryptOnly Mode * therefore, it just sets pointing to NULL. * user key should be freed by owner(user) @@ -785,8 +785,8 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, { (void) userKey; (void) dir; - - if (aes == NULL || userKey == NULL || + + if (aes == NULL || userKey == NULL || !((keylen == 16) || (keylen == 32))) { return BAD_FUNC_ARG; } @@ -806,7 +806,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, aes->ctx.wrapped_key = (FSPSM_AES_PWKEY)userKey; aes->keylen = (int)keylen; aes->ctx.keySize = keylen; - + return wc_AesSetIV(aes, iv); } #endif diff --git a/wolfcrypt/src/port/Renesas/renesas_fspsm_rsa.c b/wolfcrypt/src/port/Renesas/renesas_fspsm_rsa.c index 5db4435d52..778e5fff6f 100644 --- a/wolfcrypt/src/port/Renesas/renesas_fspsm_rsa.c +++ b/wolfcrypt/src/port/Renesas/renesas_fspsm_rsa.c @@ -1,6 +1,6 @@ /* renesas_fspsm_rsa.c * - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -40,7 +40,7 @@ extern FSPSM_INSTANCE gFSPSM_ctrl; #endif -/* Set Ctx pointer to NULL. +/* Set Ctx pointer to NULL. * A created wrapped key should be freed by user * * key RsaKey object @@ -99,6 +99,33 @@ WOLFSSL_LOCAL int wc_fspsm_MakeRsaKey(RsaKey *key, int size, void* ctx) key->ctx.wrapped_pri2048_key = info->wrapped_key_rsapri2048; key->ctx.wrapped_pub2048_key = info->wrapped_key_rsapub2048; key->ctx.keySz = 2048; + } else if (size == 0) { + if((info->keyflgs_crypt.bits.rsapri2048_installedkey_set != 1) && + (info->keyflgs_crypt.bits.rsapub2048_installedkey_set != 1) && + (info->keyflgs_crypt.bits.rsapri1024_installedkey_set != 1) && + (info->keyflgs_crypt.bits.rsapub1024_installedkey_set != 1)) { + WOLFSSL_MSG("Caller should create user key in advance."); + WOLFSSL_MSG("Caller also need to installedkey to 1."); + return BAD_FUNC_ARG; + } + + if (info->keyflgs_crypt.bits.rsapri1024_installedkey_set == 1) { + key->ctx.wrapped_pri1024_key = info->wrapped_key_rsapri1024; + key->ctx.keySz = 1024; + } + if (info->keyflgs_crypt.bits.rsapub1024_installedkey_set == 1) { + key->ctx.wrapped_pub1024_key = info->wrapped_key_rsapub1024; + key->ctx.keySz = 1024; + } + + if (info->keyflgs_crypt.bits.rsapri2048_installedkey_set == 1) { + key->ctx.wrapped_pri2048_key = info->wrapped_key_rsapri2048; + key->ctx.keySz = 2048; + } + if (info->keyflgs_crypt.bits.rsapub2048_installedkey_set == 1) { + key->ctx.wrapped_pub2048_key = info->wrapped_key_rsapub2048; + key->ctx.keySz = 2048; + } } else return CRYPTOCB_UNAVAILABLE; @@ -122,23 +149,22 @@ WOLFSSL_LOCAL int wc_fspsm_RsaFunction(const byte* in, word32 inLen, byte* out, struct WC_RNG* rng) { int ret; - + FSPSM_RSA_DATA plain; FSPSM_RSA_DATA cipher; - + int keySize; - + (void) key; (void) rng; - + /* sanity check */ - if (in == NULL || out == NULL || - ((key == NULL) && (key->ctx.keySz != 1024 && key->ctx.keySz != 2048))){ + if (in == NULL || out == NULL || key == NULL){ return BAD_FUNC_ARG; } - + keySize = (int)key->ctx.keySz; - + if (keySize == 0) { WOLFSSL_MSG("keySize is invalid, neither 128 or 256 bytes, " "1024 or 2048 bits."); @@ -147,7 +173,7 @@ WOLFSSL_LOCAL int wc_fspsm_RsaFunction(const byte* in, word32 inLen, byte* out, if ((ret = wc_fspsm_hw_lock()) == 0) { if (type == RSA_PUBLIC_ENCRYPT) { - + plain.pdata = (byte*)in; plain.data_length = inLen; cipher.pdata = out; @@ -169,7 +195,7 @@ WOLFSSL_LOCAL int wc_fspsm_RsaFunction(const byte* in, word32 inLen, byte* out, plain.data_length = *outLen; cipher.pdata = (byte*)in; cipher.data_length = inLen; - + if (keySize == 1024) { ret = FSPSM_RSA1024_PKCSDEC_FUNC(&cipher, &plain, (FSPSM_RSA1024_WPI_KEY*) @@ -181,7 +207,7 @@ WOLFSSL_LOCAL int wc_fspsm_RsaFunction(const byte* in, word32 inLen, byte* out, key->ctx.wrapped_pri2048_key, &outLen); } } - + wc_fspsm_hw_unlock(); } return ret; @@ -189,7 +215,7 @@ WOLFSSL_LOCAL int wc_fspsm_RsaFunction(const byte* in, word32 inLen, byte* out, /* Perform Rsa sign by FSP SM * Assumes to be called by Crypt Callback - * + * * in Buffer to hold plaintext * inLen Length of plaintext in bytes * out Buffer to hold generated signature @@ -198,40 +224,40 @@ WOLFSSL_LOCAL int wc_fspsm_RsaFunction(const byte* in, word32 inLen, byte* out, * ctx The callback context * return FSP_SUCCESS(0) on Success, otherwise negative value */ - + WOLFSSL_LOCAL int wc_fspsm_RsaSign(const byte* in, word32 inLen, byte* out, word32* outLen, struct RsaKey* key, void* ctx) { int ret; - + FSPSM_RSA_DATA message_hash; FSPSM_RSA_DATA signature; FSPSM_ST *info = (FSPSM_ST*)ctx; int keySize; - + /* sanity check */ - if (in == NULL || out == NULL || (word32*)outLen <= 0 || info == NULL || - ((key == NULL) && (key->ctx.keySz != 1024 && key->ctx.keySz != 2048))){ + if (in == NULL || out == NULL || *outLen <= 0 || info == NULL || + key == NULL){ return BAD_FUNC_ARG; } - + keySize = (int)key->ctx.keySz; - + message_hash.pdata = (byte *)in; message_hash.data_length = inLen; - message_hash.data_type = + message_hash.data_type = info->keyflgs_crypt.bits.message_type;/* message 0, hash 1 */ signature.pdata = out; signature.data_length = (word32*)outLen; - + #if defined(WOLFSSL_RENESAS_RSIP) - message_hash.hash_type = signature.hash_type = + message_hash.hash_type = signature.hash_type = info->hash_type; /* hash type */ #endif - + if ((ret = wc_fspsm_hw_lock()) == 0) { if (keySize == 1024) { - + ret = FSPSM_RSA1024_SIGN_FUNC(&message_hash, &signature, (FSPSM_RSA1024_WPI_KEY *) @@ -239,23 +265,23 @@ WOLFSSL_LOCAL int wc_fspsm_RsaSign(const byte* in, word32 inLen, byte* out, HW_SCE_RSA_HASH_SHA256); } else { - + ret = FSPSM_RSA2048_SIGN_FUNC(&message_hash, &signature, (FSPSM_RSA2048_WPI_KEY *) key->ctx.wrapped_pri2048_key, HW_SCE_RSA_HASH_SHA256); } - + wc_fspsm_hw_unlock(); } - + return ret; } /* Perform Rsa verify by FSP SM * Assumes to be called by Crypt Callback - * + * * in Buffer to hold plaintext * inLen Length of plaintext in bytes * out Buffer to hold generated signature @@ -264,40 +290,40 @@ WOLFSSL_LOCAL int wc_fspsm_RsaSign(const byte* in, word32 inLen, byte* out, * ctx The callback context * return FSP_SUCCESS(0) on Success, otherwise negative value */ - + WOLFSSL_LOCAL int wc_fspsm_RsaVerify(const byte* in, word32 inLen, byte* out, word32* outLen,struct RsaKey* key, void* ctx) { int ret; - + FSPSM_RSA_DATA message_hash; FSPSM_RSA_DATA signature; FSPSM_ST *info = (FSPSM_ST*)ctx; int keySize; - + (void) key; - + /* sanity check */ - if (in == NULL || out == NULL || (word32*)outLen <= 0 || info == NULL || - ((key == NULL) && (key->ctx.keySz != 1024 && key->ctx.keySz != 2048))){ + if (in == NULL || out == NULL || *outLen <= 0 || info == NULL || + key == NULL){ return BAD_FUNC_ARG; } - + keySize = (int)key->ctx.keySz; - - + + message_hash.pdata =(byte*)in; message_hash.data_length = inLen; - message_hash.data_type = + message_hash.data_type = info->keyflgs_crypt.bits.message_type;/* message 0, hash 1 */ - + signature.pdata = out; - signature.data_length = (word32*)outLen; + signature.data_length = (word32)*outLen; #if defined(WOLFSSL_RENESAS_RSIP) - message_hash.hash_type = signature.hash_type = + message_hash.hash_type = signature.hash_type = info->hash_type; /* hash type */ #endif - + if ((ret = wc_fspsm_hw_lock()) == 0) { if (keySize == 1024) { ret = FSPSM_RSA1024_VRY_FUNC(&signature, @@ -307,7 +333,7 @@ WOLFSSL_LOCAL int wc_fspsm_RsaVerify(const byte* in, word32 inLen, byte* out, HW_SCE_RSA_HASH_SHA256); } else { - ret = FSPSM_RSA2048_VRY_FUNC(&signature, + ret = FSPSM_RSA2048_VRY_FUNC(&signature, &message_hash, (FSPSM_RSA2048_WPB_KEY *) key->ctx.wrapped_pub2048_key, @@ -315,7 +341,7 @@ WOLFSSL_LOCAL int wc_fspsm_RsaVerify(const byte* in, word32 inLen, byte* out, } wc_fspsm_hw_unlock(); } - + return ret; } diff --git a/wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c b/wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c index 52df6da3dd..bba843ed02 100644 --- a/wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c +++ b/wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c @@ -149,14 +149,14 @@ static int FSPSM_HashInit(wolfssl_FSPSM_Hash* hash, void* heap, int devId, XMEMSET(hash, 0, sizeof(wolfssl_FSPSM_Hash)); hash->sha_type = sha_type; hash->heap = heap; - + #if defined(WOLFSSL_RENESAS_SCEPROTECT) hash->len = 0; hash->used = 0; hash->msg = NULL; - + #elif defined(WOLFSSL_RENESAS_RSIP) - + switch(hash->sha_type) { case FSPSM_SHA1: Init = FSPSM_SHA1_Init; @@ -244,7 +244,7 @@ static int FSPSM_HashUpdate(wolfssl_FSPSM_Hash* hash, XMEMCPY(hash->msg + hash->used, data , sz); hash->used += sz; #elif defined(WOLFSSL_RENESAS_RSIP) - + switch(hash->sha_type) { case FSPSM_SHA1: Update = FSPSM_SHA1_Up; @@ -271,7 +271,7 @@ static int FSPSM_HashUpdate(wolfssl_FSPSM_Hash* hash, return BAD_FUNC_ARG; } wc_fspsm_hw_lock(); - ret = Update(&hash->handle, data, sz); + ret = Update(&hash->handle, (byte*)data, sz); wc_fspsm_hw_unlock(); return ret; #endif @@ -309,7 +309,7 @@ static int FSPSM_HashFinal(wolfssl_FSPSM_Hash* hash, byte* out, word32 outSz) Final = FSPSM_SHA256_Final; } else return BAD_FUNC_ARG; - + wc_fspsm_hw_lock(); if (Init(&handle) == FSP_SUCCESS) { @@ -328,7 +328,7 @@ static int FSPSM_HashFinal(wolfssl_FSPSM_Hash* hash, byte* out, word32 outSz) } } wc_fspsm_hw_unlock(); - + #elif defined(WOLFSSL_RENESAS_RSIP) switch(hash->sha_type) { case FSPSM_SHA1: @@ -355,7 +355,7 @@ static int FSPSM_HashFinal(wolfssl_FSPSM_Hash* hash, byte* out, word32 outSz) default: return BAD_FUNC_ARG; } - + wc_fspsm_hw_lock(); ret = Final(&hash->handle, out, (uint32_t*)&sz); if (ret != FSP_SUCCESS) { @@ -380,7 +380,7 @@ static int FSPSM_HashGet(wolfssl_FSPSM_Hash* hash, byte* out, word32 outSz) fsp_err_t (*Final )(FSPSM_SHA_HANDLE*, uint8_t*, uint32_t*); uint32_t sz = 0; (void) outSz; - + #if defined(WOLFSSL_RENESAS_SCEPROTECT) FSPSM_SHA_HANDLE handle; fsp_err_t (*Init)(FSPSM_SHA_HANDLE*); @@ -401,7 +401,7 @@ static int FSPSM_HashGet(wolfssl_FSPSM_Hash* hash, byte* out, word32 outSz) Final = FSPSM_SHA256_Final; } else return BAD_FUNC_ARG; - + wc_fspsm_hw_lock(); if (Init(&handle) == FSP_SUCCESS) { ret = Update(&handle, (uint8_t*)hash->msg, hash->used); @@ -419,7 +419,7 @@ static int FSPSM_HashGet(wolfssl_FSPSM_Hash* hash, byte* out, word32 outSz) } } wc_fspsm_hw_unlock(); - + #elif defined(WOLFSSL_RENESAS_RSIP) switch(hash->sha_type) { case FSPSM_SHA1: @@ -446,8 +446,8 @@ static int FSPSM_HashGet(wolfssl_FSPSM_Hash* hash, byte* out, word32 outSz) default: return BAD_FUNC_ARG; } - - + + if(FSPSM_HashCopy(hash, &hashCopy) != 0) { WOLFSSL_MSG("ShaCopy operation failed"); WOLFSSL_ERROR(WC_HW_E); @@ -461,7 +461,7 @@ static int FSPSM_HashGet(wolfssl_FSPSM_Hash* hash, byte* out, word32 outSz) ret = WC_HW_E; } wc_fspsm_hw_unlock(); - + #endif return ret; diff --git a/wolfcrypt/src/port/Renesas/renesas_fspsm_util.c b/wolfcrypt/src/port/Renesas/renesas_fspsm_util.c index 1ecf750ead..f0d19e758e 100644 --- a/wolfcrypt/src/port/Renesas/renesas_fspsm_util.c +++ b/wolfcrypt/src/port/Renesas/renesas_fspsm_util.c @@ -135,7 +135,7 @@ WOLFSSL_LOCAL int wc_fspsm_Open() if (ret != FSP_SUCCESS) { WOLFSSL_MSG("RENESAS SCE Open failed"); } - + #if defined(WOLFSSL_RENESAS_FSPSM_TLS) if (ret == FSP_SUCCESS && g_user_key_info.encrypted_user_tls_key) { @@ -184,11 +184,11 @@ WOLFSSL_LOCAL void wc_fspsm_Close() } #define RANDGEN_WORDS 4 -WOLFSSL_LOCAL int wc_fspsm_GenerateRandBlock(byte* output, word32 sz) +WOLFSSL_LOCAL int wc_fspsm_GenerateRandBlock(byte* output, word32 sz) { /* Generate PRNG based on NIST SP800-90A AES CTR-DRBG */ int ret = 0; - word32 buffer[RANDGEN_WORDS]; + word32 fspbuf[RANDGEN_WORDS]; while (sz > 0) { word32 len = sizeof(buffer); @@ -197,9 +197,9 @@ WOLFSSL_LOCAL int wc_fspsm_GenerateRandBlock(byte* output, word32 sz) len = sz; } /* return 4 words random number*/ - ret = R_RANDOM_GEN(buffer); + ret = R_RANDOM_GEN((uint8_t* const)fspbuf); if(ret == FSP_SUCCESS) { - XMEMCPY(output, &buffer, len); + XMEMCPY(output, &fspbuf, len); output += len; sz -= len; } else { @@ -384,7 +384,7 @@ WOLFSSL_LOCAL int wc_fspsm_EccVerifyTLS(WOLFSSL* ssl, const uint8_t* sig, #if defined(WOLFSSL_RENESAS_FSPSM_TLS) || \ defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY) - + /* Callback for ECC shared secret */ WOLFSSL_LOCAL int fspsm_EccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, uint8_t* pubKeyDer, unsigned int* pubKeySz, @@ -723,7 +723,7 @@ WOLFSSL_LOCAL int wc_fspsm_generateSessionKey(WOLFSSL *ssl, Ciphers *dec; FSPSM_HMAC_WKEY key_client_mac; FSPSM_HMAC_WKEY key_server_mac; - + FSPSM_AES_PWKEY key_client_aes = NULL; FSPSM_AES_PWKEY key_server_aes = NULL; @@ -752,7 +752,7 @@ WOLFSSL_LOCAL int wc_fspsm_generateSessionKey(WOLFSSL *ssl, if (key_client_aes == NULL || key_server_aes == NULL) { return MEMORY_E; } - + ret = FSPSM_SESSIONKEY_GEN_FUNC( GetSceCipherSuite( ssl->options.cipherSuite0, @@ -802,7 +802,7 @@ WOLFSSL_LOCAL int wc_fspsm_generateSessionKey(WOLFSSL *ssl, return MEMORY_E; } XMEMSET(dec->aes, 0, sizeof(Aes)); - + dec->aes->ctx.wrapped_key = (FSPSM_AES_PWKEY)XMALLOC (sizeof(FSPSM_AES_WKEY), aes->heap, DYNAMIC_TYPE_AE); @@ -853,15 +853,15 @@ WOLFSSL_LOCAL int wc_fspsm_generateSessionKey(WOLFSSL *ssl, /* marked as session key is set */ cbInfo->keyflgs_tls.bits.session_key_set = 1; } - + if (key_client_aes) XFREE(key_client_aes, aes->heap, DYNAMIC_TYPE_AES); if (key_server_aes) XFREE(key_server_aes, aes->heap, DYNAMIC_TYPE_AES); - + /* unlock hw */ wc_fspsm_hw_unlock(); - + } else { WOLFSSL_LEAVE("hw lock failed", ret); diff --git a/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c b/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c index d4f474195d..1d39e5a8e2 100644 --- a/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c +++ b/wolfcrypt/src/port/Renesas/renesas_tsip_aes.c @@ -86,9 +86,9 @@ typedef e_tsip_err_t (*Tls13AesDecFinalFn) /* encrypt plain data. - * + * * return cipher data size on success, negative value on failure. - * CRYPTOCB_UNAVAILABLE may be returned. + * CRYPTOCB_UNAVAILABLE may be returned. */ WOLFSSL_LOCAL int tsip_Tls13AesEncrypt( struct WOLFSSL* ssl, @@ -166,7 +166,7 @@ WOLFSSL_LOCAL int tsip_Tls13AesEncrypt( cs, key, sz); - + if (err != TSIP_SUCCESS) { WOLFSSL_MSG("R_TSIP_Tls13DecryptUpdate error"); ret = WC_HW_E; @@ -236,7 +236,7 @@ WOLFSSL_LOCAL int tsip_Tls13AesEncrypt( /* decrypt encrypted handshake data for TLSv1.3 * AES-GCM or AES-CCM can be used * return 0 on success, otherwise on error. - */ + */ WOLFSSL_LOCAL int tsip_Tls13AesDecrypt( struct WOLFSSL* ssl, byte* output, @@ -627,7 +627,7 @@ int wc_tsip_AesGcmEncrypt( uint8_t* aadBuf = NULL; const uint8_t* iv_l = NULL; uint32_t ivSz_l = 0; - + tsip_aes_key_index_t key_client_aes; TsipUserCtx *userCtx; @@ -722,10 +722,10 @@ int wc_tsip_AesGcmEncrypt( XMEMCPY(&key_client_aes, &userCtx->user_aes128_key_index, sizeof(tsip_aes_key_index_t)); } - + iv_l = iv; ivSz_l = ivSz; - + } if (ret == 0) { diff --git a/wolfcrypt/src/port/Renesas/renesas_tsip_rsa.c b/wolfcrypt/src/port/Renesas/renesas_tsip_rsa.c index 1a77b4020d..1da7869ebc 100644 --- a/wolfcrypt/src/port/Renesas/renesas_tsip_rsa.c +++ b/wolfcrypt/src/port/Renesas/renesas_tsip_rsa.c @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - + #include #if !defined(NO_RSA) && \ @@ -63,54 +63,54 @@ WOLFSSL_LOCAL int wc_tsip_MakeRsaKey(int size, void* ctx) if (size == 1024) { tsip_pair1024_key = (tsip_rsa1024_key_pair_index_t*)XMALLOC( - sizeof(tsip_rsa1024_key_pair_index_t), NULL, + sizeof(tsip_rsa1024_key_pair_index_t), NULL, DYNAMIC_TYPE_RSA_BUFFER); if (tsip_pair1024_key == NULL) return MEMORY_E; - + ret = R_TSIP_GenerateRsa1024RandomKeyIndex(tsip_pair1024_key); } else if (size == 2048) { tsip_pair2048_key = (tsip_rsa2048_key_pair_index_t*)XMALLOC( - sizeof(tsip_rsa2048_key_pair_index_t), NULL, + sizeof(tsip_rsa2048_key_pair_index_t), NULL, DYNAMIC_TYPE_RSA_BUFFER); if (tsip_pair2048_key == NULL) return MEMORY_E; - + ret = R_TSIP_GenerateRsa2048RandomKeyIndex(tsip_pair2048_key); } else return CRYPTOCB_UNAVAILABLE; - + if (ret == TSIP_SUCCESS) { if (size == 1024) { if (info->rsa1024pri_keyIdx != NULL) { - XFREE(info->rsa1024pri_keyIdx, NULL, + XFREE(info->rsa1024pri_keyIdx, NULL, DYNAMIC_TYPE_RSA_BUFFER); } if (info->rsa1024pub_keyIdx != NULL) { - XFREE(info->rsa1024pub_keyIdx, NULL, + XFREE(info->rsa1024pub_keyIdx, NULL, DYNAMIC_TYPE_RSA_BUFFER); } - info->rsa1024pri_keyIdx = + info->rsa1024pri_keyIdx = (tsip_rsa1024_private_key_index_t*)XMALLOC( - sizeof(tsip_rsa1024_private_key_index_t), NULL, + sizeof(tsip_rsa1024_private_key_index_t), NULL, DYNAMIC_TYPE_RSA_BUFFER); - + if (info->rsa1024pri_keyIdx == NULL) { XFREE(tsip_pair1024_key, 0, DYNAMIC_TYPE_RSA_BUFFER); return MEMORY_E; } - + info->rsa1024pub_keyIdx = (tsip_rsa1024_public_key_index_t*)XMALLOC( - sizeof(tsip_rsa1024_public_key_index_t), NULL, + sizeof(tsip_rsa1024_public_key_index_t), NULL, DYNAMIC_TYPE_RSA_BUFFER); - + if (info->rsa1024pub_keyIdx == NULL) { XFREE(tsip_pair1024_key, 0, DYNAMIC_TYPE_RSA_BUFFER); - XFREE(info->rsa1024pri_keyIdx, 0, + XFREE(info->rsa1024pri_keyIdx, 0, DYNAMIC_TYPE_RSA_BUFFER); return MEMORY_E; } @@ -118,63 +118,63 @@ WOLFSSL_LOCAL int wc_tsip_MakeRsaKey(int size, void* ctx) XMEMCPY(info->rsa1024pri_keyIdx, &tsip_pair1024_key->private, sizeof(tsip_rsa1024_private_key_index_t)); - XMEMCPY(info->rsa1024pub_keyIdx, + XMEMCPY(info->rsa1024pub_keyIdx, &tsip_pair1024_key->public, sizeof(tsip_rsa1024_public_key_index_t)); XFREE(tsip_pair1024_key, 0, DYNAMIC_TYPE_RSA_BUFFER); - + info->keyflgs_crypt.bits.rsapri1024_key_set = 1; info->keyflgs_crypt.bits.rsapub1024_key_set = 1; } else if (size == 2048) { if (info->rsa2048pri_keyIdx != NULL) { - XFREE(info->rsa2048pri_keyIdx, NULL, + XFREE(info->rsa2048pri_keyIdx, NULL, DYNAMIC_TYPE_RSA_BUFFER); } if (info->rsa2048pub_keyIdx != NULL) { - XFREE(info->rsa2048pub_keyIdx, NULL, + XFREE(info->rsa2048pub_keyIdx, NULL, DYNAMIC_TYPE_RSA_BUFFER); } - info->rsa2048pri_keyIdx = + info->rsa2048pri_keyIdx = (tsip_rsa2048_private_key_index_t*)XMALLOC( - sizeof(tsip_rsa2048_private_key_index_t), NULL, + sizeof(tsip_rsa2048_private_key_index_t), NULL, DYNAMIC_TYPE_RSA_BUFFER); - + if (info->rsa2048pri_keyIdx == NULL) { XFREE(tsip_pair2048_key, 0, DYNAMIC_TYPE_RSA_BUFFER); return MEMORY_E; } - + info->rsa2048pub_keyIdx = (tsip_rsa2048_public_key_index_t*)XMALLOC( - sizeof(tsip_rsa2048_public_key_index_t), NULL, + sizeof(tsip_rsa2048_public_key_index_t), NULL, DYNAMIC_TYPE_RSA_BUFFER); - + if (info->rsa2048pub_keyIdx == NULL) { XFREE(tsip_pair2048_key, 0, DYNAMIC_TYPE_RSA_BUFFER); - XFREE(info->rsa2048pri_keyIdx, 0, + XFREE(info->rsa2048pri_keyIdx, 0, DYNAMIC_TYPE_RSA_BUFFER); return MEMORY_E; } /* copy generated key pair and free malloced key */ - XMEMCPY(info->rsa2048pri_keyIdx, + XMEMCPY(info->rsa2048pri_keyIdx, &tsip_pair2048_key->private, sizeof(tsip_rsa2048_private_key_index_t)); - XMEMCPY(info->rsa2048pub_keyIdx, + XMEMCPY(info->rsa2048pub_keyIdx, &tsip_pair2048_key->public, sizeof(tsip_rsa2048_public_key_index_t)); XFREE(tsip_pair2048_key, 0, DYNAMIC_TYPE_RSA_BUFFER); - + info->keyflgs_crypt.bits.rsapri2048_key_set = 1; info->keyflgs_crypt.bits.rsapub2048_key_set = 1; - + } } else { WOLFSSL_MSG("Failed to generate key pair by TSIP"); return CRYPTOCB_UNAVAILABLE; } - + tsip_hw_unlock(); } @@ -184,7 +184,7 @@ WOLFSSL_LOCAL int wc_tsip_MakeRsaKey(int size, void* ctx) /* Perform Rsa verify by TSIP * Assumes to be called by Crypt Callback - * + * * in Buffer to hold plaintext * inLen Length of plaintext in bytes * out Buffer to hold generated signature @@ -193,7 +193,7 @@ WOLFSSL_LOCAL int wc_tsip_MakeRsaKey(int size, void* ctx) * ctx The callback context * return FSP_SUCCESS(0) on Success, otherwise negative value */ - + WOLFSSL_LOCAL int wc_tsip_RsaVerifyPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) { int ret = 0; @@ -201,13 +201,13 @@ WOLFSSL_LOCAL int wc_tsip_RsaVerifyPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) tsip_rsa_byte_data_t hashData, sigData; uint8_t tsip_hash_type; - - + + /* sanity check */ if (info == NULL || tuc == NULL){ return BAD_FUNC_ARG; } - + if (ret == 0) { if (tuc->sing_hash_type == md5_mac) tsip_hash_type = R_TSIP_RSA_HASH_MD5; @@ -218,7 +218,7 @@ WOLFSSL_LOCAL int wc_tsip_RsaVerifyPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) else ret = CRYPTOCB_UNAVAILABLE; } - + switch (tuc->wrappedKeyType) { case TSIP_KEY_TYPE_RSA1024: if (tuc->keyflgs_crypt.bits.rsapub1024_key_set != 1) @@ -226,7 +226,7 @@ WOLFSSL_LOCAL int wc_tsip_RsaVerifyPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) ret = tsipImportPublicKey(tuc, tuc->wrappedKeyType); WOLFSSL_MSG("tsip rsa private key 1024 not set"); - if (ret != 0) + if (ret != 0) ret = CRYPTOCB_UNAVAILABLE; } @@ -237,7 +237,7 @@ WOLFSSL_LOCAL int wc_tsip_RsaVerifyPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) ret = tsipImportPublicKey(tuc, tuc->wrappedKeyType); WOLFSSL_MSG("tsip rsa private key 1024 not set"); - if (ret != 0) + if (ret != 0) ret = CRYPTOCB_UNAVAILABLE; } break; @@ -294,7 +294,7 @@ WOLFSSL_LOCAL int wc_tsip_RsaVerifyPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) tsip_hw_unlock(); } } - + return ret; } #endif /* WOLFSSL_RENESAS_TSIP_CRYPTONLY */ diff --git a/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c b/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c index a1a02f3b45..38ddd7b3e1 100644 --- a/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c +++ b/wolfcrypt/src/port/Renesas/renesas_tsip_sha.c @@ -64,7 +64,7 @@ WOLFSSL_LOCAL int tsip_Tls13GetHmacMessages(struct WOLFSSL* ssl, byte* mac) ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) isTLS13 = 1; @@ -136,8 +136,8 @@ WOLFSSL_LOCAL int tsip_Tls13GetHmacMessages(struct WOLFSSL* ssl, byte* mac) -/* store handshake message for later hash or hmac operation. - * +/* store handshake message for later hash or hmac operation. + * */ WOLFSSL_LOCAL int tsip_StoreMessage(struct WOLFSSL* ssl, const byte* data, int sz) @@ -154,7 +154,7 @@ WOLFSSL_LOCAL int tsip_StoreMessage(struct WOLFSSL* ssl, const byte* data, ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) isTLS13 = 1; @@ -164,7 +164,7 @@ WOLFSSL_LOCAL int tsip_StoreMessage(struct WOLFSSL* ssl, const byte* data, ret = CRYPTOCB_UNAVAILABLE; } } - /* should work until handshake is done */ + /* should work until handshake is done */ if (ret == 0) { if (ssl->options.handShakeDone) { WOLFSSL_MSG("handshake is done."); @@ -195,12 +195,12 @@ WOLFSSL_LOCAL int tsip_StoreMessage(struct WOLFSSL* ssl, const byte* data, bag = &(tuc->messageBag); - if (bag->msgIdx +1 > MAX_MSGBAG_MESSAGES || + if (bag->msgIdx +1 > MAX_MSGBAG_MESSAGES || bag->buffIdx + sz > MSGBAG_SIZE) { WOLFSSL_MSG("Capacity over error in tsip_StoreMessage"); ret = MEMORY_E; } - + XMEMCPY(bag->buff + bag->buffIdx, data, sz); bag->msgTypes[bag->msgIdx++] = *data; /* store message type */ bag->buffIdx += sz; @@ -229,7 +229,7 @@ WOLFSSL_LOCAL int tsip_GetMessageSha256(struct WOLFSSL* ssl, byte* hash, ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) isTLS13 = 1; @@ -246,14 +246,14 @@ WOLFSSL_LOCAL int tsip_GetMessageSha256(struct WOLFSSL* ssl, byte* hash, } bag = &(tuc->messageBag); } - + if (ret == 0) { if ((ret = tsip_hw_lock()) == 0) { err = R_TSIP_Sha256Init(&handle); if (err == TSIP_SUCCESS) { - err = R_TSIP_Sha256Update(&handle, (uint8_t*)bag->buff, + err = R_TSIP_Sha256Update(&handle, (uint8_t*)bag->buff, bag->buffIdx); } if (err == TSIP_SUCCESS) { @@ -309,7 +309,7 @@ static int TSIPHashInit(wolfssl_TSIP_Hash* hash, void* heap, int devId, else { hash->heap = heap; } - + hash->len = 0; hash->used = 0; hash->msg = NULL; diff --git a/wolfcrypt/src/port/Renesas/renesas_tsip_util.c b/wolfcrypt/src/port/Renesas/renesas_tsip_util.c index 8c98ffb781..842ffb2bda 100644 --- a/wolfcrypt/src/port/Renesas/renesas_tsip_util.c +++ b/wolfcrypt/src/port/Renesas/renesas_tsip_util.c @@ -239,7 +239,7 @@ WOLFSSL_API int tsip_use_PrivateKey_buffer_crypt(TsipUserCtx *uc, /* Obsolete function. Use tsip_use_PrivateKey_buffer instead. * Set client encrypted private key data. * parameters: - * key Renesas Secure Flash Programmer generated key. + * key Renesas Secure Flash Programmer generated key. * keyType 0: RSA 2048bit, 1: RSA 4096bit, 2 ECC P256 * return 0 on success, others on failure. */ @@ -253,7 +253,7 @@ WOLFSSL_API int tsip_set_clientPrivateKeyEnc(const byte* encKey, int keyType) g_user_key_info.encrypted_user_private_key = (uint8_t*)encKey; g_user_key_info.encrypted_user_private_key_type = keyType; } - + WOLFSSL_LEAVE("tsip_set_clientPrivateKeyEnc", ret); return ret; } @@ -299,7 +299,7 @@ WOLFSSL_LOCAL int tsip_TlsCleanup(struct WOLFSSL* ssl) /* free stored messages */ tsipFlushMessages(ssl); - + return ret; } @@ -322,12 +322,12 @@ WOLFSSL_LOCAL int tsip_Tls13GenEccKeyPair(WOLFSSL* ssl, KeyShareEntry* kse) TsipUserCtx* tuc = NULL; WOLFSSL_ENTER("tsip_Tls13GenEccKeyPair"); - + if (ssl == NULL || kse == NULL) ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -383,7 +383,7 @@ WOLFSSL_LOCAL int tsip_Tls13GenEccKeyPair(WOLFSSL* ssl, KeyShareEntry* kse) ecckey = (ecc_key*)kse->key; ret = wc_ecc_set_curve(ecckey, kse->keyLen, curveId); } - + kse->pubKey[0] = ECC_POINT_UNCOMP; /* generate ecc key pair with TSIP */ @@ -428,9 +428,9 @@ WOLFSSL_LOCAL int tsip_Tls13GenEccKeyPair(WOLFSSL* ssl, KeyShareEntry* kse) #if defined(WOLFSSL_TLS13) /* generate shared secret(pre-master secret) * get peer's raw ECDHE public key from KeyShareEntry. - * The pre-master secret generated by TSIP is stored into + * The pre-master secret generated by TSIP is stored into * TsipUserCtx.sharedSecret13Idx as TSIP specific format. - * + * * return 0 on success, CRYPTOCB_UNAVAILABLE when tsip can not handle and is * expecting to fallback to S/W, other negative values on error. */ @@ -448,7 +448,7 @@ WOLFSSL_LOCAL int tsip_Tls13GenSharedSecret(struct WOLFSSL* ssl, ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -468,7 +468,7 @@ WOLFSSL_LOCAL int tsip_Tls13GenSharedSecret(struct WOLFSSL* ssl, if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -530,7 +530,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveEarlySecret(struct WOLFSSL* ssl) if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -539,7 +539,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveEarlySecret(struct WOLFSSL* ssl) tuc->EarlySecret_set = 1; } } - + WOLFSSL_LEAVE("tsip_Tls13DeriveEarlySecret", ret); return ret; } @@ -552,7 +552,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveEarlySecret(struct WOLFSSL* ssl) * get pre-master secret stored in TsipUserCtx.sharedSecret13Idx. * Derived handshake secret is stored into TsipUserCtx.handshakeSecret13Idx * as tsip specific format. - * + * * return 0 on success, CRYPTOCB_UNAVAILABLE when tsip can not handle and is * expecting to fallback to S/W, other negative values on error. */ @@ -568,7 +568,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveHandshakeSecret(struct WOLFSSL* ssl) ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -580,7 +580,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveHandshakeSecret(struct WOLFSSL* ssl) if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -597,7 +597,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveHandshakeSecret(struct WOLFSSL* ssl) if (ret == 0) { if ((ret = tsip_hw_lock()) == 0) { - + tuc->HandshakeSecret_set = 0; err = R_TSIP_Tls13GenerateHandshakeSecret( @@ -640,7 +640,7 @@ static int tsipTls13DeriveClientHandshakeKeys(struct WOLFSSL* ssl) ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -651,7 +651,7 @@ static int tsipTls13DeriveClientHandshakeKeys(struct WOLFSSL* ssl) if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -673,9 +673,9 @@ static int tsipTls13DeriveClientHandshakeKeys(struct WOLFSSL* ssl) if (ret == 0) { if ((ret = tsip_hw_lock()) == 0) { - + tuc->HandshakeClientTrafficKey_set = 0; - + err = R_TSIP_Tls13GenerateClientHandshakeTrafficKey( &(tuc->handle13), TSIP_TLS13_MODE_FULL_HANDSHAKE, @@ -687,7 +687,7 @@ static int tsipTls13DeriveClientHandshakeKeys(struct WOLFSSL* ssl) if (err != TSIP_SUCCESS) { WOLFSSL_MSG( "R_TSIP_Tls13GenerateClientHandshakeTrafficKey error"); - ret = WC_HW_E; + ret = WC_HW_E; } /* key derivation succeeded */ @@ -724,7 +724,7 @@ static int tsipTls13DeriveServerHandshakeKeys(struct WOLFSSL* ssl) ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -735,7 +735,7 @@ static int tsipTls13DeriveServerHandshakeKeys(struct WOLFSSL* ssl) if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -757,7 +757,7 @@ static int tsipTls13DeriveServerHandshakeKeys(struct WOLFSSL* ssl) if (ret == 0) { if ((ret = tsip_hw_lock()) == 0) { - + tuc->HandshakeServerTrafficKey_set = 0; err = R_TSIP_Tls13GenerateServerHandshakeTrafficKey( @@ -773,7 +773,7 @@ static int tsipTls13DeriveServerHandshakeKeys(struct WOLFSSL* ssl) "R_TSIP_Tls13GenerateServerHandshakeTrafficKey error"); ret = WC_HW_E; } - + /* key derivation succeeded */ if (ret == 0) { tuc->HandshakeServerTrafficKey_set = 1; @@ -808,7 +808,7 @@ static int tsipTls13DeriveTrafficKeys(struct WOLFSSL* ssl) ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -819,7 +819,7 @@ static int tsipTls13DeriveTrafficKeys(struct WOLFSSL* ssl) if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -841,7 +841,7 @@ static int tsipTls13DeriveTrafficKeys(struct WOLFSSL* ssl) if (ret == 0) { if ((ret = tsip_hw_lock()) == 0) { - + tuc->ServerTrafficSecret_set = 0; tuc->ClientTrafficSecret_set = 0; tuc->ServerWriteTrafficKey_set = 0; @@ -862,7 +862,7 @@ static int tsipTls13DeriveTrafficKeys(struct WOLFSSL* ssl) "R_TSIP_Tls13GenerateApplicationTrafficKey error"); ret = WC_HW_E; } - + /* key derivation succeeded */ if (ret == 0) { tuc->ServerTrafficSecret_set = 1; @@ -899,7 +899,7 @@ static int tsipTls13UpdateClientTrafficKeys(struct WOLFSSL* ssl) ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -910,7 +910,7 @@ static int tsipTls13UpdateClientTrafficKeys(struct WOLFSSL* ssl) if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -971,7 +971,7 @@ static int tsipTls13UpdateServerTrafficKeys(struct WOLFSSL* ssl) ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -982,7 +982,7 @@ static int tsipTls13UpdateServerTrafficKeys(struct WOLFSSL* ssl) if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -1042,7 +1042,7 @@ static int tsipTls13UpdateServerTrafficKeys(struct WOLFSSL* ssl) * side ENCRYPT_SIDE_ONLY: when only encryption secret needs to be derived. * DECRYPT_SIDE_ONLY: when only decryption secret needs to be derived. * ENCRYPT_AND_DECRYPT_SIDE: when both secret needs to be derived. - * + * * returns 0 on success, CRYPTOCB_UNAVAILABLE when tsip can not handle and is * expecting to fallback to S/W, other negative values on error. */ @@ -1142,7 +1142,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveMasterSecret(struct WOLFSSL* ssl) ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -1152,7 +1152,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveMasterSecret(struct WOLFSSL* ssl) } if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -1160,7 +1160,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveMasterSecret(struct WOLFSSL* ssl) } if (ret == 0) { /* make sure handshake secret and verify data has been set by TSIP */ - if (!tuc->HandshakeSecret_set || + if (!tuc->HandshakeSecret_set || !tuc->HandshakeVerifiedData_set) { WOLFSSL_MSG("TSIP wasn't involved in the key-exchange."); ret = CRYPTOCB_UNAVAILABLE; @@ -1168,7 +1168,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveMasterSecret(struct WOLFSSL* ssl) } if (ret == 0) { if ((ret = tsip_hw_lock()) == 0) { - + tuc->MasterSecret_set = 0; err = R_TSIP_Tls13GenerateMasterSecret( @@ -1183,7 +1183,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveMasterSecret(struct WOLFSSL* ssl) "R_TSIP_Tls13GenerateMasterSecret( error"); ret = WC_HW_E; } - + if (ret == 0) { tuc->MasterSecret_set = 1; } @@ -1206,7 +1206,7 @@ WOLFSSL_LOCAL int tsip_Tls13DeriveMasterSecret(struct WOLFSSL* ssl) /* verify handshake * ssl WOLFSSL object * hash buffer holding decrypted finished message content from server. - * + * */ static int tsipTls13VerifyHandshake(struct WOLFSSL* ssl, const byte* hash)/*finished message*/ @@ -1223,7 +1223,7 @@ static int tsipTls13VerifyHandshake(struct WOLFSSL* ssl, ret = BAD_FUNC_ARG; if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -1234,7 +1234,7 @@ static int tsipTls13VerifyHandshake(struct WOLFSSL* ssl, if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx hasn't been set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -1255,7 +1255,7 @@ static int tsipTls13VerifyHandshake(struct WOLFSSL* ssl, if (ret == 0) { if ((ret = tsip_hw_lock()) == 0) { - + tuc->HandshakeVerifiedData_set = 0; err = R_TSIP_Tls13ServerHandshakeVerification( @@ -1271,7 +1271,7 @@ static int tsipTls13VerifyHandshake(struct WOLFSSL* ssl, } else if (err != TSIP_SUCCESS) { WOLFSSL_MSG("R_TSIP_Tls13ServerHandshakeVerification error"); - ret = WC_HW_E; + ret = WC_HW_E; } if (ret == 0) { WOLFSSL_MSG("Verified handshake"); @@ -1294,9 +1294,9 @@ static int tsipTls13VerifyHandshake(struct WOLFSSL* ssl, #if defined(WOLFSSL_TLS13) /* handles finished message from server. - * verify hmac in the message. Also output verify data to + * verify hmac in the message. Also output verify data to * TsipUserCtx.verifyDataIdx, which is used for deriving master secret. - * + * * ssl WOLFSSL object * input the buffer holding decrypted finished message, type and padding * inOutIdx On entry, the index into the message content of Finished. @@ -1348,7 +1348,7 @@ WOLFSSL_LOCAL int tsip_Tls13HandleFinished( * inSz The size of the handshake message (including message header). * type The real content type being put after the message data. * hashOutput Whether to hash the unencrypted record data. - * returns the size of the record including header, CRYPTOCB_UNAVAILABLE + * returns the size of the record including header, CRYPTOCB_UNAVAILABLE * when tsip can not handle and is expecting to fallback to S/W, * other negative values on error. */ @@ -1365,7 +1365,7 @@ WOLFSSL_LOCAL int tsip_Tls13BuildMessage(struct WOLFSSL* ssl, int isTLS13 = 0; RecordLayerHeader* rl = NULL; (void)outSz; - + WOLFSSL_ENTER("tsip_Tls13BuildMessage"); if (ssl == NULL || output == NULL || input == NULL) { @@ -1373,7 +1373,7 @@ WOLFSSL_LOCAL int tsip_Tls13BuildMessage(struct WOLFSSL* ssl, } if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { isTLS13 = 1; } @@ -1421,7 +1421,7 @@ WOLFSSL_LOCAL int tsip_Tls13BuildMessage(struct WOLFSSL* ssl, /* The real record content type goes at the end of the data. */ output[RECORD_HEADER_SZ + inSz] = (byte)type; - ret = tsip_Tls13AesEncrypt(ssl, + ret = tsip_Tls13AesEncrypt(ssl, output + RECORD_HEADER_SZ, /* output */ output + RECORD_HEADER_SZ, /* plain message */ inSz + 1); /* plain data size(= inSz + 1 for type) */ @@ -1440,7 +1440,7 @@ WOLFSSL_LOCAL int tsip_Tls13BuildMessage(struct WOLFSSL* ssl, #if defined(WOLFSSL_TLS13) /* Send finished message to the server. - * + * * ssl WOLFSSL object * output buffer to output packet, including packet header and finished message * outSz buffer size of output @@ -1466,7 +1466,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendFinished( if (ssl == NULL || output == NULL || input == NULL || outSz == 0) { ret = BAD_FUNC_ARG; } - + if (ret == 0) { finishedSz = ssl->specs.hash_size; @@ -1485,7 +1485,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendFinished( output, outSz, input, headerSz + finishedSz, handshake, hashOut); - + if (recordSz > 0) { ssl->options.clientState = CLIENT_FINISHED_COMPLETE; ssl->options.handShakeState = HANDSHAKE_DONE; @@ -1515,7 +1515,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendFinished( * return 0 on success, CRYPTOCB_UNAVAILABLE when TSIP can not handle, * other negative values on error. */ -WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, +WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 totalSz) { @@ -1528,7 +1528,7 @@ WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, e_tsip_err_t err = TSIP_SUCCESS; TsipUserCtx* tuc = NULL; e_tsip_tls13_signature_scheme_type_t sig_scheme; - + WOLFSSL_ENTER("tsip_Tls13CertificateVerify"); @@ -1576,7 +1576,7 @@ WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, if (ret == 0) { /* get user context for TSIP */ - tuc = ssl->RenesasUserCtx; + tuc = ssl->RenesasUserCtx; if (tuc == NULL) { WOLFSSL_MSG("TsipUserCtx is not set to ssl."); ret = CRYPTOCB_UNAVAILABLE; @@ -1596,7 +1596,7 @@ WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, idx = 0; ForceZero(sigData, sizeof(tuc->sigDataCertVerify)); - XMEMSET(sigData, TSIP_SIGNING_DATA_PREFIX_BYTE, + XMEMSET(sigData, TSIP_SIGNING_DATA_PREFIX_BYTE, TSIP_SIGNING_DATA_PREFIX_SZ); idx += TSIP_SIGNING_DATA_PREFIX_SZ; @@ -1605,7 +1605,7 @@ WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, idx += TSIP_CERT_VFY_LABEL_SZ; ret = tsip_GetMessageSha256(ssl, &sigData[idx], &messageSz); } - + if (ret == 0) { if ((ret = tsip_hw_lock()) == 0) { @@ -1617,7 +1617,7 @@ WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, totalSz); if (err == TSIP_SUCCESS) { - + *inOutIdx += totalSz; *inOutIdx += ssl->keys.padSz; ssl->options.peerAuthGood = 1; @@ -1650,17 +1650,17 @@ WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, /* Send the TLS v1.3 CertificateVerify message. A part of the message is * processed by TSIP for acceleration. * - * Prior to this function call, the appropriate key-pair should be set via - * tsip_use_PrivateKey_buffer_TLS and tsip_use_PublicKey_buffer_TLS APIs. - * Those key pair can be generated by the tool named + * Prior to this function call, the appropriate key-pair should be set via + * tsip_use_PrivateKey_buffer_TLS and tsip_use_PublicKey_buffer_TLS APIs. + * Those key pair can be generated by the tool named * "Renesas secure flash programmer". * When RSA certificate is used, both public and private keys should be set. * The public key is used for self-verify the generated certificateVerify * message. When ECC certificate is used, the self-verify will be performed only * WOLFSSL_CHECK_SIG_FAULTS is defined. - * - * Returns 0 on success, CRYPTOCB_UNAVAILABLE when the required key is not - * provided or unsupported algo is specified and otherwise failure. + * + * Returns 0 on success, CRYPTOCB_UNAVAILABLE when the required key is not + * provided or unsupported algo is specified and otherwise failure. */ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) { @@ -1693,7 +1693,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) } if (ret == 0) { - if (ssl->version.major == SSLv3_MAJOR && + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) isTLS13 = 1; @@ -1702,7 +1702,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) ret = CRYPTOCB_UNAVAILABLE; } } - + if (ret == 0) { /* get user context for TSIP */ tuc = ssl->RenesasUserCtx; @@ -1712,10 +1712,10 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) } if (ret == 0) { - #if !defined(NO_RSA) + #if !defined(NO_RSA) if (ssl->options.haveRSA) isRsa = 1; - else + else #endif #ifdef HAVE_ECC if (ssl->options.haveECC) @@ -1746,7 +1746,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) } } - if (ret == 0) { + if (ret == 0) { /* get message hash */ ForceZero(hash, sizeof(hash)); ret = tsip_GetMessageSha256(ssl, hash, (int*)&hashSz); @@ -1777,7 +1777,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) TSIP_TLS13_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA256, hash, message + HANDSHAKE_HEADER_SZ, - &messageSz); + &messageSz); } else { err = R_TSIP_Tls13CertificateVerifyGenerate( @@ -1785,7 +1785,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) TSIP_TLS13_SIGNATURE_SCHEME_ECDSA_SECP256R1_SHA256, hash, message + HANDSHAKE_HEADER_SZ, - &messageSz); + &messageSz); } if (err != TSIP_SUCCESS) { WOLFSSL_MSG("failed to make certificate verify message"); @@ -1816,7 +1816,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) } } else { -#if defined(WOLFSSL_CHECK_SIG_FAULTS) +#if defined(WOLFSSL_CHECK_SIG_FAULTS) if (!tuc->ClientEccP256PubKey_set) { ret = NO_PRIVATE_KEY; } @@ -1829,7 +1829,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) idx = 0; ForceZero(sigData, sizeof(tuc->sigDataCertVerify)); - XMEMSET(sigData, TSIP_SIGNING_DATA_PREFIX_BYTE, + XMEMSET(sigData, TSIP_SIGNING_DATA_PREFIX_BYTE, TSIP_SIGNING_DATA_PREFIX_SZ); idx += TSIP_SIGNING_DATA_PREFIX_SZ; @@ -1842,9 +1842,9 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) if (ret == 0) { /* extract signature data from generated CertificateVerify message */ if (!isRsa) { -#if defined(WOLFSSL_CHECK_SIG_FAULTS) - idx = 4; - derSig = message + +#if defined(WOLFSSL_CHECK_SIG_FAULTS) + idx = 4; + derSig = message + HANDSHAKE_HEADER_SZ + HASH_SIG_SIZE + VERIFY_HEADER; if (derSig[idx] == 0x00) idx++; @@ -1907,8 +1907,8 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(WOLFSSL* ssl) ((HandShakeHeader*)message)->type = certificate_verify; c32to24(messageSz, ((HandShakeHeader*)message)->length); - - recordSz = tsip_Tls13BuildMessage(ssl, output, 0, message, + + recordSz = tsip_Tls13BuildMessage(ssl, output, 0, message, messageSz + HANDSHAKE_HEADER_SZ, handshake, 1); @@ -2114,8 +2114,8 @@ int wc_tsip_RsaVerify( * key buffer holding peer's public key (NOT used in this function) * keySz public key size((NOT used in this function)) * result address of the variable to output result - * ctx context - * return 0 on success, CRYPTOCB_UNAVAILABLE in case TSIP cannot handle + * ctx context + * return 0 on success, CRYPTOCB_UNAVAILABLE in case TSIP cannot handle */ int wc_tsip_EccVerify( WOLFSSL* ssl, @@ -2138,8 +2138,8 @@ int wc_tsip_EccVerify( return CRYPTOCB_UNAVAILABLE; } - /* in TLS1.3 */ - if (ssl->version.major == SSLv3_MAJOR && + /* in TLS1.3 */ + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { WOLFSSL_LEAVE("wc_tsip_EccVerify", CRYPTOCB_UNAVAILABLE); return CRYPTOCB_UNAVAILABLE; @@ -2261,7 +2261,7 @@ WOLFSSL_API void tsip_set_callbacks(WOLFSSL_CTX* ctx) #endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ wolfSSL_CTX_SetEccSharedSecretCb(ctx, NULL); /* Set ssl-> options.sendVerify to SEND_CERT by the following two - * registrations. This will allow the client certificate to be sent to + * registrations. This will allow the client certificate to be sent to * the server even if the private key is empty. The two callbacks do * virtually nothing. */ @@ -2307,7 +2307,7 @@ WOLFSSL_API int tsip_set_callback_ctx(WOLFSSL* ssl, void* user_ctx) wolfSSL_SetRsaSignCtx(ssl, user_ctx); wolfSSL_SetGenPreMasterCtx(ssl, user_ctx); wolfSSL_SetEccSharedSecretCtx(ssl, NULL); -#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) wolfSSL_SetVerifyMacCtx(ssl, user_ctx); #endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ /* set up crypt callback */ @@ -2367,7 +2367,7 @@ static int tsipImportPrivateKey(TsipUserCtx* tuc, int keyType) if (encPrivKey == NULL || provisioning_key == NULL || iv == NULL) { WOLFSSL_MSG("Missing some key materials used for import" ); return CRYPTOCB_UNAVAILABLE; - } + } if (ret == 0) { if (keyType != tuc->wrappedKeyType) { @@ -2381,7 +2381,7 @@ static int tsipImportPrivateKey(TsipUserCtx* tuc, int keyType) #if !defined(NO_RSA) case TSIP_KEY_TYPE_RSA2048: - + tuc->ClientRsa2048PrivKey_set = 0; err = R_TSIP_GenerateRsa2048PrivateKeyIndex( provisioning_key, iv, (uint8_t*)encPrivKey, @@ -2396,7 +2396,7 @@ static int tsipImportPrivateKey(TsipUserCtx* tuc, int keyType) #endif case TSIP_KEY_TYPE_RSA4096: - /* not supported as of TSIPv1.15 */ + /* not supported as of TSIPv1.15 */ ret = CRYPTOCB_UNAVAILABLE; break; @@ -2458,7 +2458,7 @@ WOLFSSL_LOCAL int tsipImportPublicKey(TsipUserCtx* tuc, int keyType) if (encPubKey == NULL || provisioning_key == NULL || iv == NULL) { WOLFSSL_MSG("Missing some key materials used for import" ); return CRYPTOCB_UNAVAILABLE; - } + } if (ret == 0) { if (keyType != tuc->wrappedKeyType) { @@ -2469,7 +2469,7 @@ WOLFSSL_LOCAL int tsipImportPublicKey(TsipUserCtx* tuc, int keyType) if ((ret = tsip_hw_lock()) == 0) { switch(keyType) { - + #if !defined(NO_RSA) case TSIP_KEY_TYPE_RSA2048: #if defined(WOLFSSL_RENESAS_TSIP_TLS) @@ -2479,10 +2479,10 @@ WOLFSSL_LOCAL int tsipImportPublicKey(TsipUserCtx* tuc, int keyType) XFREE(tuc->rsa2048pub_keyIdx, NULL, DYNAMIC_TYPE_RSA_BUFFER); } - + tuc->rsa2048pub_keyIdx = (tsip_rsa2048_public_key_index_t*)XMALLOC( - sizeof(tsip_rsa2048_public_key_index_t), NULL, + sizeof(tsip_rsa2048_public_key_index_t), NULL, DYNAMIC_TYPE_RSA_BUFFER); if (tuc->rsa2048pub_keyIdx == NULL) { return MEMORY_E; @@ -2508,14 +2508,14 @@ WOLFSSL_LOCAL int tsipImportPublicKey(TsipUserCtx* tuc, int keyType) } break; #endif - + #if !defined(NO_RSA) case TSIP_KEY_TYPE_RSA4096: - /* not supported as of TSIPv1.15 */ + /* not supported as of TSIPv1.15 */ ret = CRYPTOCB_UNAVAILABLE; break; #endif - + #if defined(HAVE_ECC) && \ defined(WOLFSSL_RENESAS_TSIP_TLS) case TSIP_KEY_TYPE_ECDSAP256: @@ -3101,7 +3101,7 @@ int wc_tsip_generateVerifyData( WOLFSSL_LEAVE("tsip_generateVerifyData", BAD_FUNC_ARG); return BAD_FUNC_ARG; } - if (XSTRNCMP((const char*)side, (const char*)kTlsServerFinStr, + if (XSTRNCMP((const char*)side, (const char*)kTlsServerFinStr, FINISHED_LABEL_SZ) == 0) { l_side = R_TSIP_TLS_GENERATE_SERVER_VERIFY; } @@ -3667,14 +3667,14 @@ WOLFSSL_LOCAL int tsip_SignRsaPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) WOLFSSL_ENTER("tsip_SignRsaPkcs"); - if (info == NULL || tuc == NULL + if (info == NULL || tuc == NULL #ifndef WOLFSSL_RENESAS_TSIP_CRYPTONLY || tuc->ssl == NULL #endif ) { ret = BAD_FUNC_ARG; } - + #ifdef WOLFSSL_RENESAS_TSIP_TLS if (ret == 0) { ssl = tuc->ssl; @@ -3690,7 +3690,7 @@ WOLFSSL_LOCAL int tsip_SignRsaPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) ret = tsipImportPrivateKey(tuc, tuc->wrappedKeyType); } - + if (ret == 0) { if (ssl->options.hashAlgo == md5_mac) tsip_hash_type = R_TSIP_RSA_HASH_MD5; @@ -3703,7 +3703,7 @@ WOLFSSL_LOCAL int tsip_SignRsaPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) } #else (void)ssl; - + if (ret == 0) { if (tuc->sing_hash_type == md5_mac) tsip_hash_type = R_TSIP_RSA_HASH_MD5; @@ -3714,7 +3714,7 @@ WOLFSSL_LOCAL int tsip_SignRsaPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) else ret = CRYPTOCB_UNAVAILABLE; } - + switch (tuc->wrappedKeyType) { case TSIP_KEY_TYPE_RSA1024: if (tuc->keyflgs_crypt.bits.rsapri1024_key_set != 1) @@ -3735,9 +3735,9 @@ WOLFSSL_LOCAL int tsip_SignRsaPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) ret = CRYPTOCB_UNAVAILABLE; break; } - + #endif - + if (ret == 0) { #ifdef WOLFSSL_RENESAS_TSIP_TLS hashData.pdata = (uint8_t*)ssl->buffers.digest.buffer; @@ -3762,7 +3762,7 @@ WOLFSSL_LOCAL int tsip_SignRsaPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) tsip_hash_type); if (err != TSIP_SUCCESS) { - ret = WC_HW_E; + ret = WC_HW_E; } break; #endif @@ -3779,7 +3779,7 @@ WOLFSSL_LOCAL int tsip_SignRsaPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) tsip_hash_type); if (err != TSIP_SUCCESS) { - ret = WC_HW_E; + ret = WC_HW_E; } break; @@ -3807,7 +3807,7 @@ WOLFSSL_LOCAL int tsip_SignRsaPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc) #if !defined(NO_RSA) && defined(WOLFSSL_RENESAS_TSIP_TLS) WOLFSSL_LOCAL int tsip_VerifyRsaPkcsCb( - WOLFSSL* ssl, + WOLFSSL* ssl, unsigned char* sig, unsigned int sigSz, unsigned char** out, const unsigned char* keyDer, unsigned int keySz, @@ -3842,7 +3842,7 @@ WOLFSSL_LOCAL int tsip_VerifyRsaPkcsCb( /* import public key_index from wrapped key */ ret = tsipImportPublicKey(tuc, tuc->wrappedKeyType); } - + if (ret == 0) { if (ssl->options.hashAlgo == md5_mac) tsip_hash_type = R_TSIP_RSA_HASH_MD5; @@ -3852,7 +3852,7 @@ WOLFSSL_LOCAL int tsip_VerifyRsaPkcsCb( tsip_hash_type = R_TSIP_RSA_HASH_SHA256; else { ret = CRYPTOCB_UNAVAILABLE; - } + } } if (ret == 0) { @@ -3863,7 +3863,7 @@ WOLFSSL_LOCAL int tsip_VerifyRsaPkcsCb( if ((ret = tsip_hw_lock()) == 0) { switch (tuc->wrappedKeyType) { - + case TSIP_KEY_TYPE_RSA2048: sigData.data_length = 256; err = R_TSIP_RsassaPkcs2048SignatureVerification( @@ -3904,7 +3904,7 @@ WOLFSSL_LOCAL int tsip_VerifyRsaPkcsCb( #if defined(HAVE_ECC) && defined(WOLFSSL_RENESAS_TSIP_TLS) /* Perform signing with the client's ECC private key on hash value of messages - * exchanged with server. + * exchanged with server. * * parameters * info->pk.eccsign.in : the buffer holding hash value of messages @@ -3951,33 +3951,33 @@ WOLFSSL_LOCAL int tsip_SignEcdsa(wc_CryptoInfo* info, TsipUserCtx* tuc) /* import private key_index from wrapped key */ ret = tsipImportPrivateKey(tuc, tuc->wrappedKeyType); } - + if (ret == 0) { hashData.pdata = (uint8_t*)info->pk.eccsign.in; hashData.data_type = 1; sigData.pdata = (uint8_t*)info->pk.eccsign.out; sigData.data_length = 0; /* signature size will be returned here */ - if ((ret = tsip_hw_lock()) == 0) { + if ((ret = tsip_hw_lock()) == 0) { switch (tuc->wrappedKeyType) { #if defined(HAVE_ECC) case TSIP_KEY_TYPE_ECDSAP256: offsetForWork = R_TSIP_ECDSA_DATA_BYTE_SIZE + 32; - if (*(info->pk.eccsign.outlen) < + if (*(info->pk.eccsign.outlen) < R_TSIP_ECDSA_DATA_BYTE_SIZE + offsetForWork) { ret = BUFFER_E; break; } - sigData.pdata = (uint8_t*)info->pk.eccsign.out + + sigData.pdata = (uint8_t*)info->pk.eccsign.out + offsetForWork; err = R_TSIP_EcdsaP256SignatureGenerate( &hashData, &sigData, &tuc->EcdsaP256PrivateKeyIdx); if (err != TSIP_SUCCESS) { ret = WC_HW_E; - break; + break; } out = info->pk.eccsign.out; @@ -3991,7 +3991,7 @@ WOLFSSL_LOCAL int tsip_SignEcdsa(wc_CryptoInfo* info, TsipUserCtx* tuc) /* encode ASN sequence */ out[idx++] = ASN_SEQUENCE | ASN_CONSTRUCTED; out[idx++] = sz; - + /* copy r part */ out[idx++] = ASN_INTEGER; out[idx++] = rSz; @@ -4006,7 +4006,7 @@ WOLFSSL_LOCAL int tsip_SignEcdsa(wc_CryptoInfo* info, TsipUserCtx* tuc) if (sSz > R_TSIP_ECDSA_DATA_BYTE_SIZE / 2) out[idx++] = 0x00; XMEMCPY(&out[idx], sig, R_TSIP_ECDSA_DATA_BYTE_SIZE / 2); - + /* out size */ *(info->pk.eccsign.outlen) = ASN_TAG_SZ + 1 + sz; break; @@ -4047,20 +4047,22 @@ WOLFSSL_LOCAL int tsip_SignEcdsa(wc_CryptoInfo* info, TsipUserCtx* tuc) #ifdef WOLFSSL_RENESAS_TSIP_CRYPT_DEBUG -/* err - * e_tsip_err +#if 0 + /* this is here for documentation purposes. */ + enum e_tsip_err { TSIP_SUCCESS = 0, - TSIP_ERR_SELF_CHECK1, // Self-check 1 fail or TSIP function internal err. - TSIP_ERR_RESOURCE_CONFLICT, // A resource conflict occurred. - TSIP_ERR_SELF_CHECK2, // Self-check 2 fail. - TSIP_ERR_KEY_SET, // setting the invalid key. - TSIP_ERR_AUTHENTICATION, // Authentication failed. - TSIP_ERR_CALLBACK_UNREGIST, // Callback function is not registered. - TSIP_ERR_PARAMETER, // Illegal Input data. - TSIP_ERR_PROHIBIT_FUNCTION, // An invalid function call occurred. - * TSIP_RESUME_FIRMWARE_GENERATE_MAC, - // There is a continuation of R_TSIP_GenerateFirmwareMAC. -*/ + TSIP_ERR_SELF_CHECK1, /* Self-check 1 fail or TSIP function internal err. */ + TSIP_ERR_RESOURCE_CONFLICT, /* A resource conflict occurred. */ + TSIP_ERR_SELF_CHECK2, /* Self-check 2 fail. */ + TSIP_ERR_KEY_SET, /* setting the invalid key. */ + TSIP_ERR_AUTHENTICATION, /* Authentication failed. */ + TSIP_ERR_CALLBACK_UNREGIST, /* Callback function is not registered. */ + TSIP_ERR_PARAMETER, /* Illegal Input data. */ + TSIP_ERR_PROHIBIT_FUNCTION, /* An invalid function call occurred. */ + TSIP_RESUME_FIRMWARE_GENERATE_MAC + /* There is a continuation of R_TSIP_GenerateFirmwareMAC. */ + }; +#endif static void hexdump(const uint8_t* in, uint32_t len) { diff --git a/wolfcrypt/src/port/af_alg/wc_afalg.c b/wolfcrypt/src/port/af_alg/wc_afalg.c index 37ced88c81..b6671f7b85 100644 --- a/wolfcrypt/src/port/af_alg/wc_afalg.c +++ b/wolfcrypt/src/port/af_alg/wc_afalg.c @@ -40,7 +40,7 @@ void wc_Afalg_SockAddr(struct sockaddr_alg* in, const char* type, const char* na int nameSz = (int)XSTRLEN(name) + 1; /* +1 for null terminator */ if (typeSz > (int)sizeof(in->salg_type) || - nameSz > (int)sizeof(in->salg_name)) { + nameSz > (int)sizeof(in->salg_name)) { WOLFSSL_MSG("type or name was too large"); return; } diff --git a/wolfcrypt/src/port/arm/armv8-aes.c b/wolfcrypt/src/port/arm/armv8-aes.c index 871d6b38af..1a97996563 100644 --- a/wolfcrypt/src/port/arm/armv8-aes.c +++ b/wolfcrypt/src/port/arm/armv8-aes.c @@ -35,14 +35,29 @@ #if !defined(NO_AES) && defined(WOLFSSL_ARMASM) -#if defined(HAVE_FIPS) && !defined(FIPS_NO_WRAPPERS) -#define FIPS_NO_WRAPPERS +#if FIPS_VERSION3_LT(6,0,0) && defined(HAVE_FIPS) + #undef HAVE_FIPS +#else + #if defined(HAVE_FIPS) && FIPS_VERSION3_GE(6,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + #endif #endif -#ifndef WOLFSSL_ARMASM_NO_HW_CRYPTO - #include #include + +#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 + +#ifndef WOLFSSL_ARMASM_NO_HW_CRYPTO + #ifdef NO_INLINE #include #else @@ -16471,8 +16486,6 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, #else /* !WOLFSSL_ARMASM_NO_HW_CRYPTO */ -#include -#include #ifdef NO_INLINE #include #else diff --git a/wolfcrypt/src/port/arm/armv8-sha256.c b/wolfcrypt/src/port/arm/armv8-sha256.c index 37380a3de3..5555aa8e2a 100644 --- a/wolfcrypt/src/port/arm/armv8-sha256.c +++ b/wolfcrypt/src/port/arm/armv8-sha256.c @@ -29,11 +29,24 @@ #ifdef WOLFSSL_ARMASM #if !defined(NO_SHA256) || defined(WOLFSSL_SHA224) -#ifdef HAVE_FIPS -#undef HAVE_FIPS +#if FIPS_VERSION3_LT(6,0,0) && defined(HAVE_FIPS) + #undef HAVE_FIPS +#else + #if defined(HAVE_FIPS) && FIPS_VERSION3_GE(6,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + #endif #endif #include +#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 #include #include diff --git a/wolfcrypt/src/port/arm/armv8-sha512.c b/wolfcrypt/src/port/arm/armv8-sha512.c index 45806249a8..da82c42fe9 100644 --- a/wolfcrypt/src/port/arm/armv8-sha512.c +++ b/wolfcrypt/src/port/arm/armv8-sha512.c @@ -28,11 +28,25 @@ #ifdef WOLFSSL_ARMASM #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) -#ifdef HAVE_FIPS -#undef HAVE_FIPS +#if FIPS_VERSION3_LT(6,0,0) && defined(HAVE_FIPS) + #undef HAVE_FIPS +#else + #if defined(HAVE_FIPS) && FIPS_VERSION3_GE(6,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + #endif #endif + #include +#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 #include #include diff --git a/wolfcrypt/src/port/atmel/atmel.c b/wolfcrypt/src/port/atmel/atmel.c index 9a404d8b3f..b3c6b7906c 100644 --- a/wolfcrypt/src/port/atmel/atmel.c +++ b/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/wolfcrypt/src/port/autosar/crypto.c b/wolfcrypt/src/port/autosar/crypto.c index e124b3ca5b..f7812f190c 100644 --- a/wolfcrypt/src/port/autosar/crypto.c +++ b/wolfcrypt/src/port/autosar/crypto.c @@ -431,7 +431,7 @@ Std_ReturnType Crypto_ProcessJob(uint32 objectId, Crypto_JobType* job) break; default: - WOLFSSL_MSG("Unsuported Crypto service"); + WOLFSSL_MSG("Unsupported Crypto service"); ret = E_NOT_OK; break; } diff --git a/wolfcrypt/src/port/caam/caam_driver.c b/wolfcrypt/src/port/caam/caam_driver.c index 4698d7a520..e0007c9cb7 100644 --- a/wolfcrypt/src/port/caam/caam_driver.c +++ b/wolfcrypt/src/port/caam/caam_driver.c @@ -129,7 +129,7 @@ static Error caamDebugDesc(struct DescStruct* desc) } - //D0JQCR_LS + /* D0JQCR_LS */ printf("Next command to be executed = 0x%08X\n", CAAM_READ(0x8804)); printf("Desc = 0x%08X\n", desc->caam->ring.Desc); diff --git a/wolfcrypt/src/port/caam/caam_qnx.c b/wolfcrypt/src/port/caam/caam_qnx.c index d6e94e8d38..0c2525743a 100644 --- a/wolfcrypt/src/port/caam/caam_qnx.c +++ b/wolfcrypt/src/port/caam/caam_qnx.c @@ -1641,8 +1641,9 @@ int io_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb) #if 0 static int getSupported(char* in) { - //printf("CAAM Status [0x%8.8x] = 0x%8.8x\n", - // CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS)); + /* printf("CAAM Status [0x%8.8x] = 0x%8.8x\n", + * CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS)); + */ printf("CAAM Version MS Register [0x%8.8x] = 0x%8.8x\n", CAAM_VERSION_MS, CAAM_READ(CAAM_VERSION_MS)); printf("CAAM Version LS Register [0x%8.8x] = 0x%8.8x\n", diff --git a/wolfcrypt/src/port/caam/wolfcaam_hash.c b/wolfcrypt/src/port/caam/wolfcaam_hash.c index d3155468f0..f64a29d9ef 100644 --- a/wolfcrypt/src/port/caam/wolfcaam_hash.c +++ b/wolfcrypt/src/port/caam/wolfcaam_hash.c @@ -26,7 +26,7 @@ #include #if defined(WOLFSSL_CAAM) && defined(WOLFSSL_CAAM_HASH) \ - && !defined(WOLFSSL_IMXRT1170_CAAM) + && !defined(WOLFSSL_IMXRT1170_CAAM) #include #include diff --git a/wolfcrypt/src/port/caam/wolfcaam_init.c b/wolfcrypt/src/port/caam/wolfcaam_init.c index d6e93cf5a2..cf9a63d77e 100644 --- a/wolfcrypt/src/port/caam/wolfcaam_init.c +++ b/wolfcrypt/src/port/caam/wolfcaam_init.c @@ -694,7 +694,7 @@ int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz) } #endif /* WOLFSSL_CAAM_BLOB */ -/* outSz gets set to key size plus 16 for mac and padding +/* outSz gets set to key size plus 16 for mac and padding * return 0 on success */ int wc_caamCoverKey(byte* in, word32 inSz, byte* out, word32* outSz, int flag) diff --git a/wolfcrypt/src/port/cuda/README.md b/wolfcrypt/src/port/cuda/README.md new file mode 100644 index 0000000000..e508b3d945 --- /dev/null +++ b/wolfcrypt/src/port/cuda/README.md @@ -0,0 +1,9 @@ +You will need to have the CUDA libraries and toolchains installed to be able to use this. For the simplest +setup, I used the 'nvidia/cuda:12.3.2-devel-ubuntu22.04' container with the '--gpus=all' flag. Note that +Docker must be set up to allow passing through the CUDA instructions to the host. The container only needs +'automake' and 'libtool' installed: `apt update && apt install -y automake libtool`. + +This code was tested with the following: + ./configure --enable-all --disable-shared --disable-crl-monitor --enable-cuda CC=nvcc && make check + +There are still things that can be done to optimize, but the basic functionality is there. diff --git a/wolfcrypt/src/port/cuda/aes-cuda.cu b/wolfcrypt/src/port/cuda/aes-cuda.cu new file mode 100644 index 0000000000..0fec5d35c4 --- /dev/null +++ b/wolfcrypt/src/port/cuda/aes-cuda.cu @@ -0,0 +1,1096 @@ +/* aes.cu + * + * 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 + */ + +/* + +DESCRIPTION +This library provides the interfaces to the Advanced Encryption Standard (AES) +for encrypting and decrypting data. AES is the standard known for a symmetric +block cipher mechanism that uses n-bit binary string parameter key with 128-bits, +192-bits, and 256-bits of key sizes. + +*/ +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include + +#include + +#ifdef WOLFSSL_AESNI +#include +#include +#include +#endif /* WOLFSSL_AESNI */ + +#include + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +#ifdef WOLFSSL_SECO_CAAM +#include +#endif + +#ifdef WOLFSSL_IMXRT_DCP + #include +#endif +#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_CRYPT) + #include +#endif + +#if defined(WOLFSSL_AES_SIV) + #include +#endif /* WOLFSSL_AES_SIV */ + +#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) + #include +#endif + + +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #define WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MAX +/* #include */ +#endif +/* This routine performs a left circular arithmetic shift of by value. */ + +extern "C" { + +#if !defined(WOLFSSL_TI_CRYPT) + +#define rotlFixed(x, y) ( (x << y) | (x >> (sizeof(x) * 8 - y)) ) + +/* This routine performs a right circular arithmetic shift of by value. */ +#define rotrFixed(x, y) ( (x >> y) | (x << (sizeof(x) * 8 - y)) ) + +#ifdef WC_RC2 + +/* This routine performs a left circular arithmetic shift of by value */ +static WC_INLINE word16 rotlFixed16(word16 x, word16 y) +{ + return (x << y) | (x >> (sizeof(x) * 8 - y)); +} + + +/* This routine performs a right circular arithmetic shift of by value */ +static WC_INLINE word16 rotrFixed16(word16 x, word16 y) +{ + return (x >> y) | (x << (sizeof(x) * 8 - y)); +} + +#endif /* WC_RC2 */ + +/* This routine performs a byte swap of 32-bit word value. */ +#if defined(__CCRX__) && !defined(NO_INLINE) /* shortest version for CC-RX */ + #define ByteReverseWord32(value, outRef) ( *outRef = _builtin_revl(value) ) +#else +__device__ +static WC_INLINE word32 ByteReverseWord32(word32 value) +{ +#ifdef PPC_INTRINSICS + /* PPC: load reverse indexed instruction */ + return (word32)__lwbrx(&value,0); +#elif defined(__ICCARM__) + return (word32)__REV(value); +#elif defined(KEIL_INTRINSICS) + return (word32)__rev(value); +#elif defined(__CCRX__) + return (word32)_builtin_revl(value); +#elif defined(WOLF_ALLOW_BUILTIN) && \ + defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3) + return (word32)__builtin_bswap32(value); +#elif defined(WOLFSSL_BYTESWAP32_ASM) && defined(__GNUC__) && \ + defined(__aarch64__) + __asm__ volatile ( + "REV32 %0, %0 \n" + : "+r" (value) + : + ); + return value; +#elif defined(WOLFSSL_BYTESWAP32_ASM) && defined(__GNUC__) && \ + (defined(__thumb__) || defined(__arm__)) + __asm__ volatile ( + "REV %0, %0 \n" + : "+r" (value) + : + ); + return value; +#elif defined(FAST_ROTATE) + /* 5 instructions with rotate instruction, 9 without */ + return (rotrFixed(value, 8U) & 0xff00ff00) | + (rotlFixed(value, 8U) & 0x00ff00ff); +#else + /* 6 instructions with rotate instruction, 8 without */ + value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); + return rotlFixed(value, 16U); +#endif +} +#endif /* ! (__CCRX__ && !NO_INLINE) */ + +#if defined(STM32_CRYPTO) +#elif defined(HAVE_COLDFIRE_SEC) +#elif defined(FREESCALE_LTC) +#elif defined(FREESCALE_MMCAU) +#elif defined(WOLFSSL_PIC32MZ_CRYPT) +#elif defined(WOLFSSL_NRF51_AES) +#elif defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_AES) +#elif defined(WOLFSSL_AESNI) +#elif (defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) \ + && !defined(WOLFSSL_QNX_CAAM)) || \ + ((defined(WOLFSSL_AFALG) || defined(WOLFSSL_DEVCRYPTO_AES)) && \ + defined(HAVE_AESCCM)) +#elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypto/devcrypto_aes.c */ + +#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES) +#elif defined(WOLFSSL_KCAPI_AES) +#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) +/* implemented in wolfcrypt/src/port/psa/psa_aes.c */ + +#else + + /* using wolfCrypt software implementation */ + #define NEED_AES_TABLES +#endif + +#if !defined(NO_AES) && !defined(WOLFSSL_TI_CRYPT) && !defined(WOLFSSL_ARMASM) && \ + defined(NEED_AES_TABLES) && (defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)) && \ + defined(HAVE_CUDA) + +#define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y)))) + +#ifndef WC_CACHE_LINE_SZ + #if defined(__x86_64__) || defined(_M_X64) || \ + (defined(__ILP32__) && (__ILP32__ >= 1)) + #define WC_CACHE_LINE_SZ 64 + #else + /* default cache line size */ + #define WC_CACHE_LINE_SZ 32 + #endif +#endif + +#if WC_CACHE_LINE_SZ == 128 + #define WC_CACHE_LINE_BITS 5 + #define WC_CACHE_LINE_MASK_HI 0xe0 + #define WC_CACHE_LINE_MASK_LO 0x1f + #define WC_CACHE_LINE_ADD 0x20 +#elif WC_CACHE_LINE_SZ == 64 + #define WC_CACHE_LINE_BITS 4 + #define WC_CACHE_LINE_MASK_HI 0xf0 + #define WC_CACHE_LINE_MASK_LO 0x0f + #define WC_CACHE_LINE_ADD 0x10 +#elif WC_CACHE_LINE_SZ == 32 + #define WC_CACHE_LINE_BITS 3 + #define WC_CACHE_LINE_MASK_HI 0xf8 + #define WC_CACHE_LINE_MASK_LO 0x07 + #define WC_CACHE_LINE_ADD 0x08 +#elif WC_CACHE_LINE_SZ == 16 + #define WC_CACHE_LINE_BITS 2 + #define WC_CACHE_LINE_MASK_HI 0xfc + #define WC_CACHE_LINE_MASK_LO 0x03 + #define WC_CACHE_LINE_ADD 0x04 +#else + #error Cache line size not supported +#endif + +#ifndef WOLFSSL_AES_SMALL_TABLES +__device__ +const FLASH_QUALIFIER word32 Te_CUDA[4][256] = { +{ + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}, +{ + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}, +{ + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}, +{ + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +} +}; + + +__device__ +static word32 GetTable(const word32* t, byte o) +{ + word32 e = 0; +#if WC_CACHE_LINE_SZ == 64 + byte hi = o & 0xf0; + byte lo = o & 0x0f; + + e = t[lo + 0x00] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0x10] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0x20] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0x30] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0x40] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0x50] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0x60] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0x70] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0x80] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0x90] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0xa0] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0xb0] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0xc0] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0xd0] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0xe0] & ((word32)0 - (((word32)hi - 0x01) >> 31)); hi -= 0x10; + e |= t[lo + 0xf0] & ((word32)0 - (((word32)hi - 0x01) >> 31)); +#else + int i; + byte hi = o & WC_CACHE_LINE_MASK_HI; + byte lo = o & WC_CACHE_LINE_MASK_LO; + + for (i = 0; i < 256; i += (1 << WC_CACHE_LINE_BITS)) { + e |= t[lo + i] & ((word32)0 - (((word32)hi - 0x01) >> 31)); + hi -= WC_CACHE_LINE_ADD; + } +#endif + return e; +} + +__device__ +static void GetTable_Multi(const word32* t, word32* t0, byte o0, + word32* t1, byte o1, word32* t2, byte o2, word32* t3, byte o3) +{ + word32 e0 = 0; + word32 e1 = 0; + word32 e2 = 0; + word32 e3 = 0; + byte hi0 = o0 & WC_CACHE_LINE_MASK_HI; + byte lo0 = o0 & WC_CACHE_LINE_MASK_LO; + byte hi1 = o1 & WC_CACHE_LINE_MASK_HI; + byte lo1 = o1 & WC_CACHE_LINE_MASK_LO; + byte hi2 = o2 & WC_CACHE_LINE_MASK_HI; + byte lo2 = o2 & WC_CACHE_LINE_MASK_LO; + byte hi3 = o3 & WC_CACHE_LINE_MASK_HI; + byte lo3 = o3 & WC_CACHE_LINE_MASK_LO; + int i; + + for (i = 0; i < 256; i += (1 << WC_CACHE_LINE_BITS)) { + e0 |= t[lo0 + i] & ((word32)0 - (((word32)hi0 - 0x01) >> 31)); + hi0 -= WC_CACHE_LINE_ADD; + e1 |= t[lo1 + i] & ((word32)0 - (((word32)hi1 - 0x01) >> 31)); + hi1 -= WC_CACHE_LINE_ADD; + e2 |= t[lo2 + i] & ((word32)0 - (((word32)hi2 - 0x01) >> 31)); + hi2 -= WC_CACHE_LINE_ADD; + e3 |= t[lo3 + i] & ((word32)0 - (((word32)hi3 - 0x01) >> 31)); + hi3 -= WC_CACHE_LINE_ADD; + } + *t0 = e0; + *t1 = e1; + *t2 = e2; + *t3 = e3; +} + +/* load 4 Te Tables into cache by cache line stride */ +__device__ +static WARN_UNUSED_RESULT WC_INLINE word32 PreFetchTe(void) +{ +#ifndef WOLFSSL_AES_TOUCH_LINES + word32 x = 0; + int i,j; + + for (i = 0; i < 4; i++) { + /* 256 elements, each one is 4 bytes */ + for (j = 0; j < 256; j += WC_CACHE_LINE_SZ/4) { + x &= Te_CUDA[i][j]; + } + } + return x; +#else + return 0; +#endif +} +#else +__device__ static const byte Tsbox[256] = { + 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, + 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U, + 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, + 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U, + 0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, + 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U, + 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, + 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U, + 0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, + 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U, + 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, + 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU, + 0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, + 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U, + 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, + 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U, + 0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, + 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U, + 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, + 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU, + 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, + 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U, + 0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, + 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U, + 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, + 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU, + 0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, + 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU, + 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, + 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU, + 0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, + 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U +}; + +#define AES_XTIME(x) ((byte)((byte)((x) << 1) ^ ((0 - ((x) >> 7)) & 0x1b))) + +#define col_mul(t, i2, i3, ia, ib) \ + ( GETBYTE(t, ia) ^ GETBYTE(t, ib) ^ GETBYTE(t, i3) ^ AES_XTIME(GETBYTE(t, i2) ^ GETBYTE(t, i3)) ) + +#define GetTable(t, o) t[o] +#define GetTable8(t, o) t[o] +#define GetTable_Multi(t, t0, o0, t1, o1, t2, o2, t3, o3) \ + *(t0) = (t)[o0]; *(t1) = (t)[o1]; *(t2) = (t)[o2]; *(t3) = (t)[o3] +#define XorTable_Multi(t, t0, o0, t1, o1, t2, o2, t3, o3) \ + *(t0) ^= (t)[o0]; *(t1) ^= (t)[o1]; *(t2) ^= (t)[o2]; *(t3) ^= (t)[o3] +#define GetTable8_4(t, o0, o1, o2, o3) \ + (((word32)(t)[o0] << 24) | ((word32)(t)[o1] << 16) | \ + ((word32)(t)[o2] << 8) | ((word32)(t)[o3] << 0)) + +/* load sbox into cache by cache line stride */ +#ifndef WOLFSSL_AES_TOUCH_LINES + #define PreFetchSBox(x) { \ + x = 0; \ + int i; \ + for (i = 0; i < 256; i += WC_CACHE_LINE_SZ/4) { \ + x &= Tsbox[i]; \ + } \ + } +#else + #define PreFetchSBox(x) ( x = 0 ) +#endif +#endif + +#if !defined(WC_AES_BITSLICED) +/* Encrypt a block using AES. + * + * @param [in] aes AES object. + * @param [in] inBlock Block to encrypt. + * @param [out] outBlock Encrypted block. + * @param [in] r Rounds divided by 2. + * @param [in] sz Number of blocks to encrypt + */ +__global__ void AesEncrypt_C_CUDA(word32* rkBase, const byte* inBlockBase, byte* outBlockBase, + word32 r, word32 sz) +{ + word32 s0, s1, s2, s3; + word32 t0, t1, t2, t3; + word32 sBox; + int index = blockIdx.x * blockDim.x + threadIdx.x; + int stride = blockDim.x * gridDim.x; + const byte* inBlock = inBlockBase; + byte* outBlock = outBlockBase; + word32* rk; + + for (int i = index; i < sz; i += stride) { + rk = rkBase; + inBlock = inBlockBase + i * 4 * sizeof(s0); + outBlock = outBlockBase + i * 4 * sizeof(s0); + + /* + * map byte array block to cipher state + * and add initial round key: + */ + XMEMCPY(&s0, inBlock, sizeof(s0)); + XMEMCPY(&s1, inBlock + sizeof(s0), sizeof(s1)); + XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2)); + XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3)); + +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif + + /* AddRoundKey */ + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + +#ifndef WOLFSSL_AES_SMALL_TABLES +#ifndef WC_NO_CACHE_RESISTANT + s0 |= PreFetchTe(); +#endif + +#ifndef WOLFSSL_AES_TOUCH_LINES +#define ENC_ROUND_T_S(o) \ + t0 = GetTable(Te_CUDA[0], GETBYTE(s0, 3)) ^ GetTable(Te_CUDA[1], GETBYTE(s1, 2)) ^ \ + GetTable(Te_CUDA[2], GETBYTE(s2, 1)) ^ GetTable(Te_CUDA[3], GETBYTE(s3, 0)) ^ \ + rk[(o)+4]; \ + t1 = GetTable(Te_CUDA[0], GETBYTE(s1, 3)) ^ GetTable(Te_CUDA[1], GETBYTE(s2, 2)) ^ \ + GetTable(Te_CUDA[2], GETBYTE(s3, 1)) ^ GetTable(Te_CUDA[3], GETBYTE(s0, 0)) ^ \ + rk[(o)+5]; \ + t2 = GetTable(Te_CUDA[0], GETBYTE(s2, 3)) ^ GetTable(Te_CUDA[1], GETBYTE(s3, 2)) ^ \ + GetTable(Te_CUDA[2], GETBYTE(s0, 1)) ^ GetTable(Te_CUDA[3], GETBYTE(s1, 0)) ^ \ + rk[(o)+6]; \ + t3 = GetTable(Te_CUDA[0], GETBYTE(s3, 3)) ^ GetTable(Te_CUDA[1], GETBYTE(s0, 2)) ^ \ + GetTable(Te_CUDA[2], GETBYTE(s1, 1)) ^ GetTable(Te_CUDA[3], GETBYTE(s2, 0)) ^ \ + rk[(o)+7] +#define ENC_ROUND_S_T(o) \ + s0 = GetTable(Te_CUDA[0], GETBYTE(t0, 3)) ^ GetTable(Te_CUDA[1], GETBYTE(t1, 2)) ^ \ + GetTable(Te_CUDA[2], GETBYTE(t2, 1)) ^ GetTable(Te_CUDA[3], GETBYTE(t3, 0)) ^ \ + rk[(o)+0]; \ + s1 = GetTable(Te_CUDA[0], GETBYTE(t1, 3)) ^ GetTable(Te_CUDA[1], GETBYTE(t2, 2)) ^ \ + GetTable(Te_CUDA[2], GETBYTE(t3, 1)) ^ GetTable(Te_CUDA[3], GETBYTE(t0, 0)) ^ \ + rk[(o)+1]; \ + s2 = GetTable(Te_CUDA[0], GETBYTE(t2, 3)) ^ GetTable(Te_CUDA[1], GETBYTE(t3, 2)) ^ \ + GetTable(Te_CUDA[2], GETBYTE(t0, 1)) ^ GetTable(Te_CUDA[3], GETBYTE(t1, 0)) ^ \ + rk[(o)+2]; \ + s3 = GetTable(Te_CUDA[0], GETBYTE(t3, 3)) ^ GetTable(Te_CUDA[1], GETBYTE(t0, 2)) ^ \ + GetTable(Te_CUDA[2], GETBYTE(t1, 1)) ^ GetTable(Te_CUDA[3], GETBYTE(t2, 0)) ^ \ + rk[(o)+3] +#else +#define ENC_ROUND_T_S(o) \ + GetTable_Multi(Te_CUDA[0], &t0, GETBYTE(s0, 3), &t1, GETBYTE(s1, 3), \ + &t2, GETBYTE(s2, 3), &t3, GETBYTE(s3, 3)); \ + XorTable_Multi(Te_CUDA[1], &t0, GETBYTE(s1, 2), &t1, GETBYTE(s2, 2), \ + &t2, GETBYTE(s3, 2), &t3, GETBYTE(s0, 2)); \ + XorTable_Multi(Te_CUDA[2], &t0, GETBYTE(s2, 1), &t1, GETBYTE(s3, 1), \ + &t2, GETBYTE(s0, 1), &t3, GETBYTE(s1, 1)); \ + XorTable_Multi(Te_CUDA[3], &t0, GETBYTE(s3, 0), &t1, GETBYTE(s0, 0), \ + &t2, GETBYTE(s1, 0), &t3, GETBYTE(s2, 0)); \ + t0 ^= rk[(o)+4]; t1 ^= rk[(o)+5]; t2 ^= rk[(o)+6]; t3 ^= rk[(o)+7]; + +#define ENC_ROUND_S_T(o) \ + GetTable_Multi(Te_CUDA[0], &s0, GETBYTE(t0, 3), &s1, GETBYTE(t1, 3), \ + &s2, GETBYTE(t2, 3), &s3, GETBYTE(t3, 3)); \ + XorTable_Multi(Te_CUDA[1], &s0, GETBYTE(t1, 2), &s1, GETBYTE(t2, 2), \ + &s2, GETBYTE(t3, 2), &s3, GETBYTE(t0, 2)); \ + XorTable_Multi(Te_CUDA[2], &s0, GETBYTE(t2, 1), &s1, GETBYTE(t3, 1), \ + &s2, GETBYTE(t0, 1), &s3, GETBYTE(t1, 1)); \ + XorTable_Multi(Te_CUDA[3], &s0, GETBYTE(t3, 0), &s1, GETBYTE(t0, 0), \ + &s2, GETBYTE(t1, 0), &s3, GETBYTE(t2, 0)); \ + s0 ^= rk[(o)+0]; s1 ^= rk[(o)+1]; s2 ^= rk[(o)+2]; s3 ^= rk[(o)+3]; +#endif + +#ifndef WOLFSSL_AES_NO_UNROLL + /* Unroll the loop. */ + ENC_ROUND_T_S( 0); + ENC_ROUND_S_T( 8); ENC_ROUND_T_S( 8); + ENC_ROUND_S_T(16); ENC_ROUND_T_S(16); + ENC_ROUND_S_T(24); ENC_ROUND_T_S(24); + ENC_ROUND_S_T(32); ENC_ROUND_T_S(32); + if (r > 5) { + ENC_ROUND_S_T(40); ENC_ROUND_T_S(40); + if (r > 6) { + ENC_ROUND_S_T(48); ENC_ROUND_T_S(48); + } + } + rk += r * 8; +#else + /* + * Nr - 1 full rounds: + */ + + for (;;) { + ENC_ROUND_T_S(0); + + rk += 8; + if (--r == 0) { + break; + } + + ENC_ROUND_S_T(0); + } +#endif + + /* + * apply last round and + * map cipher state to byte array block: + */ + +#ifndef WOLFSSL_AES_TOUCH_LINES + s0 = + (GetTable(Te_CUDA[2], GETBYTE(t0, 3)) & 0xff000000) ^ + (GetTable(Te_CUDA[3], GETBYTE(t1, 2)) & 0x00ff0000) ^ + (GetTable(Te_CUDA[0], GETBYTE(t2, 1)) & 0x0000ff00) ^ + (GetTable(Te_CUDA[1], GETBYTE(t3, 0)) & 0x000000ff) ^ + rk[0]; + s1 = + (GetTable(Te_CUDA[2], GETBYTE(t1, 3)) & 0xff000000) ^ + (GetTable(Te_CUDA[3], GETBYTE(t2, 2)) & 0x00ff0000) ^ + (GetTable(Te_CUDA[0], GETBYTE(t3, 1)) & 0x0000ff00) ^ + (GetTable(Te_CUDA[1], GETBYTE(t0, 0)) & 0x000000ff) ^ + rk[1]; + s2 = + (GetTable(Te_CUDA[2], GETBYTE(t2, 3)) & 0xff000000) ^ + (GetTable(Te_CUDA[3], GETBYTE(t3, 2)) & 0x00ff0000) ^ + (GetTable(Te_CUDA[0], GETBYTE(t0, 1)) & 0x0000ff00) ^ + (GetTable(Te_CUDA[1], GETBYTE(t1, 0)) & 0x000000ff) ^ + rk[2]; + s3 = + (GetTable(Te_CUDA[2], GETBYTE(t3, 3)) & 0xff000000) ^ + (GetTable(Te_CUDA[3], GETBYTE(t0, 2)) & 0x00ff0000) ^ + (GetTable(Te_CUDA[0], GETBYTE(t1, 1)) & 0x0000ff00) ^ + (GetTable(Te_CUDA[1], GETBYTE(t2, 0)) & 0x000000ff) ^ + rk[3]; +#else + { + word32 u0; + word32 u1; + word32 u2; + word32 u3; + + s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3]; + GetTable_Multi(Te_CUDA[2], &u0, GETBYTE(t0, 3), &u1, GETBYTE(t1, 3), + &u2, GETBYTE(t2, 3), &u3, GETBYTE(t3, 3)); + s0 ^= u0 & 0xff000000; s1 ^= u1 & 0xff000000; + s2 ^= u2 & 0xff000000; s3 ^= u3 & 0xff000000; + GetTable_Multi(Te_CUDA[3], &u0, GETBYTE(t1, 2), &u1, GETBYTE(t2, 2), + &u2, GETBYTE(t3, 2), &u3, GETBYTE(t0, 2)); + s0 ^= u0 & 0x00ff0000; s1 ^= u1 & 0x00ff0000; + s2 ^= u2 & 0x00ff0000; s3 ^= u3 & 0x00ff0000; + GetTable_Multi(Te_CUDA[0], &u0, GETBYTE(t2, 1), &u1, GETBYTE(t3, 1), + &u2, GETBYTE(t0, 1), &u3, GETBYTE(t1, 1)); + s0 ^= u0 & 0x0000ff00; s1 ^= u1 & 0x0000ff00; + s2 ^= u2 & 0x0000ff00; s3 ^= u3 & 0x0000ff00; + GetTable_Multi(Te_CUDA[1], &u0, GETBYTE(t3, 0), &u1, GETBYTE(t0, 0), + &u2, GETBYTE(t1, 0), &u3, GETBYTE(t2, 0)); + s0 ^= u0 & 0x000000ff; s1 ^= u1 & 0x000000ff; + s2 ^= u2 & 0x000000ff; s3 ^= u3 & 0x000000ff; + } +#endif +#else +#ifndef WC_NO_CACHE_RESISTANT + s0 |= PreFetchSBox(); +#endif + + r *= 2; + /* Two rounds at a time */ + for (rk += 4; r > 1; r--, rk += 4) { + t0 = + ((word32)GetTable8(Tsbox, GETBYTE(s0, 3)) << 24) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s1, 2)) << 16) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s2, 1)) << 8) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s3, 0))); + t1 = + ((word32)GetTable8(Tsbox, GETBYTE(s1, 3)) << 24) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s2, 2)) << 16) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s3, 1)) << 8) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s0, 0))); + t2 = + ((word32)GetTable8(Tsbox, GETBYTE(s2, 3)) << 24) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s3, 2)) << 16) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s0, 1)) << 8) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s1, 0))); + t3 = + ((word32)GetTable8(Tsbox, GETBYTE(s3, 3)) << 24) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s0, 2)) << 16) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s1, 1)) << 8) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s2, 0))); + + s0 = + (col_mul(t0, 3, 2, 0, 1) << 24) ^ + (col_mul(t0, 2, 1, 0, 3) << 16) ^ + (col_mul(t0, 1, 0, 2, 3) << 8) ^ + (col_mul(t0, 0, 3, 2, 1) ) ^ + rk[0]; + s1 = + (col_mul(t1, 3, 2, 0, 1) << 24) ^ + (col_mul(t1, 2, 1, 0, 3) << 16) ^ + (col_mul(t1, 1, 0, 2, 3) << 8) ^ + (col_mul(t1, 0, 3, 2, 1) ) ^ + rk[1]; + s2 = + (col_mul(t2, 3, 2, 0, 1) << 24) ^ + (col_mul(t2, 2, 1, 0, 3) << 16) ^ + (col_mul(t2, 1, 0, 2, 3) << 8) ^ + (col_mul(t2, 0, 3, 2, 1) ) ^ + rk[2]; + s3 = + (col_mul(t3, 3, 2, 0, 1) << 24) ^ + (col_mul(t3, 2, 1, 0, 3) << 16) ^ + (col_mul(t3, 1, 0, 2, 3) << 8) ^ + (col_mul(t3, 0, 3, 2, 1) ) ^ + rk[3]; + } + + t0 = + ((word32)GetTable8(Tsbox, GETBYTE(s0, 3)) << 24) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s1, 2)) << 16) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s2, 1)) << 8) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s3, 0))); + t1 = + ((word32)GetTable8(Tsbox, GETBYTE(s1, 3)) << 24) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s2, 2)) << 16) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s3, 1)) << 8) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s0, 0))); + t2 = + ((word32)GetTable8(Tsbox, GETBYTE(s2, 3)) << 24) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s3, 2)) << 16) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s0, 1)) << 8) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s1, 0))); + t3 = + ((word32)GetTable8(Tsbox, GETBYTE(s3, 3)) << 24) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s0, 2)) << 16) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s1, 1)) << 8) ^ + ((word32)GetTable8(Tsbox, GETBYTE(s2, 0))); + s0 = t0 ^ rk[0]; + s1 = t1 ^ rk[1]; + s2 = t2 ^ rk[2]; + s3 = t3 ^ rk[3]; +#endif + + /* write out */ +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif + + XMEMCPY(outBlock, &s0, sizeof(s0)); + XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1)); + XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2)); + XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3)); + } +} + +void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, + word32 r) +{ + byte *inBlock_GPU = NULL; + byte *outBlock_GPU = NULL; + word32* rk_GPU = NULL; + cudaError_t ret = cudaSuccess; + +#ifdef WC_C_DYNAMIC_FALLBACK + if ( ret == cudaSuccess ) + ret = cudaMalloc(&rk_GPU, sizeof(aes->key_C_fallback)); + if ( ret == cudaSuccess ) + ret = cudaMemcpy(rk_GPU, aes->key_C_fallback, sizeof(aes->key_C_fallback), cudaMemcpyDefault); +#else + if ( ret == cudaSuccess ) + ret = cudaMalloc(&rk_GPU, sizeof(aes->key)); + if ( ret == cudaSuccess ) + ret = cudaMemcpy(rk_GPU, aes->key, sizeof(aes->key), cudaMemcpyDefault); +#endif + + if ( ret == cudaSuccess ) + ret = cudaMalloc(&inBlock_GPU, AES_BLOCK_SIZE); + if ( ret == cudaSuccess ) + ret = cudaMemcpy(inBlock_GPU, inBlock, AES_BLOCK_SIZE, cudaMemcpyDefault); + + if ( ret == cudaSuccess ) + ret = cudaMalloc(&outBlock_GPU, AES_BLOCK_SIZE); + + if ( ret == cudaSuccess ) + AesEncrypt_C_CUDA<<<1,1>>>(rk_GPU, inBlock_GPU, outBlock_GPU, r, 1); + + if ( ret == cudaSuccess ) + ret = cudaMemcpy(outBlock, outBlock_GPU, AES_BLOCK_SIZE, cudaMemcpyDefault); + + cudaFree(inBlock_GPU); + cudaFree(outBlock_GPU); + cudaFree(rk_GPU); +} + +#if defined(HAVE_AES_ECB) && !(defined(WOLFSSL_IMX6_CAAM) && \ + !defined(NO_IMX6_CAAM_AES) && !defined(WOLFSSL_QNX_CAAM)) +/* Encrypt a number of blocks using AES. + * + * @param [in] aes AES object. + * @param [in] in Block to encrypt. + * @param [out] out Encrypted block. + * @param [in] sz Number of blocks to encrypt. + */ +void AesEncryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz) +{ + byte *in_GPU = NULL; + byte *out_GPU = NULL; + word32* rk_GPU = NULL; + cudaError_t ret = cudaSuccess; + +#ifdef WC_C_DYNAMIC_FALLBACK + if ( ret == cudaSuccess ) + ret = cudaMalloc(&rk_GPU, sizeof(aes->key_C_fallback)); + if ( ret == cudaSuccess ) + ret = cudaMemcpy(rk_GPU, aes->key_C_fallback, sizeof(aes->key_C_fallback), cudaMemcpyDefault); +#else + if ( ret == cudaSuccess ) + ret = cudaMalloc(&rk_GPU, sizeof(aes->key)); + if ( ret == cudaSuccess ) + ret = cudaMemcpy(rk_GPU, aes->key, sizeof(aes->key), cudaMemcpyDefault); +#endif + + if ( ret == cudaSuccess ) + ret = cudaMalloc(&in_GPU, sz); + if ( ret == cudaSuccess ) + ret = cudaMemcpy(in_GPU, in, sz, cudaMemcpyDefault); + + if ( ret == cudaSuccess ) + ret = cudaMalloc(&out_GPU, sz); + + if ( ret == cudaSuccess ) { + int blockSize = 256; + int numBlocks = (sz / AES_BLOCK_SIZE + blockSize - 1) / blockSize; + AesEncrypt_C_CUDA<<>>(rk_GPU, in_GPU, out_GPU, aes->rounds >> 1, sz / AES_BLOCK_SIZE); + } + + if ( ret == cudaSuccess ) + ret = cudaMemcpy(out, out_GPU, sz, cudaMemcpyDefault); + + cudaFree(in_GPU); + cudaFree(out_GPU); + cudaFree(rk_GPU); +} +#endif + +#else + +/* Encrypt a block using AES. + * + * @param [in] aes AES object. + * @param [in] inBlock Block to encrypt. + * @param [out] outBlock Encrypted block. + * @param [in] r Rounds divided by 2. + */ +__global__ +void AesEncrypt_C_CUDA(Aes* aes, const byte* inBlock, byte* outBlock, + word32 r) +{ + bs_word state[AES_BLOCK_BITS]; + + (void)r; + + XMEMCPY(state, inBlock, AES_BLOCK_SIZE); + XMEMSET(((byte*)state) + AES_BLOCK_SIZE, 0, sizeof(state) - AES_BLOCK_SIZE); + + bs_encrypt(state, aes->bs_key, aes->rounds); + + XMEMCPY(outBlock, state, AES_BLOCK_SIZE); +} + +void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, + word32 r) +{ + AesEncrypt_C_CUDA<<<1,1>>>(aes, inBlock, outBlock, r); +} + +#if defined(HAVE_AES_ECB) && !(defined(WOLFSSL_IMX6_CAAM) && \ + !defined(NO_IMX6_CAAM_AES) && !defined(WOLFSSL_QNX_CAAM)) +/* Encrypt a number of blocks using AES. + * + * @param [in] aes AES object. + * @param [in] in Block to encrypt. + * @param [out] out Encrypted block. + * @param [in] sz Number of blocks to encrypt. + */ +void AesEncryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz) +{ + bs_word state[AES_BLOCK_BITS]; + + while (sz >= BS_BLOCK_SIZE) { + XMEMCPY(state, in, BS_BLOCK_SIZE); + bs_encrypt(state, aes->bs_key, aes->rounds); + XMEMCPY(out, state, BS_BLOCK_SIZE); + sz -= BS_BLOCK_SIZE; + in += BS_BLOCK_SIZE; + out += BS_BLOCK_SIZE; + } + if (sz > 0) { + XMEMCPY(state, in, sz); + XMEMSET(((byte*)state) + sz, 0, sizeof(state) - sz); + bs_encrypt(state, aes->bs_key, aes->rounds); + XMEMCPY(out, state, sz); + } +} +#endif + +#endif /* !WC_AES_BITSLICED */ + +#endif /* HAVE_CUDA */ + +#endif /* !WOLFSSL_TI_CRYPT */ + +} /* extern "C" */ diff --git a/wolfcrypt/src/port/intel/quickassist_sync.c b/wolfcrypt/src/port/intel/quickassist_sync.c index 4a68b337cb..4d79ca10c7 100644 --- a/wolfcrypt/src/port/intel/quickassist_sync.c +++ b/wolfcrypt/src/port/intel/quickassist_sync.c @@ -144,9 +144,9 @@ typedef void (*IntelQaFreeFunc)(struct IntelQaDev*); /* QuickAssist device */ typedef struct IntelQaDev { - CpaInstanceHandle handle; + CpaInstanceHandle handle; int devId; - void* heap; + void* heap; /* callback return info */ int ret; @@ -220,7 +220,7 @@ static int IntelQaGetCyInstanceCount(void); #ifdef WOLF_CRYPTO_CB static int IntelQaSymSync_CryptoDevCb(int, struct wc_CryptoInfo*, - void*); + void*); #endif /* WOLF_CRYPTO_CB */ @@ -423,7 +423,7 @@ int IntelQaHardwareStart(const char* process_name, int limitDevAccess) #ifdef QAT_DEBUG /* optionally enable debugging */ - //osalLogLevelSet(8); + /* osalLogLevelSet(8); */ #endif status = cpaCyGetNumInstances(&g_numInstances); diff --git a/wolfcrypt/src/port/iotsafe/iotsafe.c b/wolfcrypt/src/port/iotsafe/iotsafe.c index 8a7ec2e635..2fcf612173 100644 --- a/wolfcrypt/src/port/iotsafe/iotsafe.c +++ b/wolfcrypt/src/port/iotsafe/iotsafe.c @@ -612,7 +612,7 @@ static int iotsafe_parse_public_key(char* resp, int len, ecc_key *key) /* Execute GEN_KEYPAIR on the IoT-SAFE applet. * * Return -1 on error; 0 if the operation is successful, but - * the generated public key was not yet stored in `key`; 1 if + * the generated public key was not yet stored in `key`; 1 if * the operation is successful and the public key was found in the * command response and copied to the `key` structure, if not NULL. */ @@ -1089,11 +1089,11 @@ static int wolfIoT_hkdf_extract(byte* prk, const byte* salt, word32 saltLen, localSalt = tmp; } } - - ret = iotsafe_hkdf_extract(prk, localSalt, saltLen, ikm, ikmLen, digest); + + ret = iotsafe_hkdf_extract(prk, localSalt, saltLen, ikm, ikmLen, digest); (void)ctx; return ret; -} +} #endif static int wolfIoT_ecc_sign(WOLFSSL* ssl, @@ -1573,7 +1573,7 @@ int wolfSSL_CTX_iotsafe_enable(WOLFSSL_CTX *ctx) WOLFSSL_MSG("ECC callbacks set to IoT_safe interface"); #endif #ifndef NO_RSA - /* wolfSSL_CTX_SetRsaSignCb(wolfIoT_rsa_sign); // TODO: RSA callbacks */ + /* wolfSSL_CTX_SetRsaSignCb(wolfIoT_rsa_sign); */ /* TODO: RSA callbacks */ #endif #else (void)ctx; diff --git a/wolfcrypt/src/port/kcapi/kcapi_aes.c b/wolfcrypt/src/port/kcapi/kcapi_aes.c index bf87340a3b..1f1aa03f4c 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_aes.c +++ b/wolfcrypt/src/port/kcapi/kcapi_aes.c @@ -39,8 +39,8 @@ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$g") - #pragma const_seg(".fipsB$g") + #pragma code_seg(".fipsA$ba") + #pragma const_seg(".fipsB$ba") #endif #endif diff --git a/wolfcrypt/src/port/liboqs/liboqs.c b/wolfcrypt/src/port/liboqs/liboqs.c index f04cab02c7..46733cbbf3 100644 --- a/wolfcrypt/src/port/liboqs/liboqs.c +++ b/wolfcrypt/src/port/liboqs/liboqs.c @@ -60,7 +60,7 @@ static void wolfSSL_liboqsGetRandomData(uint8_t* buffer, size_t numOfBytes) ret = wc_RNG_GenerateBlock(liboqsCurrentRNG, buffer, numOfBytes_word32); if (ret != 0) { - /* ToDo: liboqs exits programm if RNG fails, + /* ToDo: liboqs exits program if RNG fails, * not sure what to do here */ WOLFSSL_MSG_EX( diff --git a/wolfcrypt/src/port/maxim/maxq10xx.c b/wolfcrypt/src/port/maxim/maxq10xx.c index c0375fc519..06b9af0802 100644 --- a/wolfcrypt/src/port/maxim/maxq10xx.c +++ b/wolfcrypt/src/port/maxim/maxq10xx.c @@ -56,7 +56,7 @@ void dbg_dumphex(const char *identifier, const uint8_t* pdata, uint32_t plen); #endif /* MAXQ_DEBUG */ #if defined(USE_WINDOWS_API) -# define maxq_CryptHwMutexTryLock() (0) +# define maxq_CryptHwMutexTryLock() 0 #endif #define AES_KEY_ID_START (0x2000) diff --git a/wolfcrypt/src/port/nxp/ksdk_port.c b/wolfcrypt/src/port/nxp/ksdk_port.c index 7cfa04771b..b63864b0bd 100644 --- a/wolfcrypt/src/port/nxp/ksdk_port.c +++ b/wolfcrypt/src/port/nxp/ksdk_port.c @@ -105,7 +105,7 @@ static int ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz) #else res = mp_to_unsigned_bin(A, dst); if (res == MP_OKAY) { - ltc_reverse_array(dst, sz); + ltc_reverse_array(dst, sz); } #endif *psz = sz; @@ -134,7 +134,7 @@ int mp_mul(mp_int *A, mp_int *B, mp_int *C) szA = mp_unsigned_bin_size(A); szB = mp_unsigned_bin_size(B); - /* if unsigned mul can fit into LTC PKHA let's use it, otherwise call + /* if unsigned mul can fit into LTC PKHA let's use it, otherwise call * software mul */ if ((szA <= LTC_MAX_INT_BYTES / 2) && (szB <= LTC_MAX_INT_BYTES / 2)) { uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, @@ -264,7 +264,7 @@ int mp_mod(mp_int *a, mp_int *b, mp_int *c) { ltc_reverse_array(ptrC, sizeC); res = mp_read_unsigned_bin(c, ptrC, sizeC); - + #if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \ defined(WOLFSSL_SP_INT_NEGATIVE) /* fix sign */ @@ -341,10 +341,10 @@ int mp_invmod(mp_int *a, mp_int *b, mp_int *c) res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); if (res == MP_OKAY) res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - + /* if a >= b then reduce */ /* TODO: Perhaps always do mod reduce depending on hardware performance */ - if (res == MP_OKAY && + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrB, sizeB) >= 0) { if (LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrA, &sizeA, kLTC_PKHA_IntegerArith) != kStatus_Success) { @@ -411,7 +411,7 @@ int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) int res = MP_OKAY; status_t status; int szA, szB, szC; - + #ifdef ENABLE_NXPLTC_TESTS mp_int t; mp_init(&t); @@ -543,8 +543,8 @@ int ltc_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int useConstTime) szX = mp_unsigned_bin_size(X); szP = mp_unsigned_bin_size(P); - if ((szG <= LTC_MAX_INT_BYTES) && - (szX <= LTC_MAX_INT_BYTES) && + if ((szG <= LTC_MAX_INT_BYTES) && + (szX <= LTC_MAX_INT_BYTES) && (szP <= LTC_MAX_INT_BYTES)) { uint16_t sizeG, sizeX, sizeP, sizeY; @@ -563,9 +563,9 @@ int ltc_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int useConstTime) /* if G >= P then reduce */ /* TODO: Perhaps always do mod reduce depending on hardware performance */ - if (res == MP_OKAY && + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { - res = LTC_PKHA_ModRed(LTC_BASE, + res = LTC_PKHA_ModRed(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrG, &sizeG, kLTC_PKHA_IntegerArith); @@ -602,7 +602,7 @@ int ltc_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int useConstTime) } if (ptrG) { XFREE(ptrG, NULL, DYNAMIC_TYPE_BIGINT); - } + } } else { #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) @@ -678,7 +678,7 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); } if (res == MP_OKAY) { - if (LTC_PKHA_PrimalityTest(LTC_BASE, + if (LTC_PKHA_PrimalityTest(LTC_BASE, ptrB, sizeB, /* seed */ (uint8_t*)&t, sizeof(t), /* trials */ ptrA, sizeA, /* candidate */ @@ -726,7 +726,7 @@ int mp_prime_is_prime(mp_int* a, int t, int* result) #if defined(HAVE_ECC) && defined(FREESCALE_LTC_ECC) /* convert from mp_int to LTC integer, as array of bytes of size sz. - * if mp_int has less bytes than sz, add zero bytes at most significant byte + * if mp_int has less bytes than sz, add zero bytes at most significant byte * positions. * This is when for example modulus is 32 bytes (P-256 curve) * and mp_int has only 31 bytes, we add leading zeros @@ -763,7 +763,7 @@ static int ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) return res; } -/* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA +/* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA * driver functions */ #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #define ECC192 @@ -1196,7 +1196,7 @@ static const uint8_t invThree[32] = { /* * * finds square root in finite field when modulus congruent to 5 modulo 8 - * this is fixed to curve25519 modulus 2^255 - 19 which is congruent to + * this is fixed to curve25519 modulus 2^255 - 19 which is congruent to * 5 modulo 8. * * This function solves equation: res^2 = a mod (2^255 - 19) @@ -1914,7 +1914,7 @@ status_t LTC_PKHA_Ed25519_PointDecompress(const uint8_t *pubkey, return status; } -/* LSByte first of Ed25519 parameter l = 2^252 + +/* LSByte first of Ed25519 parameter l = 2^252 + * 27742317777372353535851937790883648493 */ static const uint8_t l_coefEdDSA[] = { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, diff --git a/wolfcrypt/src/port/nxp/se050_port.c b/wolfcrypt/src/port/nxp/se050_port.c index b2ada57737..ad526778a5 100644 --- a/wolfcrypt/src/port/nxp/se050_port.c +++ b/wolfcrypt/src/port/nxp/se050_port.c @@ -266,7 +266,7 @@ int se050_hash_copy(SE050_HASH_Context* src, SE050_HASH_Context* dst) int se050_hash_update(SE050_HASH_Context* se050Ctx, const byte* data, word32 len) { - byte* tmp = NULL; + byte* tmp = NULL; if (se050Ctx == NULL || (len > 0 && data == NULL)) { return BAD_FUNC_ARG; diff --git a/wolfcrypt/src/port/pic32/pic32mz-crypt.c b/wolfcrypt/src/port/pic32/pic32mz-crypt.c index 32cf02ed05..171fe0aac2 100644 --- a/wolfcrypt/src/port/pic32/pic32mz-crypt.c +++ b/wolfcrypt/src/port/pic32/pic32mz-crypt.c @@ -365,7 +365,7 @@ static void reset_engine(int algo) static void update_engine(const byte *input, word32 len, word32 *hash) { int total; - + gLHDesc.bd[gLHDesc.currBd].UPDPTR = KVA_TO_PA(hash); /* Add the data to the current buffer. If the buffer fills, start processing it diff --git a/wolfcrypt/src/port/st/stsafe.c b/wolfcrypt/src/port/st/stsafe.c index ebe0727332..4745fcf531 100644 --- a/wolfcrypt/src/port/st/stsafe.c +++ b/wolfcrypt/src/port/st/stsafe.c @@ -539,7 +539,7 @@ int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) &otherKeyY[0], (word32*)&otherKeyY_len); if (rc == 0) { /* Compute shared secret */ - *info->pk.ecdh.outlen = 0; + *info->pk.ecdh.outlen = 0; rc = stsafe_interface_shared_secret( #ifdef WOLFSSL_STSAFE_TAKES_SLOT STSAFE_A_SLOT_0, diff --git a/wolfcrypt/src/port/ti/ti-hash.c b/wolfcrypt/src/port/ti/ti-hash.c index 0077e96dab..48270f15a8 100644 --- a/wolfcrypt/src/port/ti/ti-hash.c +++ b/wolfcrypt/src/port/ti/ti-hash.c @@ -203,7 +203,7 @@ WOLFSSL_API int wc_Md5GetHash(Md5* md5, byte* hash) WOLFSSL_API int wc_Md5Copy(Md5* src, Md5* dst) { - return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); + return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); } WOLFSSL_API int wc_Md5Hash(const byte*data, word32 len, byte* hash) @@ -249,7 +249,7 @@ WOLFSSL_API int wc_ShaGetHash(Sha* sha, byte* hash) WOLFSSL_API int wc_ShaCopy(Sha* src, Sha* dst) { - return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); + return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); } WOLFSSL_API int wc_ShaHash(const byte*data, word32 len, byte* hash) diff --git a/wolfcrypt/src/port/xilinx/xil-aesgcm.c b/wolfcrypt/src/port/xilinx/xil-aesgcm.c index e2dfc8af43..d92a2cd415 100644 --- a/wolfcrypt/src/port/xilinx/xil-aesgcm.c +++ b/wolfcrypt/src/port/xilinx/xil-aesgcm.c @@ -87,9 +87,9 @@ static WC_INLINE int aligned_xmalloc(byte** buf, byte** aligned, void* heap, wor static WC_INLINE void aligned_xfree(void* buf, void* heap) { - if (buf == NULL) - return; - XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) + return; + XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); } static WC_INLINE int check_keysize(word32 len) diff --git a/wolfcrypt/src/port/xilinx/xil-versal-glue.c b/wolfcrypt/src/port/xilinx/xil-versal-glue.c index ed90fd4fc8..f40c86a077 100644 --- a/wolfcrypt/src/port/xilinx/xil-versal-glue.c +++ b/wolfcrypt/src/port/xilinx/xil-versal-glue.c @@ -78,7 +78,7 @@ int wc_InitXsecure(wc_Xsecure* xsec) /** Convert Xilinx specific error to string - err The error to convert + err The error to convert Returns a pointer to a string (always, never returns NULL). */ diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index 8be0c64e82..5ca98cb0fb 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/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,14 @@ #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_pbkdf_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000010 }; + int wolfCrypt_FIPS_PBKDF_sanity(void) + { + return 0; + } +#endif #ifdef HAVE_PBKDF1 @@ -214,7 +232,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/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index d44f2e2d2f..272afd93cf 100644 --- a/wolfcrypt/src/random.c +++ b/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 { @@ -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; @@ -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) { @@ -3832,6 +3846,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) || \ diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 4299fd2f86..717d4cca06 100644 --- a/wolfcrypt/src/rsa.c +++ b/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,7 +127,6 @@ enum { RSA_STATE_DECRYPT_RES }; - static void wc_RsaCleanup(RsaKey* key) { #if !defined(WOLFSSL_RSA_VERIFY_INLINE) && !defined(WOLFSSL_NO_MALLOC) @@ -148,20 +153,11 @@ 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; @@ -188,19 +184,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 +268,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 +297,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) { @@ -3339,7 +3318,7 @@ 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); + &outLen, rsa_type, key, rng); if (ret != CRYPTOCB_UNAVAILABLE) return ret; /* fall-through when unavailable */ @@ -3496,7 +3475,7 @@ 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); + &outLen, rsa_type, key, rng); if (ret != CRYPTOCB_UNAVAILABLE) return ret; /* fall-through when unavailable */ @@ -4721,7 +4700,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; @@ -4827,12 +4811,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 +4921,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); diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 69990791fd..86d2f83b97 100644 --- a/wolfcrypt/src/sha.c +++ b/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) diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 0025e85727..00c5e9afbf 100644 --- a/wolfcrypt/src/sha256.c +++ b/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,199 @@ 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, SHA256_AVX2, + SHA256_AVX1_RORX, 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; + } + 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; + } + } + 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: + ret = Transform_Sha256_AVX1_Sha(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: + ret = Transform_Sha256_AVX1_Sha_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 +661,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 +683,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); @@ -1151,7 +1359,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) { @@ -1387,8 +1603,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)], @@ -1732,11 +1952,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/wolfcrypt/src/sha256_asm.S b/wolfcrypt/src/sha256_asm.S index 3f7f6cf24a..2f2bfde578 100644 --- a/wolfcrypt/src/sha256_asm.S +++ b/wolfcrypt/src/sha256_asm.S @@ -1,6 +1,6 @@ /* sha256_asm.S */ /* - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -92,6 +92,7 @@ Transform_Sha256_SSE2_Sha: .p2align 4 _Transform_Sha256_SSE2_Sha: #endif /* __APPLE__ */ + leaq L_sse2_sha256_sha_k(%rip), %rdx movdqa L_sse2_sha256_shuf_mask(%rip), %xmm10 movq (%rdi), %xmm1 movq 8(%rdi), %xmm2 @@ -108,14 +109,14 @@ _Transform_Sha256_SSE2_Sha: movdqa %xmm2, %xmm9 # Rounds: 0-3 movdqa %xmm3, %xmm0 - paddd 0+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd (%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 pshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 # Rounds: 4-7 pshufb %xmm10, %xmm4 movdqa %xmm4, %xmm0 - paddd 16+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 16(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 pshufd $14, %xmm0, %xmm0 sha256msg1 %xmm4, %xmm3 @@ -123,7 +124,7 @@ _Transform_Sha256_SSE2_Sha: # Rounds: 8-11 pshufb %xmm10, %xmm5 movdqa %xmm5, %xmm0 - paddd 32+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 32(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 pshufd $14, %xmm0, %xmm0 sha256msg1 %xmm5, %xmm4 @@ -131,7 +132,7 @@ _Transform_Sha256_SSE2_Sha: # Rounds: 12-15 pshufb %xmm10, %xmm6 movdqa %xmm6, %xmm0 - paddd 48+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 48(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm6, %xmm7 palignr $4, %xmm5, %xmm7 @@ -142,7 +143,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 16-19 movdqa %xmm3, %xmm0 - paddd 64+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 64(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm3, %xmm7 palignr $4, %xmm6, %xmm7 @@ -153,7 +154,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 20-23 movdqa %xmm4, %xmm0 - paddd 80+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 80(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm4, %xmm7 palignr $4, %xmm3, %xmm7 @@ -164,7 +165,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 24-27 movdqa %xmm5, %xmm0 - paddd 96+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 96(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm5, %xmm7 palignr $4, %xmm4, %xmm7 @@ -175,7 +176,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 28-31 movdqa %xmm6, %xmm0 - paddd 112+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 112(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm6, %xmm7 palignr $4, %xmm5, %xmm7 @@ -186,7 +187,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 32-35 movdqa %xmm3, %xmm0 - paddd 128+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 128(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm3, %xmm7 palignr $4, %xmm6, %xmm7 @@ -197,7 +198,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 36-39 movdqa %xmm4, %xmm0 - paddd 144+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 144(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm4, %xmm7 palignr $4, %xmm3, %xmm7 @@ -208,7 +209,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 40-43 movdqa %xmm5, %xmm0 - paddd 160+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 160(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm5, %xmm7 palignr $4, %xmm4, %xmm7 @@ -219,7 +220,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 44-47 movdqa %xmm6, %xmm0 - paddd 176+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 176(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm6, %xmm7 palignr $4, %xmm5, %xmm7 @@ -230,7 +231,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 48-51 movdqa %xmm3, %xmm0 - paddd 192+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 192(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm3, %xmm7 palignr $4, %xmm6, %xmm7 @@ -241,7 +242,7 @@ _Transform_Sha256_SSE2_Sha: sha256rnds2 %xmm2, %xmm1 # Rounds: 52-63 movdqa %xmm4, %xmm0 - paddd 208+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 208(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm4, %xmm7 palignr $4, %xmm3, %xmm7 @@ -250,7 +251,7 @@ _Transform_Sha256_SSE2_Sha: pshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 movdqa %xmm5, %xmm0 - paddd 224+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 224(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm5, %xmm7 palignr $4, %xmm4, %xmm7 @@ -259,7 +260,7 @@ _Transform_Sha256_SSE2_Sha: pshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 movdqa %xmm6, %xmm0 - paddd 240+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 240(%rdx), %xmm0 sha256rnds2 %xmm1, %xmm2 pshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 @@ -289,6 +290,7 @@ Transform_Sha256_SSE2_Sha_Len: .p2align 4 _Transform_Sha256_SSE2_Sha_Len: #endif /* __APPLE__ */ + leaq L_sse2_sha256_sha_k(%rip), %rax movdqa L_sse2_sha256_shuf_mask(%rip), %xmm10 movq (%rdi), %xmm1 movq 8(%rdi), %xmm2 @@ -307,14 +309,14 @@ L_sha256_sha_len_sse2_start: movdqa %xmm2, %xmm9 # Rounds: 0-3 movdqa %xmm3, %xmm0 - paddd 0+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd (%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 pshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 # Rounds: 4-7 pshufb %xmm10, %xmm4 movdqa %xmm4, %xmm0 - paddd 16+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 16(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 pshufd $14, %xmm0, %xmm0 sha256msg1 %xmm4, %xmm3 @@ -322,7 +324,7 @@ L_sha256_sha_len_sse2_start: # Rounds: 8-11 pshufb %xmm10, %xmm5 movdqa %xmm5, %xmm0 - paddd 32+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 32(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 pshufd $14, %xmm0, %xmm0 sha256msg1 %xmm5, %xmm4 @@ -330,7 +332,7 @@ L_sha256_sha_len_sse2_start: # Rounds: 12-15 pshufb %xmm10, %xmm6 movdqa %xmm6, %xmm0 - paddd 48+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 48(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm6, %xmm7 palignr $4, %xmm5, %xmm7 @@ -341,7 +343,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 16-19 movdqa %xmm3, %xmm0 - paddd 64+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 64(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm3, %xmm7 palignr $4, %xmm6, %xmm7 @@ -352,7 +354,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 20-23 movdqa %xmm4, %xmm0 - paddd 80+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 80(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm4, %xmm7 palignr $4, %xmm3, %xmm7 @@ -363,7 +365,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 24-27 movdqa %xmm5, %xmm0 - paddd 96+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 96(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm5, %xmm7 palignr $4, %xmm4, %xmm7 @@ -374,7 +376,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 28-31 movdqa %xmm6, %xmm0 - paddd 112+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 112(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm6, %xmm7 palignr $4, %xmm5, %xmm7 @@ -385,7 +387,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 32-35 movdqa %xmm3, %xmm0 - paddd 128+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 128(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm3, %xmm7 palignr $4, %xmm6, %xmm7 @@ -396,7 +398,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 36-39 movdqa %xmm4, %xmm0 - paddd 144+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 144(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm4, %xmm7 palignr $4, %xmm3, %xmm7 @@ -407,7 +409,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 40-43 movdqa %xmm5, %xmm0 - paddd 160+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 160(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm5, %xmm7 palignr $4, %xmm4, %xmm7 @@ -418,7 +420,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 44-47 movdqa %xmm6, %xmm0 - paddd 176+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 176(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm6, %xmm7 palignr $4, %xmm5, %xmm7 @@ -429,7 +431,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 48-51 movdqa %xmm3, %xmm0 - paddd 192+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 192(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm3, %xmm7 palignr $4, %xmm6, %xmm7 @@ -440,7 +442,7 @@ L_sha256_sha_len_sse2_start: sha256rnds2 %xmm2, %xmm1 # Rounds: 52-63 movdqa %xmm4, %xmm0 - paddd 208+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 208(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm4, %xmm7 palignr $4, %xmm3, %xmm7 @@ -449,7 +451,7 @@ L_sha256_sha_len_sse2_start: pshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 movdqa %xmm5, %xmm0 - paddd 224+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 224(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 movdqa %xmm5, %xmm7 palignr $4, %xmm4, %xmm7 @@ -458,7 +460,7 @@ L_sha256_sha_len_sse2_start: pshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 movdqa %xmm6, %xmm0 - paddd 240+L_sse2_sha256_sha_k(%rip), %xmm0 + paddd 240(%rax), %xmm0 sha256rnds2 %xmm1, %xmm2 pshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 @@ -555,7 +557,9 @@ _Transform_Sha256_AVX1: pushq %r13 pushq %r14 pushq %r15 + pushq %rbp subq $0x40, %rsp + leaq L_avx1_sha256_k(%rip), %rbp vmovdqa L_avx1_sha256_flip_mask(%rip), %xmm13 vmovdqa L_avx1_sha256_shuf_00BA(%rip), %xmm11 vmovdqa L_avx1_sha256_shuf_DC00(%rip), %xmm12 @@ -580,12 +584,12 @@ _Transform_Sha256_AVX1: movl %r12d, %edx xorl %r10d, %ebx # set_w_k_xfer_4: 0 - vpaddd 0+L_avx1_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 16+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vpaddd (%rbp), %xmm0, %xmm4 + vpaddd 16(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 32+L_avx1_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 48+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 32(%rbp), %xmm2, %xmm6 + vpaddd 48(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -1213,12 +1217,12 @@ _Transform_Sha256_AVX1: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 4 - vpaddd 64+L_avx1_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 80+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 64(%rbp), %xmm0, %xmm4 + vpaddd 80(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 96+L_avx1_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 112+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 96(%rbp), %xmm2, %xmm6 + vpaddd 112(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -1846,12 +1850,12 @@ _Transform_Sha256_AVX1: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 8 - vpaddd 128+L_avx1_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 144+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 128(%rbp), %xmm0, %xmm4 + vpaddd 144(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 160+L_avx1_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 176+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 160(%rbp), %xmm2, %xmm6 + vpaddd 176(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -2479,12 +2483,12 @@ _Transform_Sha256_AVX1: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 12 - vpaddd 192+L_avx1_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 208+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 192(%rbp), %xmm0, %xmm4 + vpaddd 208(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 224+L_avx1_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 240+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 224(%rbp), %xmm2, %xmm6 + vpaddd 240(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # rnd_all_4: 0-3 @@ -2918,6 +2922,7 @@ _Transform_Sha256_AVX1: xorq %rax, %rax vzeroupper addq $0x40, %rsp + popq %rbp popq %r15 popq %r14 popq %r13 @@ -2946,7 +2951,9 @@ _Transform_Sha256_AVX1_Len: pushq %r15 pushq %rbp movq %rdx, %rbp - subq $0x40, %rsp + subq $0x44, %rsp + movl %ebp, 64(%rsp) + leaq L_avx1_sha256_k(%rip), %rbp vmovdqa L_avx1_sha256_flip_mask(%rip), %xmm13 vmovdqa L_avx1_sha256_shuf_00BA(%rip), %xmm11 vmovdqa L_avx1_sha256_shuf_DC00(%rip), %xmm12 @@ -2973,12 +2980,12 @@ L_sha256_len_avx1_start: movl %r12d, %edx xorl %r10d, %ebx # set_w_k_xfer_4: 0 - vpaddd 0+L_avx1_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 16+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vpaddd (%rbp), %xmm0, %xmm4 + vpaddd 16(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 32+L_avx1_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 48+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 32(%rbp), %xmm2, %xmm6 + vpaddd 48(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -3606,12 +3613,12 @@ L_sha256_len_avx1_start: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 4 - vpaddd 64+L_avx1_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 80+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 64(%rbp), %xmm0, %xmm4 + vpaddd 80(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 96+L_avx1_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 112+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 96(%rbp), %xmm2, %xmm6 + vpaddd 112(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -4239,12 +4246,12 @@ L_sha256_len_avx1_start: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 8 - vpaddd 128+L_avx1_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 144+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 128(%rbp), %xmm0, %xmm4 + vpaddd 144(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 160+L_avx1_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 176+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 160(%rbp), %xmm2, %xmm6 + vpaddd 176(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -4872,12 +4879,12 @@ L_sha256_len_avx1_start: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 12 - vpaddd 192+L_avx1_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 208+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 192(%rbp), %xmm0, %xmm4 + vpaddd 208(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 224+L_avx1_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 240+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 224(%rbp), %xmm2, %xmm6 + vpaddd 240(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # rnd_all_4: 0-3 @@ -5309,7 +5316,7 @@ L_sha256_len_avx1_start: addl 24(%rdi), %r14d addl 28(%rdi), %r15d addq $0x40, %rsi - subl $0x40, %ebp + subl $0x40, 64(%rsp) movl %r8d, (%rdi) movl %r9d, 4(%rdi) movl %r10d, 8(%rdi) @@ -5321,7 +5328,7 @@ L_sha256_len_avx1_start: jnz L_sha256_len_avx1_start xorq %rax, %rax vzeroupper - addq $0x40, %rsp + addq $0x44, %rsp popq %rbp popq %r15 popq %r14 @@ -5407,7 +5414,9 @@ _Transform_Sha256_AVX1_RORX: pushq %r13 pushq %r14 pushq %r15 + pushq %rbp subq $0x40, %rsp + leaq L_avx1_rorx_sha256_k(%rip), %rbp vmovdqa L_avx1_rorx_sha256_flip_mask(%rip), %xmm13 vmovdqa L_avx1_rorx_sha256_shuf_00BA(%rip), %xmm11 vmovdqa L_avx1_rorx_sha256_shuf_DC00(%rip), %xmm12 @@ -5429,12 +5438,12 @@ _Transform_Sha256_AVX1_RORX: movl 24(%rdi), %r14d movl 28(%rdi), %r15d # set_w_k_xfer_4: 0 - vpaddd 0+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 16+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vpaddd (%rbp), %xmm0, %xmm4 + vpaddd 16(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 32+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 48+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 32(%rbp), %xmm2, %xmm6 + vpaddd 48(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) movl %r9d, %ebx @@ -6061,12 +6070,12 @@ _Transform_Sha256_AVX1_RORX: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 4 - vpaddd 64+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 80+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 64(%rbp), %xmm0, %xmm4 + vpaddd 80(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 96+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 112+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 96(%rbp), %xmm2, %xmm6 + vpaddd 112(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -6690,12 +6699,12 @@ _Transform_Sha256_AVX1_RORX: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 8 - vpaddd 128+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 144+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 128(%rbp), %xmm0, %xmm4 + vpaddd 144(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 160+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 176+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 160(%rbp), %xmm2, %xmm6 + vpaddd 176(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -7319,12 +7328,12 @@ _Transform_Sha256_AVX1_RORX: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 12 - vpaddd 192+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 208+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 192(%rbp), %xmm0, %xmm4 + vpaddd 208(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 224+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 240+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 224(%rbp), %xmm2, %xmm6 + vpaddd 240(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) xorl %eax, %eax @@ -7728,6 +7737,7 @@ _Transform_Sha256_AVX1_RORX: xorq %rax, %rax vzeroupper addq $0x40, %rsp + popq %rbp popq %r15 popq %r14 popq %r13 @@ -7756,7 +7766,9 @@ _Transform_Sha256_AVX1_RORX_Len: pushq %r15 pushq %rbp movq %rdx, %rbp - subq $0x40, %rsp + subq $0x44, %rsp + movl %ebp, 64(%rsp) + leaq L_avx1_rorx_sha256_k(%rip), %rbp vmovdqa L_avx1_rorx_sha256_flip_mask(%rip), %xmm13 vmovdqa L_avx1_rorx_sha256_shuf_00BA(%rip), %xmm11 vmovdqa L_avx1_rorx_sha256_shuf_DC00(%rip), %xmm12 @@ -7780,12 +7792,12 @@ L_sha256_len_avx1_len_rorx_start: vpshufb %xmm13, %xmm2, %xmm2 vpshufb %xmm13, %xmm3, %xmm3 # set_w_k_xfer_4: 0 - vpaddd 0+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 16+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vpaddd (%rbp), %xmm0, %xmm4 + vpaddd 16(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 32+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 48+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 32(%rbp), %xmm2, %xmm6 + vpaddd 48(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) movl %r9d, %ebx @@ -8412,12 +8424,12 @@ L_sha256_len_avx1_len_rorx_start: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 4 - vpaddd 64+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 80+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 64(%rbp), %xmm0, %xmm4 + vpaddd 80(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 96+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 112+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 96(%rbp), %xmm2, %xmm6 + vpaddd 112(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -9041,12 +9053,12 @@ L_sha256_len_avx1_len_rorx_start: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 8 - vpaddd 128+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 144+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 128(%rbp), %xmm0, %xmm4 + vpaddd 144(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 160+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 176+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 160(%rbp), %xmm2, %xmm6 + vpaddd 176(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) # msg_sched: 0-3 @@ -9670,12 +9682,12 @@ L_sha256_len_avx1_len_rorx_start: vpaddd %xmm4, %xmm9, %xmm3 # msg_sched done: 12-15 # set_w_k_xfer_4: 12 - vpaddd 192+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 - vpaddd 208+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vpaddd 192(%rbp), %xmm0, %xmm4 + vpaddd 208(%rbp), %xmm1, %xmm5 vmovdqu %xmm4, (%rsp) vmovdqu %xmm5, 16(%rsp) - vpaddd 224+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 - vpaddd 240+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vpaddd 224(%rbp), %xmm2, %xmm6 + vpaddd 240(%rbp), %xmm3, %xmm7 vmovdqu %xmm6, 32(%rsp) vmovdqu %xmm7, 48(%rsp) xorl %eax, %eax @@ -10078,7 +10090,7 @@ L_sha256_len_avx1_len_rorx_start: addl 24(%rdi), %r14d addl 28(%rdi), %r15d addq $0x40, %rsi - subl $0x40, %ebp + subl $0x40, 64(%rsp) movl %r8d, (%rdi) movl %r9d, 4(%rdi) movl %r10d, 8(%rdi) @@ -10090,7 +10102,7 @@ L_sha256_len_avx1_len_rorx_start: jnz L_sha256_len_avx1_len_rorx_start xorq %rax, %rax vzeroupper - addq $0x40, %rsp + addq $0x44, %rsp popq %rbp popq %r15 popq %r14 @@ -10147,6 +10159,7 @@ Transform_Sha256_AVX1_Sha: .p2align 4 _Transform_Sha256_AVX1_Sha: #endif /* __APPLE__ */ + leaq L_avx1_sha256_sha_k(%rip), %rdx vmovdqa L_avx1_sha256_shuf_mask(%rip), %xmm10 vmovq (%rdi), %xmm1 vmovq 8(%rdi), %xmm2 @@ -10162,27 +10175,27 @@ _Transform_Sha256_AVX1_Sha: vmovdqa %xmm1, %xmm8 vmovdqa %xmm2, %xmm9 # Rounds: 0-3 - vpaddd 0+L_avx1_sha256_sha_k(%rip), %xmm3, %xmm0 + vpaddd (%rdx), %xmm3, %xmm0 sha256rnds2 %xmm1, %xmm2 vpshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 # Rounds: 4-7 vpshufb %xmm10, %xmm4, %xmm4 - vpaddd 16+L_avx1_sha256_sha_k(%rip), %xmm4, %xmm0 + vpaddd 16(%rdx), %xmm4, %xmm0 sha256rnds2 %xmm1, %xmm2 vpshufd $14, %xmm0, %xmm0 sha256msg1 %xmm4, %xmm3 sha256rnds2 %xmm2, %xmm1 # Rounds: 8-11 vpshufb %xmm10, %xmm5, %xmm5 - vpaddd 32+L_avx1_sha256_sha_k(%rip), %xmm5, %xmm0 + vpaddd 32(%rdx), %xmm5, %xmm0 sha256rnds2 %xmm1, %xmm2 vpshufd $14, %xmm0, %xmm0 sha256msg1 %xmm5, %xmm4 sha256rnds2 %xmm2, %xmm1 # Rounds: 12-15 vpshufb %xmm10, %xmm6, %xmm6 - vpaddd 48+L_avx1_sha256_sha_k(%rip), %xmm6, %xmm0 + vpaddd 48(%rdx), %xmm6, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm5, %xmm6, %xmm7 vpaddd %xmm7, %xmm3, %xmm3 @@ -10191,7 +10204,7 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm6, %xmm5 sha256rnds2 %xmm2, %xmm1 # Rounds: 16-19 - vpaddd 64+L_avx1_sha256_sha_k(%rip), %xmm3, %xmm0 + vpaddd 64(%rdx), %xmm3, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm6, %xmm3, %xmm7 vpaddd %xmm7, %xmm4, %xmm4 @@ -10200,7 +10213,7 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm3, %xmm6 sha256rnds2 %xmm2, %xmm1 # Rounds: 20-23 - vpaddd 80+L_avx1_sha256_sha_k(%rip), %xmm4, %xmm0 + vpaddd 80(%rdx), %xmm4, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm3, %xmm4, %xmm7 vpaddd %xmm7, %xmm5, %xmm5 @@ -10209,7 +10222,7 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm4, %xmm3 sha256rnds2 %xmm2, %xmm1 # Rounds: 24-27 - vpaddd 96+L_avx1_sha256_sha_k(%rip), %xmm5, %xmm0 + vpaddd 96(%rdx), %xmm5, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm4, %xmm5, %xmm7 vpaddd %xmm7, %xmm6, %xmm6 @@ -10218,7 +10231,7 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm5, %xmm4 sha256rnds2 %xmm2, %xmm1 # Rounds: 28-31 - vpaddd 112+L_avx1_sha256_sha_k(%rip), %xmm6, %xmm0 + vpaddd 112(%rdx), %xmm6, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm5, %xmm6, %xmm7 vpaddd %xmm7, %xmm3, %xmm3 @@ -10227,7 +10240,7 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm6, %xmm5 sha256rnds2 %xmm2, %xmm1 # Rounds: 32-35 - vpaddd 128+L_avx1_sha256_sha_k(%rip), %xmm3, %xmm0 + vpaddd 128(%rdx), %xmm3, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm6, %xmm3, %xmm7 vpaddd %xmm7, %xmm4, %xmm4 @@ -10236,7 +10249,7 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm3, %xmm6 sha256rnds2 %xmm2, %xmm1 # Rounds: 36-39 - vpaddd 144+L_avx1_sha256_sha_k(%rip), %xmm4, %xmm0 + vpaddd 144(%rdx), %xmm4, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm3, %xmm4, %xmm7 vpaddd %xmm7, %xmm5, %xmm5 @@ -10245,7 +10258,7 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm4, %xmm3 sha256rnds2 %xmm2, %xmm1 # Rounds: 40-43 - vpaddd 160+L_avx1_sha256_sha_k(%rip), %xmm5, %xmm0 + vpaddd 160(%rdx), %xmm5, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm4, %xmm5, %xmm7 vpaddd %xmm7, %xmm6, %xmm6 @@ -10254,7 +10267,7 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm5, %xmm4 sha256rnds2 %xmm2, %xmm1 # Rounds: 44-47 - vpaddd 176+L_avx1_sha256_sha_k(%rip), %xmm6, %xmm0 + vpaddd 176(%rdx), %xmm6, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm5, %xmm6, %xmm7 vpaddd %xmm7, %xmm3, %xmm3 @@ -10263,7 +10276,7 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm6, %xmm5 sha256rnds2 %xmm2, %xmm1 # Rounds: 48-51 - vpaddd 192+L_avx1_sha256_sha_k(%rip), %xmm3, %xmm0 + vpaddd 192(%rdx), %xmm3, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm6, %xmm3, %xmm7 vpaddd %xmm7, %xmm4, %xmm4 @@ -10272,21 +10285,21 @@ _Transform_Sha256_AVX1_Sha: sha256msg1 %xmm3, %xmm6 sha256rnds2 %xmm2, %xmm1 # Rounds: 52-63 - vpaddd 208+L_avx1_sha256_sha_k(%rip), %xmm4, %xmm0 + vpaddd 208(%rdx), %xmm4, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm3, %xmm4, %xmm7 vpaddd %xmm7, %xmm5, %xmm5 sha256msg2 %xmm4, %xmm5 vpshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 - vpaddd 224+L_avx1_sha256_sha_k(%rip), %xmm5, %xmm0 + vpaddd 224(%rdx), %xmm5, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm4, %xmm5, %xmm7 vpaddd %xmm7, %xmm6, %xmm6 sha256msg2 %xmm5, %xmm6 vpshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 - vpaddd 240+L_avx1_sha256_sha_k(%rip), %xmm6, %xmm0 + vpaddd 240(%rdx), %xmm6, %xmm0 sha256rnds2 %xmm1, %xmm2 vpshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 @@ -10316,6 +10329,7 @@ Transform_Sha256_AVX1_Sha_Len: .p2align 4 _Transform_Sha256_AVX1_Sha_Len: #endif /* __APPLE__ */ + leaq L_avx1_sha256_sha_k(%rip), %rax vmovdqa L_avx1_sha256_shuf_mask(%rip), %xmm10 vmovq (%rdi), %xmm1 vmovq 8(%rdi), %xmm2 @@ -10333,27 +10347,27 @@ L_sha256_sha_len_avx1_start: vmovdqa %xmm1, %xmm8 vmovdqa %xmm2, %xmm9 # Rounds: 0-3 - vpaddd 0+L_avx1_sha256_sha_k(%rip), %xmm3, %xmm0 + vpaddd (%rax), %xmm3, %xmm0 sha256rnds2 %xmm1, %xmm2 vpshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 # Rounds: 4-7 vpshufb %xmm10, %xmm4, %xmm4 - vpaddd 16+L_avx1_sha256_sha_k(%rip), %xmm4, %xmm0 + vpaddd 16(%rax), %xmm4, %xmm0 sha256rnds2 %xmm1, %xmm2 vpshufd $14, %xmm0, %xmm0 sha256msg1 %xmm4, %xmm3 sha256rnds2 %xmm2, %xmm1 # Rounds: 8-11 vpshufb %xmm10, %xmm5, %xmm5 - vpaddd 32+L_avx1_sha256_sha_k(%rip), %xmm5, %xmm0 + vpaddd 32(%rax), %xmm5, %xmm0 sha256rnds2 %xmm1, %xmm2 vpshufd $14, %xmm0, %xmm0 sha256msg1 %xmm5, %xmm4 sha256rnds2 %xmm2, %xmm1 # Rounds: 12-15 vpshufb %xmm10, %xmm6, %xmm6 - vpaddd 48+L_avx1_sha256_sha_k(%rip), %xmm6, %xmm0 + vpaddd 48(%rax), %xmm6, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm5, %xmm6, %xmm7 vpaddd %xmm7, %xmm3, %xmm3 @@ -10362,7 +10376,7 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm6, %xmm5 sha256rnds2 %xmm2, %xmm1 # Rounds: 16-19 - vpaddd 64+L_avx1_sha256_sha_k(%rip), %xmm3, %xmm0 + vpaddd 64(%rax), %xmm3, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm6, %xmm3, %xmm7 vpaddd %xmm7, %xmm4, %xmm4 @@ -10371,7 +10385,7 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm3, %xmm6 sha256rnds2 %xmm2, %xmm1 # Rounds: 20-23 - vpaddd 80+L_avx1_sha256_sha_k(%rip), %xmm4, %xmm0 + vpaddd 80(%rax), %xmm4, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm3, %xmm4, %xmm7 vpaddd %xmm7, %xmm5, %xmm5 @@ -10380,7 +10394,7 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm4, %xmm3 sha256rnds2 %xmm2, %xmm1 # Rounds: 24-27 - vpaddd 96+L_avx1_sha256_sha_k(%rip), %xmm5, %xmm0 + vpaddd 96(%rax), %xmm5, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm4, %xmm5, %xmm7 vpaddd %xmm7, %xmm6, %xmm6 @@ -10389,7 +10403,7 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm5, %xmm4 sha256rnds2 %xmm2, %xmm1 # Rounds: 28-31 - vpaddd 112+L_avx1_sha256_sha_k(%rip), %xmm6, %xmm0 + vpaddd 112(%rax), %xmm6, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm5, %xmm6, %xmm7 vpaddd %xmm7, %xmm3, %xmm3 @@ -10398,7 +10412,7 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm6, %xmm5 sha256rnds2 %xmm2, %xmm1 # Rounds: 32-35 - vpaddd 128+L_avx1_sha256_sha_k(%rip), %xmm3, %xmm0 + vpaddd 128(%rax), %xmm3, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm6, %xmm3, %xmm7 vpaddd %xmm7, %xmm4, %xmm4 @@ -10407,7 +10421,7 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm3, %xmm6 sha256rnds2 %xmm2, %xmm1 # Rounds: 36-39 - vpaddd 144+L_avx1_sha256_sha_k(%rip), %xmm4, %xmm0 + vpaddd 144(%rax), %xmm4, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm3, %xmm4, %xmm7 vpaddd %xmm7, %xmm5, %xmm5 @@ -10416,7 +10430,7 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm4, %xmm3 sha256rnds2 %xmm2, %xmm1 # Rounds: 40-43 - vpaddd 160+L_avx1_sha256_sha_k(%rip), %xmm5, %xmm0 + vpaddd 160(%rax), %xmm5, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm4, %xmm5, %xmm7 vpaddd %xmm7, %xmm6, %xmm6 @@ -10425,7 +10439,7 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm5, %xmm4 sha256rnds2 %xmm2, %xmm1 # Rounds: 44-47 - vpaddd 176+L_avx1_sha256_sha_k(%rip), %xmm6, %xmm0 + vpaddd 176(%rax), %xmm6, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm5, %xmm6, %xmm7 vpaddd %xmm7, %xmm3, %xmm3 @@ -10434,7 +10448,7 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm6, %xmm5 sha256rnds2 %xmm2, %xmm1 # Rounds: 48-51 - vpaddd 192+L_avx1_sha256_sha_k(%rip), %xmm3, %xmm0 + vpaddd 192(%rax), %xmm3, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm6, %xmm3, %xmm7 vpaddd %xmm7, %xmm4, %xmm4 @@ -10443,21 +10457,21 @@ L_sha256_sha_len_avx1_start: sha256msg1 %xmm3, %xmm6 sha256rnds2 %xmm2, %xmm1 # Rounds: 52-63 - vpaddd 208+L_avx1_sha256_sha_k(%rip), %xmm4, %xmm0 + vpaddd 208(%rax), %xmm4, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm3, %xmm4, %xmm7 vpaddd %xmm7, %xmm5, %xmm5 sha256msg2 %xmm4, %xmm5 vpshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 - vpaddd 224+L_avx1_sha256_sha_k(%rip), %xmm5, %xmm0 + vpaddd 224(%rax), %xmm5, %xmm0 sha256rnds2 %xmm1, %xmm2 vpalignr $4, %xmm4, %xmm5, %xmm7 vpaddd %xmm7, %xmm6, %xmm6 sha256msg2 %xmm5, %xmm6 vpshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 - vpaddd 240+L_avx1_sha256_sha_k(%rip), %xmm6, %xmm0 + vpaddd 240(%rax), %xmm6, %xmm0 sha256rnds2 %xmm1, %xmm2 vpshufd $14, %xmm0, %xmm0 sha256rnds2 %xmm2, %xmm1 @@ -10574,7 +10588,9 @@ _Transform_Sha256_AVX2: pushq %r13 pushq %r14 pushq %r15 + pushq %rbp subq $0x200, %rsp + leaq L_avx2_sha256_k(%rip), %rbp vmovdqa L_avx2_sha256_flip_mask(%rip), %xmm13 vmovdqa L_avx2_sha256_shuf_00BA(%rip), %ymm11 vmovdqa L_avx2_sha256_shuf_DC00(%rip), %ymm12 @@ -10599,12 +10615,12 @@ _Transform_Sha256_AVX2: movl %r12d, %edx xorl %r10d, %ebx # set_w_k_xfer_4: 0 - vpaddd 0+L_avx2_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 32+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vpaddd (%rbp), %ymm0, %ymm4 + vpaddd 32(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, (%rsp) vmovdqu %ymm5, 32(%rsp) - vpaddd 64+L_avx2_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 96+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 64(%rbp), %ymm2, %ymm4 + vpaddd 96(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 64(%rsp) vmovdqu %ymm5, 96(%rsp) # msg_sched: 0-3 @@ -11232,12 +11248,12 @@ _Transform_Sha256_AVX2: vpaddd %ymm4, %ymm9, %ymm3 # msg_sched done: 24-27 # set_w_k_xfer_4: 4 - vpaddd 128+L_avx2_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 160+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vpaddd 128(%rbp), %ymm0, %ymm4 + vpaddd 160(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, 128(%rsp) vmovdqu %ymm5, 160(%rsp) - vpaddd 192+L_avx2_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 224+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 192(%rbp), %ymm2, %ymm4 + vpaddd 224(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 192(%rsp) vmovdqu %ymm5, 224(%rsp) # msg_sched: 32-35 @@ -11865,12 +11881,12 @@ _Transform_Sha256_AVX2: vpaddd %ymm4, %ymm9, %ymm3 # msg_sched done: 56-59 # set_w_k_xfer_4: 8 - vpaddd 256+L_avx2_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 288+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vpaddd 256(%rbp), %ymm0, %ymm4 + vpaddd 288(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, 256(%rsp) vmovdqu %ymm5, 288(%rsp) - vpaddd 320+L_avx2_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 352+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 320(%rbp), %ymm2, %ymm4 + vpaddd 352(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 320(%rsp) vmovdqu %ymm5, 352(%rsp) # msg_sched: 64-67 @@ -12498,12 +12514,12 @@ _Transform_Sha256_AVX2: vpaddd %ymm4, %ymm9, %ymm3 # msg_sched done: 88-91 # set_w_k_xfer_4: 12 - vpaddd 384+L_avx2_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 416+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vpaddd 384(%rbp), %ymm0, %ymm4 + vpaddd 416(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, 384(%rsp) vmovdqu %ymm5, 416(%rsp) - vpaddd 448+L_avx2_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 480+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 448(%rbp), %ymm2, %ymm4 + vpaddd 480(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 448(%rsp) vmovdqu %ymm5, 480(%rsp) # rnd_all_4: 24-27 @@ -12937,6 +12953,7 @@ _Transform_Sha256_AVX2: xorq %rax, %rax vzeroupper addq $0x200, %rsp + popq %rbp popq %r15 popq %r14 popq %r13 @@ -12965,8 +12982,9 @@ _Transform_Sha256_AVX2_Len: pushq %r15 pushq %rbp movq %rdx, %rbp - subq $0x200, %rsp + subq $0x204, %rsp testb $0x40, %bpl + movl %ebp, 512(%rsp) je L_sha256_len_avx2_block vmovdqu (%rsi), %ymm0 vmovdqu 32(%rsi), %ymm1 @@ -12978,9 +12996,10 @@ _Transform_Sha256_AVX2_Len: call _Transform_Sha256_AVX2 #endif /* __APPLE__ */ addq $0x40, %rsi - subl $0x40, %ebp + subl $0x40, 512(%rsp) jz L_sha256_len_avx2_done L_sha256_len_avx2_block: + leaq L_avx2_sha256_k(%rip), %rbp vmovdqa L_avx2_sha256_flip_mask(%rip), %ymm13 vmovdqa L_avx2_sha256_shuf_00BA(%rip), %ymm11 vmovdqa L_avx2_sha256_shuf_DC00(%rip), %ymm12 @@ -13015,12 +13034,12 @@ L_sha256_len_avx2_start: movl %r12d, %edx xorl %r10d, %ebx # set_w_k_xfer_4: 0 - vpaddd 0+L_avx2_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 32+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vpaddd (%rbp), %ymm0, %ymm4 + vpaddd 32(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, (%rsp) vmovdqu %ymm5, 32(%rsp) - vpaddd 64+L_avx2_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 96+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 64(%rbp), %ymm2, %ymm4 + vpaddd 96(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 64(%rsp) vmovdqu %ymm5, 96(%rsp) # msg_sched: 0-3 @@ -13648,12 +13667,12 @@ L_sha256_len_avx2_start: vpaddd %ymm4, %ymm9, %ymm3 # msg_sched done: 24-27 # set_w_k_xfer_4: 4 - vpaddd 128+L_avx2_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 160+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vpaddd 128(%rbp), %ymm0, %ymm4 + vpaddd 160(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, 128(%rsp) vmovdqu %ymm5, 160(%rsp) - vpaddd 192+L_avx2_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 224+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 192(%rbp), %ymm2, %ymm4 + vpaddd 224(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 192(%rsp) vmovdqu %ymm5, 224(%rsp) # msg_sched: 32-35 @@ -14281,12 +14300,12 @@ L_sha256_len_avx2_start: vpaddd %ymm4, %ymm9, %ymm3 # msg_sched done: 56-59 # set_w_k_xfer_4: 8 - vpaddd 256+L_avx2_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 288+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vpaddd 256(%rbp), %ymm0, %ymm4 + vpaddd 288(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, 256(%rsp) vmovdqu %ymm5, 288(%rsp) - vpaddd 320+L_avx2_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 352+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 320(%rbp), %ymm2, %ymm4 + vpaddd 352(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 320(%rsp) vmovdqu %ymm5, 352(%rsp) # msg_sched: 64-67 @@ -14914,12 +14933,12 @@ L_sha256_len_avx2_start: vpaddd %ymm4, %ymm9, %ymm3 # msg_sched done: 88-91 # set_w_k_xfer_4: 12 - vpaddd 384+L_avx2_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 416+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vpaddd 384(%rbp), %ymm0, %ymm4 + vpaddd 416(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, 384(%rsp) vmovdqu %ymm5, 416(%rsp) - vpaddd 448+L_avx2_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 480+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 448(%rbp), %ymm2, %ymm4 + vpaddd 480(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 448(%rsp) vmovdqu %ymm5, 480(%rsp) # rnd_all_4: 24-27 @@ -17050,7 +17069,7 @@ L_sha256_len_avx2_start: addl 24(%rdi), %r14d addl 28(%rdi), %r15d addq $0x80, %rsi - subl $0x80, %ebp + subl $0x80, 512(%rsp) movl %r8d, (%rdi) movl %r9d, 4(%rdi) movl %r10d, 8(%rdi) @@ -17063,7 +17082,7 @@ L_sha256_len_avx2_start: L_sha256_len_avx2_done: xorq %rax, %rax vzeroupper - addq $0x200, %rsp + addq $0x204, %rsp popq %rbp popq %r15 popq %r14 @@ -17168,7 +17187,9 @@ _Transform_Sha256_AVX2_RORX: pushq %r13 pushq %r14 pushq %r15 + pushq %rbp subq $0x200, %rsp + leaq L_avx2_rorx_sha256_k(%rip), %rbp vmovdqa L_avx2_rorx_sha256_flip_mask(%rip), %xmm13 vmovdqa L_avx2_rorx_sha256_shuf_00BA(%rip), %ymm11 vmovdqa L_avx2_rorx_sha256_shuf_DC00(%rip), %ymm12 @@ -17177,16 +17198,16 @@ _Transform_Sha256_AVX2_RORX: vmovdqu 16(%rsi), %xmm1 vpshufb %xmm13, %xmm0, %xmm0 vpshufb %xmm13, %xmm1, %xmm1 - vpaddd 0+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 32+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm5 + vpaddd (%rbp), %ymm0, %ymm4 + vpaddd 32(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, (%rsp) vmovdqu %ymm5, 32(%rsp) vmovdqu 32(%rsi), %xmm2 vmovdqu 48(%rsi), %xmm3 vpshufb %xmm13, %xmm2, %xmm2 vpshufb %xmm13, %xmm3, %xmm3 - vpaddd 64+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 96+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 64(%rbp), %ymm2, %ymm4 + vpaddd 96(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 64(%rsp) vmovdqu %ymm5, 96(%rsp) movl (%rdi), %r8d @@ -17349,7 +17370,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 128+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 128(%rbp), %ymm0, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -17508,7 +17529,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 160+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + vpaddd 160(%rbp), %ymm1, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -17667,7 +17688,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 192+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 192(%rbp), %ymm2, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -17826,7 +17847,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 224+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + vpaddd 224(%rbp), %ymm3, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -17985,7 +18006,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 256+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 256(%rbp), %ymm0, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -18144,7 +18165,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 288+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + vpaddd 288(%rbp), %ymm1, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -18303,7 +18324,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 320+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 320(%rbp), %ymm2, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -18462,7 +18483,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 352+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + vpaddd 352(%rbp), %ymm3, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -18621,7 +18642,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 384+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 384(%rbp), %ymm0, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -18780,7 +18801,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 416+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + vpaddd 416(%rbp), %ymm1, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -18939,7 +18960,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 448+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 448(%rbp), %ymm2, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -19098,7 +19119,7 @@ _Transform_Sha256_AVX2_RORX: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 480+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + vpaddd 480(%rbp), %ymm3, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -19506,6 +19527,7 @@ _Transform_Sha256_AVX2_RORX: xorq %rax, %rax vzeroupper addq $0x200, %rsp + popq %rbp popq %r15 popq %r14 popq %r13 @@ -19534,8 +19556,9 @@ _Transform_Sha256_AVX2_RORX_Len: pushq %r15 pushq %rbp movq %rdx, %rbp - subq $0x200, %rsp + subq $0x204, %rsp testb $0x40, %bpl + movl %ebp, 512(%rsp) je L_sha256_len_avx2_rorx_block vmovdqu (%rsi), %ymm0 vmovdqu 32(%rsi), %ymm1 @@ -19547,9 +19570,10 @@ _Transform_Sha256_AVX2_RORX_Len: call _Transform_Sha256_AVX2_RORX #endif /* __APPLE__ */ addq $0x40, %rsi - subl $0x40, %ebp + subl $0x40, 512(%rsp) jz L_sha256_len_avx2_rorx_done L_sha256_len_avx2_rorx_block: + leaq L_avx2_rorx_sha256_k(%rip), %rbp vmovdqa L_avx2_rorx_sha256_flip_mask(%rip), %ymm13 vmovdqa L_avx2_rorx_sha256_shuf_00BA(%rip), %ymm11 vmovdqa L_avx2_rorx_sha256_shuf_DC00(%rip), %ymm12 @@ -19570,8 +19594,8 @@ L_sha256_len_avx2_rorx_start: vinserti128 $0x01, 80(%rsi), %ymm1, %ymm1 vpshufb %ymm13, %ymm0, %ymm0 vpshufb %ymm13, %ymm1, %ymm1 - vpaddd 0+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 - vpaddd 32+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm5 + vpaddd (%rbp), %ymm0, %ymm4 + vpaddd 32(%rbp), %ymm1, %ymm5 vmovdqu %ymm4, (%rsp) vmovdqu %ymm5, 32(%rsp) vmovdqu 32(%rsi), %xmm2 @@ -19580,8 +19604,8 @@ L_sha256_len_avx2_rorx_start: vinserti128 $0x01, 112(%rsi), %ymm3, %ymm3 vpshufb %ymm13, %ymm2, %ymm2 vpshufb %ymm13, %ymm3, %ymm3 - vpaddd 64+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 - vpaddd 96+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm5 + vpaddd 64(%rbp), %ymm2, %ymm4 + vpaddd 96(%rbp), %ymm3, %ymm5 vmovdqu %ymm4, 64(%rsp) vmovdqu %ymm5, 96(%rsp) movl %r9d, %ebx @@ -19736,7 +19760,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 128+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 128(%rbp), %ymm0, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -19895,7 +19919,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 160+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + vpaddd 160(%rbp), %ymm1, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -20054,7 +20078,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 192+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 192(%rbp), %ymm2, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -20213,7 +20237,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 224+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + vpaddd 224(%rbp), %ymm3, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -20372,7 +20396,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 256+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 256(%rbp), %ymm0, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -20531,7 +20555,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 288+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + vpaddd 288(%rbp), %ymm1, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -20690,7 +20714,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 320+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 320(%rbp), %ymm2, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -20849,7 +20873,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 352+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + vpaddd 352(%rbp), %ymm3, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -21008,7 +21032,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 384+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 384(%rbp), %ymm0, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -21167,7 +21191,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 416+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + vpaddd 416(%rbp), %ymm1, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -21326,7 +21350,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r12d, %r8d movl %r14d, %ebx - vpaddd 448+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 448(%rbp), %ymm2, %ymm4 # rnd_1: 6 - 6 xorl %r13d, %ebx addl %edx, %r12d @@ -21485,7 +21509,7 @@ L_sha256_len_avx2_rorx_start: xorl %ecx, %edx addl %r8d, %r12d movl %r10d, %ebx - vpaddd 480+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + vpaddd 480(%rbp), %ymm3, %ymm4 # rnd_1: 6 - 6 xorl %r9d, %ebx addl %edx, %r8d @@ -23448,7 +23472,7 @@ L_sha256_len_avx2_rorx_start: addl 20(%rdi), %r13d addl 24(%rdi), %r14d addl 28(%rdi), %r15d - subl $0x80, %ebp + subl $0x80, 512(%rsp) movl %r8d, (%rdi) movl %r9d, 4(%rdi) movl %r10d, 8(%rdi) @@ -23461,7 +23485,7 @@ L_sha256_len_avx2_rorx_start: L_sha256_len_avx2_rorx_done: xorq %rax, %rax vzeroupper - addq $0x200, %rsp + addq $0x204, %rsp popq %rbp popq %r15 popq %r14 diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c index 096566d282..14f304fa3a 100644 --- a/wolfcrypt/src/sha3.c +++ b/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 @@ -50,6 +50,14 @@ #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) @@ -58,9 +66,16 @@ 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 +629,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 +669,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 +693,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 +702,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 +714,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 +758,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 +778,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 +787,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; } @@ -1311,6 +1356,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 +1372,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 +1389,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 +1510,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 +1527,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/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index 91bf1e5b3f..8ee668f6f5 100644 --- a/wolfcrypt/src/sha512.c +++ b/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)) @@ -196,6 +205,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 +233,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 +284,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 +337,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 +464,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 +687,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 +699,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 +720,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 +959,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) || \ @@ -794,7 +998,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 +1032,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); @@ -949,7 +1166,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 +1216,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 +1239,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); @@ -1217,15 +1446,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, @@ -1318,6 +1546,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. @@ -1460,11 +1698,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); diff --git a/wolfcrypt/src/sphincs.c b/wolfcrypt/src/sphincs.c index a0196ce395..6556fdb5dc 100644 --- a/wolfcrypt/src/sphincs.c +++ b/wolfcrypt/src/sphincs.c @@ -952,7 +952,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/wolfcrypt/src/wc_kyber.c b/wolfcrypt/src/wc_kyber.c index b0b358f07a..5493c9e617 100644 --- a/wolfcrypt/src/wc_kyber.c +++ b/wolfcrypt/src/wc_kyber.c @@ -203,7 +203,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 +364,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 +528,7 @@ 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; + unsigned int ctSz = 0; /* Validate parameters. */ if ((key == NULL) || (ct == NULL) || (ss == NULL) || (rand == NULL)) { @@ -636,7 +636,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; @@ -741,9 +741,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 diff --git a/wolfcrypt/src/wc_kyber_poly.c b/wolfcrypt/src/wc_kyber_poly.c index fe140f402f..a95d812db8 100644 --- a/wolfcrypt/src/wc_kyber_poly.c +++ b/wolfcrypt/src/wc_kyber_poly.c @@ -50,7 +50,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) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index feab257fb6..d7589fc8b4 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1,6 +1,6 @@ /* test.c * - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -257,6 +257,7 @@ const byte const_byte_array[] = "A+Gd\0\0\0"; #include #include #include +#include #include #include #if !defined(WC_NO_RNG) @@ -518,6 +519,16 @@ static wc_test_ret_t hkdf_test(void); #else WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void); #endif +#endif /* HAVE_HKDF && ! NO_HMAC */ +#ifdef WOLFSSL_HAVE_PRF +#if defined(HAVE_HKDF) && !defined(NO_HMAC) +#ifdef WOLFSSL_BASE16 +WOLFSSL_TEST_SUBROUTINE wc_test_ret_t tls12_kdf_test(void); +#endif /* WOLFSSL_BASE16 */ +#endif /* WOLFSSL_HAVE_HKDF && !NO_HMAC */ +#endif /* WOLFSSL_HAVE_PRF */ +#if defined(WOLFSSL_HAVE_PRF) && !defined(NO_HMAC) && defined(WOLFSSL_SHA384) +WOLFSSL_TEST_SUBROUTINE wc_test_ret_t prf_test(void); #endif WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sshkdf_test(void); #ifdef WOLFSSL_TLS13 @@ -628,7 +639,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void); #endif #if defined(WOLFSSL_HAVE_LMS) #if !defined(WOLFSSL_SMALL_STACK) - #if defined(WOLFSSL_WC_LMS) && (LMS_MAX_HEIGHT >= 10) + #if (defined(WOLFSSL_WC_LMS) && (LMS_MAX_HEIGHT >= 10)) || \ + defined(HAVE_LIBLMS) WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test_verify_only(void); #endif #endif @@ -985,6 +997,10 @@ wc_test_ret_t wolfcrypt_test(void* args) heap_baselineBytes = wolfCrypt_heap_peakBytes_checkpoint(); #endif +#ifdef WC_RNG_SEED_CB + wc_SetSeed_Cb(wc_GenerateSeed); +#endif + printf("------------------------------------------------------------------------------\n"); printf(" wolfSSL version %s\n", LIBWOLFSSL_VERSION_STRING); #ifdef WOLF_CRYPTO_CB @@ -1051,6 +1067,10 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #if defined(HAVE_FIPS) && !defined(WOLFSSL_LINUXKM) wolfCrypt_SetCb_fips(myFipsCb); + #if FIPS_VERSION3_GE(6,0,0) + printf("FIPS module version in use: %s\n", + wolfCrypt_GetVersion_fips()); + #endif #endif #if !defined(NO_BIG_INT) @@ -1361,6 +1381,28 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ PRIVATE_KEY_LOCK(); #endif /* WOLFSSL_WOLFSSH */ +#if defined(WOLFSSL_HAVE_PRF) && !defined(NO_HMAC) && defined(WOLFSSL_SHA384) + PRIVATE_KEY_UNLOCK(); + if ( (ret = prf_test()) != 0) + TEST_FAIL("PRF test failed!\n", ret); + else + TEST_PASS("PRF test passed!\n"); + PRIVATE_KEY_LOCK(); +#endif + +#ifdef WOLFSSL_HAVE_PRF +#if defined (HAVE_HKDF) && !defined(NO_HMAC) +#ifdef WOLFSSL_BASE16 + PRIVATE_KEY_UNLOCK(); + if ( (ret = tls12_kdf_test()) != 0) + TEST_FAIL("TLSv1.2 KDF test failed!\n", ret); + else + TEST_PASS("TLSv1.2 KDF test passed!\n"); + PRIVATE_KEY_LOCK(); +#endif /* WOLFSSL_BASE16 */ +#endif /* WOLFSSL_HAVE_HKDF && !NO_HMAC */ +#endif /* WOLFSSL_HAVE_PRF */ + #ifdef WOLFSSL_TLS13 PRIVATE_KEY_UNLOCK(); if ( (ret = tls13_kdf_test()) != 0) @@ -1385,10 +1427,12 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #if defined(WC_SRTP_KDF) + PRIVATE_KEY_UNLOCK(); if ( (ret = srtpkdf_test()) != 0) TEST_FAIL("SRTP KDF test failed!\n", ret); else TEST_PASS("SRTP KDF test passed!\n"); + PRIVATE_KEY_LOCK(); #endif #if defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128) && \ @@ -1620,10 +1664,12 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifndef NO_PWDBASED + PRIVATE_KEY_UNLOCK(); if ( (ret = pwdbased_test()) != 0) TEST_FAIL("PWDBASED test failed!\n", ret); else TEST_PASS("PWDBASED test passed!\n"); + PRIVATE_KEY_LOCK(); #endif #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) @@ -1713,10 +1759,12 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifdef HAVE_ED25519 + PRIVATE_KEY_UNLOCK(); if ( (ret = ed25519_test()) != 0) TEST_FAIL("ED25519 test failed!\n", ret); else TEST_PASS("ED25519 test passed!\n"); + PRIVATE_KEY_LOCK(); #endif #ifdef HAVE_CURVE448 @@ -1727,10 +1775,12 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifdef HAVE_ED448 + PRIVATE_KEY_UNLOCK(); if ( (ret = ed448_test()) != 0) TEST_FAIL("ED448 test failed!\n", ret); else TEST_PASS("ED448 test passed!\n"); + PRIVATE_KEY_LOCK(); #endif #ifdef WOLFSSL_HAVE_KYBER @@ -1758,7 +1808,8 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #if defined(WOLFSSL_HAVE_LMS) #if !defined(WOLFSSL_SMALL_STACK) - #if defined(WOLFSSL_WC_LMS) && (LMS_MAX_HEIGHT >= 10) + #if (defined(WOLFSSL_WC_LMS) && (LMS_MAX_HEIGHT >= 10)) || \ + defined(HAVE_LIBLMS) if ( (ret = lms_test_verify_only()) != 0) TEST_FAIL("LMS Vfy test failed!\n", ret); else @@ -1871,9 +1922,9 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #if !defined(NO_ASN) && !defined(NO_ASN_TIME) if ( (ret = time_test()) != 0) - TEST_FAIL("time test failed!\n", ret); + TEST_FAIL("time test failed!\n", ret); else - TEST_PASS("time test passed!\n"); + TEST_PASS("time test passed!\n"); #endif #if defined(__INCLUDE_NUTTX_CONFIG_H) @@ -2049,10 +2100,6 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ printf("Math: %s\n", wc_GetMathInfo()); #endif -#ifdef WC_RNG_SEED_CB - wc_SetSeed_Cb(wc_GenerateSeed); -#endif - #ifdef HAVE_STACK_SIZE StackSizeCheck(&args, wolfcrypt_test); #else @@ -2125,7 +2172,11 @@ static wc_test_ret_t _SaveDerAndPem(const byte* der, int derSz, #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) XFILE pemFile; #endif + #ifndef WOLFSSL_NO_MALLOC byte* pem; + #else + byte pem[1024]; + #endif int pemSz; /* calculate PEM size */ @@ -2133,10 +2184,15 @@ static wc_test_ret_t _SaveDerAndPem(const byte* der, int derSz, if (pemSz < 0) { return WC_TEST_RET_ENC(calling_line, 2, WC_TEST_RET_TAG_I); } + #ifndef WOLFSSL_NO_MALLOC pem = (byte*)XMALLOC(pemSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { return WC_TEST_RET_ENC(calling_line, 3, WC_TEST_RET_TAG_I); } + #else + if (pemSz > (int)sizeof(pem)) + return BAD_FUNC_ARG; + #endif /* Convert to PEM */ pemSz = wc_DerToPem(der, derSz, pem, pemSz, pemType); if (pemSz < 0) { @@ -2193,9 +2249,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t error_test(void) int i; int j = 0; /* Values that are not or no longer error codes. */ - int missing[] = { -124, -128, -129, -159, -163, -164, - -165, -166, -167, -168, -169, -233, 0 }; - WOLFSSL_ENTER("error_test !NO_ERROR_STRINGS"); + int missing[] = { -124, -166, -167, -168, -169, 0 }; /* Check that all errors have a string and it's the same through the two * APIs. Check that the values that are not errors map to the unknown @@ -2438,8 +2492,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t asn_test(void) { wc_test_ret_t ret; /* ASN1 encoded date buffer */ - WOLFSSL_SMALL_STACK_STATIC const byte dateBuf[] = {0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x31, 0x31, - 0x32, 0x30, 0x30, 0x37, 0x33, 0x37, 0x5a}; + WOLFSSL_SMALL_STACK_STATIC const byte dateBuf[] = { + 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x31, 0x31, + 0x32, 0x30, 0x30, 0x37, 0x33, 0x37, 0x5a + }; byte format; int length; const byte* datePart; @@ -5742,16 +5798,22 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_md5_test(void) { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Jefe", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" }; - testVector a, b, c; - testVector test_hmac[3]; + testVector a, b, c, d; + testVector test_hmac[4]; wc_test_ret_t ret; int times = sizeof(test_hmac) / sizeof(testVector), i; WOLFSSL_ENTER("hmac_md5_test"); + /* Following test vectors are from RFC 2202 section 2 */ a.input = "Hi There"; a.output = "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc" "\x9d"; @@ -5773,9 +5835,17 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_md5_test(void) c.inLen = XSTRLEN(c.input); c.outLen = WC_MD5_DIGEST_SIZE; + d.input = "Test Using Larger Than Block-Size Key - Hash Key First"; + d.output = "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0" + "\xcd"; + d.inLen = XSTRLEN(d.input); + d.outLen = WC_MD5_DIGEST_SIZE; + + test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; + test_hmac[3] = d; for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) @@ -5827,16 +5897,22 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha_test(void) "\x0b\x0b\x0b", "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA" + "\xAA\xAA\xAA", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" }; - testVector a, b, c; - testVector test_hmac[3]; + testVector a, b, c, d; + testVector test_hmac[4]; wc_test_ret_t ret; int times = sizeof(test_hmac) / sizeof(testVector), i; WOLFSSL_ENTER("hmac_sha_test"); + /* Following test vectors are from RFC 2202 section 3 */ a.input = "Hi There"; a.output = "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c" "\x8e\xf1\x46\xbe\x00"; @@ -5858,12 +5934,22 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha_test(void) c.inLen = XSTRLEN(c.input); c.outLen = WC_SHA_DIGEST_SIZE; + d.input = "Test Using Larger Than Block-Size Key - Hash Key First"; + d.output = "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b" + "\x55\xed\x40\x21\x12"; + d.inLen = XSTRLEN(d.input); + d.outLen = WC_SHA_DIGEST_SIZE; + test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; + test_hmac[3] = d; +#if FIPS_VERSION3_GE(6,0,0) + int allowShortKeyWithFips = 1; +#endif for (i = 0; i < times; ++i) { -#if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) +#if defined(HAVE_CAVIUM) || (defined(HAVE_FIPS) && FIPS_VERSION3_LT(6,0,0)) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif @@ -5873,6 +5959,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha_test(void) ret = wc_HmacSetKey(&hmac, WC_SHA, (byte*)keys[i], (word32)XSTRLEN(keys[i])); +#if FIPS_VERSION3_GE(6,0,0) + if (i == 1) { + if (ret != HMAC_MIN_KEYLEN_E) + return WC_TEST_RET_ENC_EC(ret); + /* Now use the ex and allow short keys with FIPS option */ + ret = wc_HmacSetKey_ex(&hmac, WC_SHA, (byte*) keys[i], + (word32)XSTRLEN(keys[i]), allowShortKeyWithFips); + } +#endif if (ret != 0) return WC_TEST_RET_ENC_EC(ret); ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, @@ -5912,11 +6007,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha224_test(void) "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" "\xAA\xAA\xAA", - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" }; testVector a, b, c, d; @@ -5926,6 +6025,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha224_test(void) int times = sizeof(test_hmac) / sizeof(testVector), i; WOLFSSL_ENTER("hmac_sha224_test"); + /* Following test vectors are from RFC 4231 section 4 */ a.input = "Hi There"; a.output = "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3" "\x3f\x47\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22"; @@ -5947,9 +6047,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha224_test(void) c.inLen = XSTRLEN(c.input); c.outLen = WC_SHA224_DIGEST_SIZE; - d.input = "Big Key Input"; - d.output = "\xe7\x4e\x2b\x8a\xa9\xf0\x37\x2f\xed\xae\x70\x0c\x49\x47\xf1" - "\x46\x54\xa7\x32\x6b\x55\x01\x87\xd2\xc8\x02\x0e\x3a"; + d.input = "Test Using Larger Than Block-Size Key - Hash Key First"; + d.output = "\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e"; d.inLen = XSTRLEN(d.input); d.outLen = WC_SHA224_DIGEST_SIZE; @@ -6010,15 +6109,25 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha256_test(void) "\xAA\xAA\xAA", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" "\xAA\xAA\xAA", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" }; - testVector a, b, c, d; - testVector test_hmac[4]; + testVector a, b, c, d, e; + testVector test_hmac[5]; wc_test_ret_t ret; int times = sizeof(test_hmac) / sizeof(testVector), i; WOLFSSL_ENTER("hmac_sha256_test"); + /* Following test vectors are from RFC 4231 section 4 */ a.input = "Hi There"; a.output = "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1" "\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32" @@ -6050,10 +6159,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha256_test(void) d.inLen = 0; d.outLen = WC_SHA256_DIGEST_SIZE; + e.input = "Test Using Larger Than Block-Size Key - Hash Key First"; + e.output = "\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7" + "\x7f\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3" + "\x7f\x54"; + e.inLen = XSTRLEN(e.input);; + e.outLen = WC_SHA256_DIGEST_SIZE; + test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; test_hmac[3] = d; + test_hmac[4] = e; for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) @@ -6115,15 +6232,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha384_test(void) "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" "\xAA\xAA\xAA", - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" }; testVector a, b, c, d; @@ -6133,6 +6250,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha384_test(void) int times = sizeof(test_hmac) / sizeof(testVector), i; WOLFSSL_ENTER("hmac_sha384_test"); + /* Following test vectors are from RFC 4231 section 4 */ a.input = "Hi There"; a.output = "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90" "\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb" @@ -6160,11 +6278,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha384_test(void) c.inLen = XSTRLEN(c.input); c.outLen = WC_SHA384_DIGEST_SIZE; - d.input = "Big Key Input"; - d.output = "\xd2\x3d\x29\x6e\xf5\x1e\x23\x23\x49\x18\xb3\xbf\x4c\x38\x7b" - "\x31\x21\x17\xbb\x09\x73\x27\xf8\x12\x9d\xe9\xc6\x5d\xf9\x54" - "\xd6\x38\x5a\x68\x53\x14\xee\xe0\xa6\x4f\x36\x7e\xb2\xf3\x1a" - "\x57\x41\x69"; + d.input = "Test Using Larger Than Block-Size Key - Hash Key First"; + d.output = "\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5" + "\xb4\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a" + "\xc4\xc6\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63" + "\xf4\x49\x52"; d.inLen = XSTRLEN(d.input); d.outLen = WC_SHA384_DIGEST_SIZE; @@ -6223,15 +6341,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha512_test(void) "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" "\xAA\xAA\xAA", - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" - "\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" }; testVector a, b, c, d; @@ -6241,6 +6359,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha512_test(void) int times = sizeof(test_hmac) / sizeof(testVector), i; WOLFSSL_ENTER("hmac_sha512_test"); + /* Following test vectors are from RFC 4231 section 4 */ a.input = "Hi There"; a.output = "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c" "\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1" @@ -6271,12 +6390,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hmac_sha512_test(void) c.inLen = XSTRLEN(c.input); c.outLen = WC_SHA512_DIGEST_SIZE; - d.input = "Big Key Input"; - d.output = "\x3f\xa9\xc9\xe1\xbd\xbb\x04\x55\x1f\xef\xcc\x92\x33\x08\xeb" - "\xcf\xc1\x9a\x5b\x5b\xc0\x7c\x86\x84\xae\x8c\x40\xaf\xb1\x27" - "\x87\x38\x92\x04\xa8\xed\xd7\xd7\x07\xa9\x85\xa0\xc2\xcd\x30" - "\xc0\x56\x14\x49\xbc\x2f\x69\x15\x6a\x97\xd8\x79\x2f\xb3\x3b" - "\x1e\x18\xfe\xfa"; + d.input = "Test Using Larger Than Block-Size Key - Hash Key First"; + d.output = "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8" + "\xb4\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8" + "\xf3\x52\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d" + "\x6a\x1e\x52\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98" + "\x5d\x78\x65\x98"; d.inLen = XSTRLEN(d.input); d.outLen = WC_SHA512_DIGEST_SIZE; @@ -8288,7 +8407,8 @@ static const int fiducial1 = WC_TEST_RET_LN; /* source code reference point -- #if defined(WOLFSSL_AES_OFB) || defined(WOLFSSL_AES_CFB) || \ defined(WOLFSSL_AES_XTS) #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) \ - && !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + && !defined(HAVE_SELFTEST) +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(6,0,0) /* pass in the function, key, iv, plain text and expected and this function * tests that the encryption and decryption is successful */ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, @@ -8392,7 +8512,8 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, return ret; } -#endif /* OPENSSL_EXTRA */ +#endif /* !HAVE_FIPS || FIPS_VERSION3_GE(6,0,0) */ +#endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY && !HAVE_SELFTEST */ #endif /* WOLFSSL_AES_OFB || WOLFSSL_AES_CFB */ #ifdef WOLFSSL_AES_OFB @@ -9099,7 +9220,7 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, return ret; } -#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) +#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(6,0,0)) static wc_test_ret_t aescfb1_test(void) { #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) @@ -9141,6 +9262,11 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, { 0xC0 }; + + WOLFSSL_SMALL_STACK_STATIC const byte cipher1_7bit[] = + { + 0x1C + }; #endif /* WOLFSSL_AES_128 */ #ifdef WOLFSSL_AES_192 WOLFSSL_SMALL_STACK_STATIC const byte iv2[] = { @@ -9241,6 +9367,15 @@ static wc_test_ret_t EVP_test(const WOLFSSL_EVP_CIPHER* type, const byte* key, ERROR_OUT(WC_TEST_RET_ENC_NC, out); #endif /* HAVE_AES_DECRYPT */ + XMEMSET(cipher, 0, sizeof(cipher)); + ret = wc_AesCfb1Encrypt(enc, cipher, msg1, 7); + + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + + if (cipher[0] != cipher1_7bit[0]) + ERROR_OUT(WC_TEST_RET_ENC_NC, out); + #ifdef OPENSSL_EXTRA ret = wc_AesSetKey(enc, key1, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); if (ret != 0) @@ -9701,7 +9836,7 @@ static wc_test_ret_t aes_key_size_test(void) return ret; } -#if defined(WOLFSSL_AES_XTS) +#if defined(WOLFSSL_AES_XTS) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,3)) /* test vectors from http://csrc.nist.gov/groups/STM/cavp/block-cipher-modes.html */ #ifdef WOLFSSL_AES_128 @@ -9840,7 +9975,8 @@ static wc_test_ret_t aes_xts_128_test(void) if (XMEMCMP(c2, buf, sizeof(c2))) ERROR_OUT(WC_TEST_RET_ENC_NC, out); -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS_AESXTS) && \ + defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); ret = wc_AesXtsEncrypt(aes, buf, p2, sizeof(p2), i2, sizeof(i2)); #if defined(WOLFSSL_ASYNC_CRYPT) @@ -9867,7 +10003,8 @@ static wc_test_ret_t aes_xts_128_test(void) if (XMEMCMP(c1, buf, AES_BLOCK_SIZE)) ERROR_OUT(WC_TEST_RET_ENC_NC, out); -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS_AESXTS) && \ + defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); ret = wc_AesXtsEncrypt(aes, buf, p1, sizeof(p1), i1, sizeof(i1)); #if defined(WOLFSSL_ASYNC_CRYPT) @@ -9891,7 +10028,8 @@ static wc_test_ret_t aes_xts_128_test(void) if (XMEMCMP(cp2, cipher, sizeof(cp2))) ERROR_OUT(WC_TEST_RET_ENC_NC, out); -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS_AESXTS) && \ + defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); XMEMSET(cipher, 0, sizeof(cipher)); ret = wc_AesXtsEncrypt(aes, cipher, pp, sizeof(pp), i1, sizeof(i1)); @@ -9923,7 +10061,8 @@ static wc_test_ret_t aes_xts_128_test(void) if (XMEMCMP(pp, buf, sizeof(pp))) ERROR_OUT(WC_TEST_RET_ENC_NC, out); -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS_AESXTS) && \ + defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); XMEMSET(buf, 0, sizeof(buf)); ret = wc_AesXtsDecrypt(aes, buf, cipher, sizeof(pp), i1, sizeof(i1)); @@ -9956,7 +10095,8 @@ static wc_test_ret_t aes_xts_128_test(void) if (XMEMCMP(p1, buf, AES_BLOCK_SIZE)) ERROR_OUT(WC_TEST_RET_ENC_NC, out); -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS_AESXTS) && \ + defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); XMEMSET(buf, 0, sizeof(buf)); ret = wc_AesXtsDecrypt(aes, buf, c1, sizeof(c1), i1, sizeof(i1)); @@ -10847,7 +10987,7 @@ static wc_test_ret_t aesecb_test(void) if (XMEMCMP(cipher, niCipher, AES_BLOCK_SIZE) != 0) ERROR_OUT(WC_TEST_RET_ENC_NC, out); -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) XMEMSET(cipher, 0, AES_BLOCK_SIZE); WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); ret = wc_AesSetKey(enc, niKey, sizeof(niKey), cipher, AES_ENCRYPTION); @@ -10889,7 +11029,7 @@ static wc_test_ret_t aesecb_test(void) if (XMEMCMP(plain, niPlain, AES_BLOCK_SIZE) != 0) ERROR_OUT(WC_TEST_RET_ENC_NC, out); -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) XMEMSET(plain, 0, AES_BLOCK_SIZE); WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); ret = wc_AesSetKey(dec, niKey, sizeof(niKey), plain, AES_DECRYPTION); @@ -11554,7 +11694,7 @@ static wc_test_ret_t aesctr_test(Aes* enc, Aes* dec, byte* cipher, byte* plain) #endif } -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) for (i = 0; i < AES_CTR_TEST_LEN; i++) { if (testVec[i].key != NULL) { ret = wc_AesSetKeyDirect(enc, testVec[i].key, testVec[i].keySz, @@ -11631,7 +11771,7 @@ static wc_test_ret_t aesctr_test(Aes* enc, Aes* dec, byte* cipher, byte* plain) #endif } -#endif /* DEBUG_VECTOR_REGISTER_ACCESS && WC_AES_C_DYNAMIC_FALLBACK */ +#endif /* DEBUG_VECTOR_REGISTER_ACCESS && WC_C_DYNAMIC_FALLBACK */ out: @@ -11896,7 +12036,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_test(void) break; } -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) /* Iterate from one AES_BLOCK_SIZE of bigMsg through the whole * message by AES_BLOCK_SIZE for each size of AES key. */ WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); @@ -11945,7 +12085,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_test(void) break; } WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(0); -#endif /* DEBUG_VECTOR_REGISTER_ACCESS && WC_AES_C_DYNAMIC_FALLBACK */ +#endif /* DEBUG_VECTOR_REGISTER_ACCESS && WC_C_DYNAMIC_FALLBACK */ #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) XFREE(bigCipher, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -12447,7 +12587,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes256_test(void) ERROR_OUT(WC_TEST_RET_ENC_NC, out); #endif -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) ret = wc_AesSetKey(enc, key, keySz, iv, AES_ENCRYPTION); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); @@ -12522,7 +12662,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes256_test(void) ERROR_OUT(WC_TEST_RET_ENC_NC, out); #endif -#endif /* DEBUG_VECTOR_REGISTER_ACCESS && WC_AES_C_DYNAMIC_FALLBACK */ +#endif /* DEBUG_VECTOR_REGISTER_ACCESS && WC_C_DYNAMIC_FALLBACK */ out: @@ -12614,7 +12754,7 @@ static wc_test_ret_t aesgcm_default_test_helper(byte* key, int keySz, byte* iv, if (XMEMCMP(tag, resultT, tagSz)) ERROR_OUT(WC_TEST_RET_ENC_NC, out); -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); ret = wc_AesGcmEncrypt(enc, resultC, plain, plainSz, iv, ivSz, resultT, tagSz, aad, aadSz); @@ -12649,7 +12789,7 @@ static wc_test_ret_t aesgcm_default_test_helper(byte* key, int keySz, byte* iv, ERROR_OUT(WC_TEST_RET_ENC_NC, out); } -#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_AES_C_DYNAMIC_FALLBACK) +#if defined(DEBUG_VECTOR_REGISTER_ACCESS) && defined(WC_C_DYNAMIC_FALLBACK) WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(SYSLIB_FAILED_E); ret = wc_AesGcmDecrypt(dec, resultP, resultC, cipherSz, iv, ivSz, resultT, tagSz, aad, aadSz); @@ -16220,6 +16360,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t memory_test(void) CERT_ROOT "test" CERT_PATH_SEP "cert-ext-ia.der"; static const char* certExtNct = CERT_ROOT "test" CERT_PATH_SEP "cert-ext-nct.der"; +#ifndef WOLFSSL_ASN_INT_LEAD_0_ANY + static const char* certBadNegInt = + CERT_ROOT "test" CERT_PATH_SEP "cert-bad-neg-int.der"; +#endif + static const char* certBadOid = + CERT_ROOT "test" CERT_PATH_SEP "cert-bad-oid.der"; +#ifndef WOLFSSL_NO_ASN_STRICT + static const char* certBadUtf8 = + CERT_ROOT "test" CERT_PATH_SEP "cert-bad-utf8.der"; +#endif #endif #ifndef NO_WRITE_TEMP_FILES @@ -16469,6 +16619,71 @@ static wc_test_ret_t cert_asn1_test(void) return ret; } +static wc_test_ret_t cert_load_bad(const char* fname, byte* tmp, int err) +{ + wc_test_ret_t ret; + DecodedCert cert; + XFILE file; + size_t bytes; + + if ((fname == NULL) || (tmp == NULL)) { + ERROR_OUT(WC_TEST_RET_ENC_NC, done); + } + file = XFOPEN(fname, "rb"); + if (!file) { + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); + } + bytes = XFREAD(tmp, 1, FOURK_BUF, file); + XFCLOSE(file); + if (bytes == 0) { + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); + } + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + FreeDecodedCert(&cert); + if (ret != err) { + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + } + ret = 0; + +done: + return ret; +} + +static wc_test_ret_t cert_bad_asn1_test(void) +{ + wc_test_ret_t ret = 0; + byte* tmp; + + tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ret = WC_TEST_RET_ENC_ERRNO; + } + +#ifndef WOLFSSL_ASN_INT_LEAD_0_ANY + if (ret == 0) { + /* Serial number: 0xff 0xa8. 0xff and top bit set on next byte invalid. + */ + ret = cert_load_bad(certBadNegInt, tmp, ASN_EXPECT_0_E); + } +#endif + if (ret == 0) { + /* Subject name OID: 55 04 f4. Last byte with top bit set invalid. */ + ret = cert_load_bad(certBadOid, tmp, ASN_PARSE_E); + } +#ifndef WOLFSSL_NO_ASN_STRICT + if (ret == 0) { + /* Issuer name UTF8STRING: df 52 4e 44. Top bit of second byte not set. + */ + ret = cert_load_bad(certBadUtf8, tmp, ASN_PARSE_E); + } +#endif + + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void) { #if !defined(NO_FILESYSTEM) @@ -16542,6 +16757,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void) if (ret == 0) ret = cert_asn1_test(); + if (ret == 0) + ret = cert_bad_asn1_test(); return ret; } @@ -18697,7 +18914,9 @@ static wc_test_ret_t rsa_ecc_certgen_test(WC_RNG* rng, byte* tmp) word32 idx3 = 0; #if (!defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)) \ || !defined(USE_CERT_BUFFERS_256) - XFILE file3; + #ifndef NO_FILESYSTEM + XFILE file3; + #endif #endif wc_test_ret_t ret; @@ -18750,20 +18969,29 @@ static wc_test_ret_t rsa_ecc_certgen_test(WC_RNG* rng, byte* tmp) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa); /* Get Cert Key */ -#ifdef USE_CERT_BUFFERS_256 - XMEMCPY(tmp, ecc_key_pub_der_256, sizeof_ecc_key_pub_der_256); - bytes3 = sizeof_ecc_key_pub_der_256; -#else - file3 = XFOPEN(eccKeyPubFileDer, "rb"); - if (!file3) { - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit_rsa); + #if defined(USE_CERT_BUFFERS_256) + { + XMEMCPY(tmp, ecc_key_pub_der_256, sizeof_ecc_key_pub_der_256); + bytes3 = sizeof_ecc_key_pub_der_256; } + #elif !defined(NO_FILESYSTEM) + { + file3 = XFOPEN(eccKeyPubFileDer, "rb"); + if (!file3) { + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit_rsa); + } - bytes3 = XFREAD(tmp, 1, FOURK_BUF, file3); - XFCLOSE(file3); - if (bytes3 == 0) - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit_rsa); -#endif + bytes3 = XFREAD(tmp, 1, FOURK_BUF, file3); + XFCLOSE(file3); + if (bytes3 == 0) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit_rsa); + } + #else + { + WOLFSSL_MSG("No file system and USE_CERT_BUFFERS_256 not defined.(1)"); + ERROR_OUT(ASN_PARSE_E, exit_rsa); + } + #endif ret = wc_ecc_init_ex(caEccKeyPub, HEAP_HINT, devId); if (ret != 0) @@ -18911,7 +19139,11 @@ static wc_test_ret_t rsa_keygen_test(WC_RNG* rng) RsaKey genKey[1]; #endif wc_test_ret_t ret; +#ifndef WOLFSSL_NO_MALLOC byte* der = NULL; +#else + byte der[1024]; +#endif #ifndef WOLFSSL_CRYPTOCELL word32 idx = 0; #endif @@ -18956,11 +19188,12 @@ static wc_test_ret_t rsa_keygen_test(WC_RNG* rng) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_rsa); #endif +#ifndef WOLFSSL_NO_MALLOC der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit_rsa); } - +#endif derSz = wc_RsaKeyToDer(genKey, der, FOURK_BUF); if (derSz < 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(derSz), exit_rsa); @@ -18996,10 +19229,12 @@ static wc_test_ret_t rsa_keygen_test(WC_RNG* rng) wc_FreeRsaKey(genKey); #endif +#ifndef WOLFSSL_NO_MALLOC if (der != NULL) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); der = NULL; } +#endif return ret; } @@ -22426,9 +22661,19 @@ static wc_test_ret_t openssl_aes_test(void) WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) { wc_test_ret_t ret; - EVP_MD_CTX md_ctx; +#ifdef WOLFSSL_SMALL_STACK + EVP_MD_CTX *md_ctx = (EVP_MD_CTX *)XMALLOC(sizeof(EVP_MD_CTX), NULL, DYNAMIC_TYPE_OPENSSL); +#else + EVP_MD_CTX md_ctx[1]; +#endif testVector a, b, c, d, e, f; byte hash[WC_SHA256_DIGEST_SIZE*2]; /* max size */ + +#ifdef WOLFSSL_SMALL_STACK + if (md_ctx == NULL) + return WC_TEST_RET_ENC_EC(MEMORY_E); +#endif + WOLFSSL_ENTER("openssl_test"); a.inLen = 0; @@ -22462,15 +22707,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) a.inLen = XSTRLEN(a.input); a.outLen = WC_MD5_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_md5()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_md5()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, a.input, (unsigned long)a.inLen); + ret = EVP_DigestUpdate(md_ctx, a.input, (unsigned long)a.inLen); } if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS) return WC_TEST_RET_ENC_NC; if (XMEMCMP(hash, a.output, WC_MD5_DIGEST_SIZE) != 0) @@ -22486,14 +22731,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) b.inLen = XSTRLEN(b.input); b.outLen = WC_SHA_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha1()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha1()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, b.input, (unsigned long)b.inLen); + ret = EVP_DigestUpdate(md_ctx, b.input, (unsigned long)b.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS) return WC_TEST_RET_ENC_NC; if (XMEMCMP(hash, b.output, b.outLen) != 0) @@ -22508,14 +22753,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) e.inLen = XSTRLEN(e.input); e.outLen = WC_SHA224_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha224()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha224()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); + ret = EVP_DigestUpdate(md_ctx, e.input, (unsigned long)e.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, e.output, e.outLen) != 0) { return WC_TEST_RET_ENC_NC; } @@ -22529,14 +22774,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) d.inLen = XSTRLEN(d.input); d.outLen = WC_SHA256_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha256()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha256()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, d.input, (unsigned long)d.inLen); + ret = EVP_DigestUpdate(md_ctx, d.input, (unsigned long)d.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, d.output, d.outLen) != 0) { return WC_TEST_RET_ENC_NC; } @@ -22552,14 +22797,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) e.inLen = XSTRLEN(e.input); e.outLen = WC_SHA384_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha384()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha384()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); + ret = EVP_DigestUpdate(md_ctx, e.input, (unsigned long)e.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, e.output, e.outLen) != 0) { return WC_TEST_RET_ENC_NC; } @@ -22576,14 +22821,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) f.inLen = XSTRLEN(f.input); f.outLen = WC_SHA512_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha512()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha512()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, f.input, (unsigned long)f.inLen); + ret = EVP_DigestUpdate(md_ctx, f.input, (unsigned long)f.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, f.output, f.outLen) != 0) { return WC_TEST_RET_ENC_NC; } @@ -22598,14 +22843,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) f.inLen = XSTRLEN(f.input); f.outLen = WC_SHA512_224_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha512_224()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha512_224()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, f.input, (unsigned long)f.inLen); + ret = EVP_DigestUpdate(md_ctx, f.input, (unsigned long)f.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, f.output, f.outLen) != 0) { return WC_TEST_RET_ENC_NC; } @@ -22621,14 +22866,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) f.inLen = XSTRLEN(f.input); f.outLen = WC_SHA512_256_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha512_256()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha512_256()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, f.input, (unsigned long)f.inLen); + ret = EVP_DigestUpdate(md_ctx, f.input, (unsigned long)f.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, f.output, f.outLen) != 0) { return WC_TEST_RET_ENC_NC; } @@ -22644,14 +22889,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) e.inLen = XSTRLEN(e.input); e.outLen = WC_SHA3_224_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha3_224()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha3_224()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); + ret = EVP_DigestUpdate(md_ctx, e.input, (unsigned long)e.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, e.output, e.outLen) != 0) { return WC_TEST_RET_ENC_NC; } @@ -22666,14 +22911,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) d.inLen = XSTRLEN(d.input); d.outLen = WC_SHA3_256_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha3_256()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha3_256()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, d.input, (unsigned long)d.inLen); + ret = EVP_DigestUpdate(md_ctx, d.input, (unsigned long)d.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, d.output, d.outLen) != 0) { return WC_TEST_RET_ENC_NC; } @@ -22688,14 +22933,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) e.inLen = XSTRLEN(e.input); e.outLen = WC_SHA3_384_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha3_384()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha3_384()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, e.input, (unsigned long)e.inLen); + ret = EVP_DigestUpdate(md_ctx, e.input, (unsigned long)e.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, e.output, e.outLen) != 0) { return WC_TEST_RET_ENC_NC; } @@ -22711,14 +22956,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) f.inLen = XSTRLEN(f.input); f.outLen = WC_SHA3_512_DIGEST_SIZE; - EVP_MD_CTX_init(&md_ctx); - ret = EVP_DigestInit(&md_ctx, EVP_sha3_512()); + EVP_MD_CTX_init(md_ctx); + ret = EVP_DigestInit(md_ctx, EVP_sha3_512()); if (ret == WOLFSSL_SUCCESS) { - ret = EVP_DigestUpdate(&md_ctx, f.input, (unsigned long)f.inLen); + ret = EVP_DigestUpdate(md_ctx, f.input, (unsigned long)f.inLen); if (ret == WOLFSSL_SUCCESS) - ret = EVP_DigestFinal(&md_ctx, hash, 0); + ret = EVP_DigestFinal(md_ctx, hash, 0); } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_cleanup(md_ctx); if (ret != WOLFSSL_SUCCESS || XMEMCMP(hash, f.output, f.outLen) != 0) { return WC_TEST_RET_ENC_NC; @@ -22726,6 +22971,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t openssl_test(void) #endif /* WOLFSSL_NOSHA3_512 */ #endif /* WOLFSSL_SHA3 */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(md_ctx, NULL, DYNAMIC_TYPE_OPENSSL); + md_ctx = NULL; +#endif + #ifndef WC_NO_RNG if (RAND_bytes(hash, sizeof(hash)) != WOLFSSL_SUCCESS) return WC_TEST_RET_ENC_NC; @@ -24529,7 +24779,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void) salt, (int)sizeof(salt), iterations, kLen, WC_SHA256, HEAP_HINT, devId); if (ret != 0) - return ret; + return WC_TEST_RET_ENC_EC(ret); if (XMEMCMP(derived, verify, sizeof(verify)) != 0) return WC_TEST_RET_ENC_NC; @@ -24872,6 +25122,116 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sshkdf_test(void) #endif /* WOLFSSL_WOLFSSH */ +#if defined(WOLFSSL_HAVE_PRF) && !defined(NO_HMAC) && defined(WOLFSSL_SHA384) +#define DIGL 12 +#define SECL 48 +#define LBSL 63 +WOLFSSL_TEST_SUBROUTINE wc_test_ret_t prf_test(void) +{ + int ret; + byte dig[DIGL] = {0}; + byte secret[SECL] = { + 0x10, 0xbc, 0xb4, 0xa2, 0xe8, 0xdc, 0xf1, 0x9b, 0x4c, + 0x51, 0x9c, 0xed, 0x31, 0x1b, 0x51, 0x57, 0x02, 0x3f, + 0xa1, 0x7d, 0xfb, 0x0e, 0xf3, 0x4e, 0x8f, 0x6f, 0x71, + 0xa3, 0x67, 0x76, 0x6b, 0xfa, 0x5d, 0x46, 0x4a, 0xe8, + 0x61, 0x18, 0x81, 0xc4, 0x66, 0xcc, 0x6f, 0x09, 0x99, + 0x9d, 0xfc, 0x47 + }; + byte lablSd[LBSL] = { + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x69, + 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x0b, 0x46, 0xba, + 0x56, 0xbf, 0x1f, 0x5d, 0x99, 0xff, 0xe9, 0xbb, 0x43, + 0x01, 0xe7, 0xca, 0x2c, 0x00, 0xdf, 0x9a, 0x39, 0x6e, + 0xcf, 0x6d, 0x15, 0x27, 0x4d, 0xf2, 0x93, 0x96, 0x4a, + 0x91, 0xde, 0x5c, 0xc0, 0x47, 0x7c, 0xa8, 0xae, 0xcf, + 0x5d, 0x93, 0x5f, 0x4c, 0x92, 0xcc, 0x98, 0x5b, 0x43 + }; + byte expected[DIGL] = { + 0xee, 0xcb, 0xb1, 0x30, 0xf2, 0xcd, 0xb3, 0x4a, + 0xbe, 0xda, 0xc1, 0xf6 + }; + int digL = DIGL; + int secL = SECL; + int lblsdL = LBSL; + int hash_type = sha384_mac; + + ret = wc_PRF(dig, digL, secret, secL, lablSd, lblsdL, hash_type, + HEAP_HINT, INVALID_DEVID); + if (ret != 0) { + printf("Failed w/ code: %d\n", ret); + return ret; + } + + if (XMEMCMP(expected, dig, DIGL) != 0) { + printf("Got unexpected digest\n"); + return -1; + } + + if (ret != 0) + return -1; + + return 0; +} +#endif /* WOLFSSL_HAVE_PRF && !NO_HMAC */ + +#ifdef WOLFSSL_HAVE_PRF +#if defined(HAVE_HKDF) && !defined(NO_HMAC) +#ifdef WOLFSSL_BASE16 +WOLFSSL_TEST_SUBROUTINE wc_test_ret_t tls12_kdf_test(void) +{ + const char* preMasterSecret = "D06F9C19BFF49B1E91E4EFE97345D089" + "4E6C2E6C34A165B24540E2970875D641" + "2AA6515871B389B4C199BB8389C71CED"; + const char* helloRandom = "162B81EDFBEAE4F25240320B87E7651C" + "865564191DD782DB0B9ECA275FBA1BB9" + "5A1DA3DF436D68DA86C5E7B4B4A36E46" + "B977C61767983A31BE270D74517BD0F6"; + const char* masterSecret = "EB38B8D89B98B1C266DE44BB3CA14E83" + "C32F009F9955B1D994E61D3C51EE8760" + "90B4EF89CC7AF42F46E72201BFCC7977"; + const char* label = "master secret"; + + byte pms[48] = {0}; + byte seed[64] = {0}; + byte ms[48] = {0}; + byte result[48] = {0}; + + word32 pmsSz = (word32)sizeof(pms); + word32 seedSz = (word32)sizeof(seed); + word32 msSz = (word32)sizeof(ms); + int ret; + + ret = Base16_Decode((const byte*)preMasterSecret, + (word32)XSTRLEN(preMasterSecret), pms, &pmsSz); + if (ret != 0) + return ret; + ret = Base16_Decode((const byte*)helloRandom, + (word32)XSTRLEN(helloRandom), seed, &seedSz); + if (ret != 0) + return ret; + ret = Base16_Decode((const byte*)masterSecret, + (word32)XSTRLEN(masterSecret), ms, &msSz); + if (ret != 0) + return ret; + + ret = wc_PRF_TLS(result, msSz, pms, pmsSz, + (const byte*)label, (word32)XSTRLEN(label), seed, seedSz, + 1, sha256_mac, NULL, INVALID_DEVID); + if (ret != 0) { + if (ret == FIPS_PRIVATE_KEY_LOCKED_E) { + printf(" wc_PRF_TLSv12: Private key locked.\n"); + } + return -1; + } + + if (XMEMCMP(result, ms, msSz) != 0) + return -1; + return 0; +} +#endif /* WOLFSSL_BASE16 */ +#endif /* WOLFSSL_HAVE_HKDF && !NO_HMAC */ +#endif /* WOLFSSL_HAVE_PRF */ #ifdef WOLFSSL_TLS13 @@ -26083,6 +26443,61 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t srtpkdf_test(void) 0xe1, 0x29, 0x4f, 0x61, 0x30, 0x3c, 0x4d, 0x46, 0x5f, 0x5c, 0x81, 0x3c, 0x38, 0xb6 }; + + /* SRTCP w/ 48-bit idx - KDR 0 (-1) */ + WOLFSSL_SMALL_STACK_STATIC const byte mk48_1[] = { + 0xFF, 0xB6, 0xCB, 0x09, 0x71, 0x3F, 0x63, 0x4D, + 0x7F, 0x42, 0xED, 0xA8, 0x12, 0x81, 0x50, 0xE6 + }; + WOLFSSL_SMALL_STACK_STATIC const byte ms48_1[] = { + 0x1F, 0x04, 0x76, 0xC8, 0x7F, 0x58, 0x23, 0xEF, + 0xD3, 0x57, 0xB2, 0xBD, 0xF1, 0x32 + }; + WOLFSSL_SMALL_STACK_STATIC const byte srtcp48idx_1[] = { + 0x00, 0x00, 0x08, 0x56, 0xBC, 0x39 + }; + WOLFSSL_SMALL_STACK_STATIC const byte srtcpKe_48_1[] = { + 0xD2, 0xC3, 0xF3, 0x49, 0x00, 0x1A, 0x18, 0x0F, + 0xB6, 0x05, 0x5A, 0x5A, 0x67, 0x8E, 0xE5, 0xB2 + }; + WOLFSSL_SMALL_STACK_STATIC const byte srtcpKa_48_1[] = { + 0x8D, 0x54, 0xBE, 0xB5, 0x7B, 0x7F, 0x7A, 0xAB, + 0xF5, 0x46, 0xCE, 0x5B, 0x45, 0x69, 0x4A, 0x75, + 0x81, 0x2A, 0xE2, 0xCB + }; + WOLFSSL_SMALL_STACK_STATIC const byte srtcpKs_48_1[] = { + 0x76, 0x3C, 0x97, 0x6A, 0x45, 0x31, 0xA7, 0x79, + 0x3C, 0x28, 0x4A, 0xA6, 0x82, 0x03 + }; + + /* SRTCP w/ 48-bit idx - KDR 19 */ + WOLFSSL_SMALL_STACK_STATIC const byte mk48_2[] = { + 0xBD, 0x1D, 0x71, 0x6B, 0xDA, 0x28, 0xE3, 0xFC, + 0xA5, 0xA0, 0x66, 0x3F, 0x2E, 0x34, 0xA8, 0x58 + }; + WOLFSSL_SMALL_STACK_STATIC const byte ms48_2[] = { + 0x79, 0x06, 0xE5, 0xAB, 0x5C, 0x2B, 0x1B, 0x69, + 0xFA, 0xEE, 0xD2, 0x29, 0x57, 0x3C + }; + WOLFSSL_SMALL_STACK_STATIC const byte srtcp48idx_2[] = { + 0x00, 0x00, 0x59, 0xD0, 0xC2, 0xE8 + }; + WOLFSSL_SMALL_STACK_STATIC const byte srtcpKe_48_2[] = { + 0xB9, 0xD7, 0xAD, 0xD8, 0x90, 0x94, 0xC2, 0x92, + 0xA5, 0x04, 0x87, 0xC4, 0x8C, 0xEF, 0xE2, 0xA3 + }; + WOLFSSL_SMALL_STACK_STATIC const byte srtcpKa_48_2[] = { + 0x07, 0xD5, 0xC4, 0xD2, 0x06, 0xFB, 0x63, 0x15, + 0xC2, 0x9C, 0x7F, 0x55, 0xD1, 0x16, 0x5C, 0xB5, + 0xB7, 0x44, 0x54, 0xBD + }; + WOLFSSL_SMALL_STACK_STATIC const byte srtcpKs_48_2[] = { + 0x0C, 0x5E, 0x53, 0xC1, 0xD0, 0x75, 0xAD, 0x65, + 0xBF, 0x51, 0x74, 0x50, 0x89, 0xD7 + }; + int kdr_48_1 = -1; + int kdr_48_2 = 19; + #define SRTP_TV_CNT 4 Srtp_Kdf_Tv tv[SRTP_TV_CNT] = { { key_0, (word32)sizeof(key_0), salt_0, (word32)sizeof(salt_0), -1, @@ -26322,6 +26737,37 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t srtpkdf_test(void) return WC_TEST_RET_ENC_NC; } + /* SRTCP w/ 48-bit IDX, 128-bit key test */ + if (i == 0) { + ret = wc_SRTCP_KDF_ex(mk48_1, (word32)sizeof(mk48_1), + ms48_1, (word32)sizeof(ms48_1), + kdr_48_1, srtcp48idx_1, keyE, tv[i].keSz, + keyA, tv[i].kaSz, keyS, tv[i].ksSz, + WC_SRTCP_48BIT_IDX); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + if (XMEMCMP(keyE, srtcpKe_48_1, tv[i].keSz) != 0) + return WC_TEST_RET_ENC_NC; + if (XMEMCMP(keyA, srtcpKa_48_1, tv[i].kaSz) != 0) + return WC_TEST_RET_ENC_NC; + if (XMEMCMP(keyS, srtcpKs_48_1, tv[i].ksSz) != 0) + return WC_TEST_RET_ENC_NC; + + ret = wc_SRTCP_KDF_ex(mk48_2, (word32)sizeof(mk48_2), + ms48_2, (word32)sizeof(ms48_2), + kdr_48_2, srtcp48idx_2, keyE, tv[i].keSz, + keyA, tv[i].kaSz, keyS, tv[i].ksSz, + WC_SRTCP_48BIT_IDX); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + if (XMEMCMP(keyE, srtcpKe_48_2, tv[i].keSz) != 0) + return WC_TEST_RET_ENC_NC; + if (XMEMCMP(keyA, srtcpKa_48_2, tv[i].kaSz) != 0) + return WC_TEST_RET_ENC_NC; + if (XMEMCMP(keyS, srtcpKs_48_2, tv[i].ksSz) != 0) + return WC_TEST_RET_ENC_NC; + } + return 0; } #endif @@ -27343,10 +27789,12 @@ static wc_test_ret_t ecc_test_make_pub(WC_RNG* rng) wc_ecc_init_ex(key, HEAP_HINT, devId); #ifndef NO_ECC256 -#ifdef USE_CERT_BUFFERS_256 - XMEMCPY(tmp, ecc_key_der_256, (size_t)sizeof_ecc_key_der_256); - tmpSz = (size_t)sizeof_ecc_key_der_256; -#else +#if defined(USE_CERT_BUFFERS_256) + { + XMEMCPY(tmp, ecc_key_der_256, (size_t)sizeof_ecc_key_der_256); + tmpSz = (size_t)sizeof_ecc_key_der_256; + } +#elif !defined(NO_FILESYSTEM) { XFILE file = XFOPEN(eccKeyDerFile, "rb"); if (!file) { @@ -27358,6 +27806,11 @@ static wc_test_ret_t ecc_test_make_pub(WC_RNG* rng) if (tmpSz == 0) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); } +#else + { + WOLFSSL_MSG("No file system and USE_CERT_BUFFERS_256 not defined.(2)"); + ERROR_OUT(ASN_PARSE_E, done); + } #endif /* USE_CERT_BUFFERS_256 */ /* import private only then test with */ @@ -28224,6 +28677,15 @@ static wc_test_ret_t ecc_test_curve(WC_RNG* rng, int keySize, int curve_id) wc_test_ret_t ret; WOLFSSL_MSG_EX("ecc_test_curve keySize = %d", keySize); +#if FIPS_VERSION3_GE(6,0,0) + #ifdef DEBUG_WOLFSSL + printf("keySize is %d\n", keySize); + #endif + if (keySize < WC_ECC_FIPS_GEN_MIN) { + goto skip_A; + } +#endif + ret = ecc_test_curve_size(rng, keySize, ECC_TEST_VERIFY_COUNT, curve_id, NULL); if (ret < 0) { @@ -28239,7 +28701,9 @@ static wc_test_ret_t ecc_test_curve(WC_RNG* rng, int keySize, int curve_id) } } #ifndef WOLF_CRYPTO_CB_ONLY_ECC - +#if FIPS_VERSION3_GE(6,0,0) + skip_A: +#endif #ifdef HAVE_ECC_VECTOR_TEST ret = ecc_test_vector(keySize); if (ret < 0) { @@ -28248,6 +28712,12 @@ static wc_test_ret_t ecc_test_curve(WC_RNG* rng, int keySize, int curve_id) } #endif +#if FIPS_VERSION3_GE(6,0,0) + if (keySize < WC_ECC_FIPS_GEN_MIN) { + goto skip_B; + } +#endif + #if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) && \ !defined(NO_ASN_CRYPT) && !defined(WC_NO_RNG) ret = ecc_test_key_decode(rng, keySize); @@ -28274,6 +28744,9 @@ static wc_test_ret_t ecc_test_curve(WC_RNG* rng, int keySize, int curve_id) } } #endif +#if FIPS_VERSION3_GE(6,0,0) + skip_B: +#endif #endif /* WOLF_CRYPTO_CB_ONLY_ECC */ return 0; } @@ -28889,10 +29362,12 @@ static wc_test_ret_t ecc_def_curve_test(WC_RNG *rng) ((defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT)) || \ (defined(HAVE_ECC_KEY_IMPORT) && !defined(WOLFSSL_VALIDATE_ECC_IMPORT))) /* Use test ECC key - ensure real private "d" exists */ - #ifdef USE_CERT_BUFFERS_256 - ret = wc_EccPrivateKeyDecode(ecc_key_der_256, &idx, key, - sizeof_ecc_key_der_256); - #else + #if defined(USE_CERT_BUFFERS_256) + { + ret = wc_EccPrivateKeyDecode(ecc_key_der_256, &idx, key, + sizeof_ecc_key_der_256); + } + #elif !defined(NO_FILESYSTEM) { XFILE file = XFOPEN(eccKeyDerFile, "rb"); byte der[128]; @@ -28906,6 +29381,12 @@ static wc_test_ret_t ecc_def_curve_test(WC_RNG *rng) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); ret = wc_EccPrivateKeyDecode(der, &idx, key, derSz); } + #else + { + (void)idx; + WOLFSSL_MSG("No file system and USE_CERT_BUFFERS_256 not defined.(3)"); + ERROR_OUT(ASN_PARSE_E, done); + } #endif if (ret != 0) { goto done; @@ -29834,9 +30315,9 @@ static wc_test_ret_t ecc_test_cert_gen(WC_RNG* rng) ecc_key certPubKey[1]; #endif int certSz; - size_t bytes; + size_t bytes = 0; word32 idx = 0; -#ifndef USE_CERT_BUFFERS_256 +#if !defined(USE_CERT_BUFFERS_256) && !defined(NO_FILESYSTEM) XFILE file; #endif #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) @@ -29867,38 +30348,46 @@ static wc_test_ret_t ecc_test_cert_gen(WC_RNG* rng) /* Get cert private key */ #ifdef ENABLE_ECC384_CERT_GEN_TEST /* Get Cert Key 384 */ -#ifdef USE_CERT_BUFFERS_256 - XMEMCPY(der, ca_ecc_key_der_384, sizeof_ca_ecc_key_der_384); - bytes = sizeof_ca_ecc_key_der_384; -#else - file = XFOPEN(eccCaKey384File, "rb"); - if (!file) { - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit); - } + #ifdef USE_CERT_BUFFERS_256 + XMEMCPY(der, ca_ecc_key_der_384, sizeof_ca_ecc_key_der_384); + bytes = sizeof_ca_ecc_key_der_384; + #elif !defined(NO_FILESYSTEM) + file = XFOPEN(eccCaKey384File, "rb"); + if (!file) { + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit); + } - bytes = XFREAD(der, 1, FOURK_BUF, file); - XFCLOSE(file); - if (bytes == 0) - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit); - (void)eccCaKeyFile; -#endif /* USE_CERT_BUFFERS_256 */ -#else -#ifdef USE_CERT_BUFFERS_256 - XMEMCPY(der, ca_ecc_key_der_256, sizeof_ca_ecc_key_der_256); - bytes = sizeof_ca_ecc_key_der_256; + bytes = XFREAD(der, 1, FOURK_BUF, file); + XFCLOSE(file); + if (bytes == 0) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit); + (void)eccCaKeyFile; + #else + WOLFSSL_MSG("No file system and USE_CERT_BUFFERS_256 not defined.(4)"); + ERROR_OUT(ASN_PARSE_E, exit); + #endif /* USE_CERT_BUFFERS_256 */ + + /* end if ENABLE_ECC384_CERT_GEN_TEST */ #else - file = XFOPEN(eccCaKeyFile, "rb"); - if (!file) { - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit); - } - bytes = XFREAD(der, 1, FOURK_BUF, file); - XFCLOSE(file); - if (bytes == 0) - ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit); -#ifdef ENABLE_ECC384_CERT_GEN_TEST - (void)eccCaKey384File; -#endif -#endif /* USE_CERT_BUFFERS_256 */ + /* !ENABLE_ECC384_CERT_GEN_TEST */ + + #ifdef USE_CERT_BUFFERS_256 + XMEMCPY(der, ca_ecc_key_der_256, sizeof_ca_ecc_key_der_256); + bytes = sizeof_ca_ecc_key_der_256; + #else + file = XFOPEN(eccCaKeyFile, "rb"); + if (!file) { + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit); + } + bytes = XFREAD(der, 1, FOURK_BUF, file); + XFCLOSE(file); + if (bytes == 0) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit); + + #ifdef ENABLE_ECC384_CERT_GEN_TEST + (void)eccCaKey384File; + #endif + #endif /* USE_CERT_BUFFERS_256 */ #endif /* ENABLE_ECC384_CERT_GEN_TEST */ /* Get CA Key */ @@ -29959,23 +30448,28 @@ static wc_test_ret_t ecc_test_cert_gen(WC_RNG* rng) #endif /* WOLFSSL_CERT_EXT */ #ifdef ENABLE_ECC384_CERT_GEN_TEST -#if defined(USE_CERT_BUFFERS_256) - ret = wc_SetIssuerBuffer(myCert, ca_ecc_cert_der_384, - sizeof_ca_ecc_cert_der_384); -#else - ret = wc_SetIssuer(myCert, eccCaCert384File); - (void)eccCaCertFile; -#endif -#else -#if defined(USE_CERT_BUFFERS_256) - ret = wc_SetIssuerBuffer(myCert, ca_ecc_cert_der_256, - sizeof_ca_ecc_cert_der_256); + #if defined(USE_CERT_BUFFERS_256) + ret = wc_SetIssuerBuffer(myCert, ca_ecc_cert_der_384, + sizeof_ca_ecc_cert_der_384); + #elif !defined(NO_FILESYSTEM) + ret = wc_SetIssuer(myCert, eccCaCert384File); + (void)eccCaCertFile; + #else + /* not testing with embedded, no file system target */ + ERROR_OUT(ASN_PARSE_E, exit); + #endif /* USE_CERT_BUFFERS_256 */ + #else - ret = wc_SetIssuer(myCert, eccCaCertFile); - #ifdef ENABLE_ECC384_CERT_GEN_TEST - (void)eccCaCert384File; + /* not ENABLE_ECC384_CERT_GEN_TEST */ + #if defined(USE_CERT_BUFFERS_256) + ret = wc_SetIssuerBuffer(myCert, ca_ecc_cert_der_256, + sizeof_ca_ecc_cert_der_256); + #else + ret = wc_SetIssuer(myCert, eccCaCertFile); + #ifdef ENABLE_ECC384_CERT_GEN_TEST + (void)eccCaCert384File; + #endif #endif -#endif #endif /* ENABLE_ECC384_CERT_GEN_TEST */ if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit); @@ -30669,11 +31163,13 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test(void) } #endif /* HAVE_ECC160 */ #if (defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 192 +#if !FIPS_VERSION3_GE(6,0,0) ret = ecc_test_curve(&rng, 24, ECC_CURVE_DEF); if (ret < 0) { printf("keySize=24, Default\n"); goto done; } +#endif #endif /* HAVE_ECC192 */ #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224 ret = ecc_test_curve(&rng, 28, ECC_CURVE_DEF); @@ -32579,6 +33075,88 @@ static wc_test_ret_t ed25519_test_make_cert(void) } #endif /* WOLFSSL_TEST_CERT */ +#if defined(HAVE_ED25519_KEY_IMPORT) +static wc_test_ret_t ed25519_test_check_key(void) +{ + /* Fails to find x-ordinate from this y-ordinate. */ + WOLFSSL_SMALL_STACK_STATIC const byte key_bad_y[] = { + 0x40, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + }; + /* Y-ordinate value larger than prime. */ + WOLFSSL_SMALL_STACK_STATIC const byte key_bad_y_max[] = { + 0x40, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, + }; + /* Y-ordinate value equal to prime. */ + WOLFSSL_SMALL_STACK_STATIC const byte key_bad_y_is_p[] = { + 0x40, + 0xed,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, + }; + /* Y-ordinate value equal to prime - 1. */ + WOLFSSL_SMALL_STACK_STATIC const byte key_y_is_p_minus_1[] = { + 0x40, + 0xec,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, + }; + ed25519_key key; + int ret; + int res = 0; + + /* Initialize key for use. */ + ret = wc_ed25519_init_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + return WC_TEST_RET_ENC_NC; + } + + /* Load bad public key only and perform checks. */ + ret = wc_ed25519_import_public(key_bad_y, ED25519_PUB_KEY_SIZE + 1, &key); + if (ret != PUBLIC_KEY_E) { + res = WC_TEST_RET_ENC_NC; + } + if (res == 0) { + /* Load bad public key only and perform checks. */ + ret = wc_ed25519_import_public(key_bad_y_max, ED25519_PUB_KEY_SIZE + 1, + &key); + if (ret != PUBLIC_KEY_E) { + res = WC_TEST_RET_ENC_NC; + } + } + if (res == 0) { + /* Load bad public key only and perform checks. */ + ret = wc_ed25519_import_public(key_bad_y_is_p, ED25519_PUB_KEY_SIZE + 1, + &key); + if (ret != PUBLIC_KEY_E) { + res = WC_TEST_RET_ENC_NC; + } + } + if (res == 0) { + /* Load good public key only and perform checks. */ + ret = wc_ed25519_import_public(key_y_is_p_minus_1, + ED25519_PUB_KEY_SIZE + 1, &key); + if (ret != 0) { + res = WC_TEST_RET_ENC_NC; + } + } + + /* Dispose of key. */ + wc_ed25519_free(&key); + + return res; +} +#endif + #if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) && \ defined(HAVE_ED25519_KEY_IMPORT) static wc_test_ret_t ed25519ctx_test(void) @@ -33412,6 +33990,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void) (void)keySz; (void)sigSz; + ret = ed25519_test_check_key(); + if (ret < 0) + return ret; #ifdef WOLFSSL_TEST_CERT ret = ed25519_test_cert(); if (ret < 0) @@ -33937,6 +34518,104 @@ static wc_test_ret_t ed448_test_make_cert(void) } #endif /* WOLFSSL_TEST_CERT */ +#if defined(HAVE_ED448_KEY_IMPORT) +static wc_test_ret_t ed448_test_check_key(void) +{ + /* Fails to find x-ordinate from this y-ordinate. */ + WOLFSSL_SMALL_STACK_STATIC const byte key_bad_y[] = { + 0x40, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00 + }; + /* Y-ordinate value larger than prime. */ + WOLFSSL_SMALL_STACK_STATIC const byte key_bad_y_max[] = { + 0x40, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff + }; + /* Y-ordinate value equal to prime. */ + WOLFSSL_SMALL_STACK_STATIC const byte key_bad_y_is_p[] = { + 0x40, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff + }; + /* Y-ordinate value equal to prime - 1. */ + WOLFSSL_SMALL_STACK_STATIC const byte key_y_is_p_minus_1[] = { + 0x40, + 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff + }; + ed448_key key; + int ret; + int res = 0; + + /* Initialize key for use. */ + ret = wc_ed448_init_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + return WC_TEST_RET_ENC_NC; + } + + /* Load bad public key only and perform checks. */ + ret = wc_ed448_import_public(key_bad_y, ED448_PUB_KEY_SIZE + 1, &key); + if (ret != PUBLIC_KEY_E) { + res = WC_TEST_RET_ENC_NC; + } + if (ret == 0) { + /* Load bad public key only and perform checks. */ + ret = wc_ed448_import_public(key_bad_y_max, ED448_PUB_KEY_SIZE + 1, + &key); + if (ret != PUBLIC_KEY_E) { + res = WC_TEST_RET_ENC_NC; + } + } + if (res == 0) { + /* Load bad public key only and perform checks. */ + ret = wc_ed448_import_public(key_bad_y_is_p, ED448_PUB_KEY_SIZE + 1, + &key); + if (ret != PUBLIC_KEY_E) { + res = WC_TEST_RET_ENC_NC; + } + } + if (res == 0) { + /* Load good public key only and perform checks. */ + ret = wc_ed448_import_public(key_y_is_p_minus_1, ED448_PUB_KEY_SIZE + 1, + &key); + if (ret != 0) { + res = WC_TEST_RET_ENC_NC; + } + } + + /* Dispose of key. */ + wc_ed448_free(&key); + + return res; +} +#endif + #if defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_KEY_EXPORT) && \ defined(HAVE_ED448_KEY_IMPORT) static wc_test_ret_t ed448_ctx_test(void) @@ -34488,7 +35167,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed448_test(void) WOLFSSL_SMALL_STACK_STATIC const byte* sigs[] = {sig1, sig2, sig3, sig4, sig5, sig6}; #define SIGSZ sizeof(sig1) - PEDANTIC_EXTENSION WOLFSSL_SMALL_STACK_STATIC const byte msg1[] = { }; + PEDANTIC_EXTENSION WOLFSSL_SMALL_STACK_STATIC const byte msg1[] = { 0 }; WOLFSSL_SMALL_STACK_STATIC const byte msg2[] = { 0x03 }; WOLFSSL_SMALL_STACK_STATIC const byte msg3[] = { 0x64, 0xa6, 0x5f, 0x3c, 0xde, 0xdc, 0xdd, 0x66, 0x81, 0x1e, 0x29, 0x15 }; @@ -34935,6 +35614,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed448_test(void) (void)keySz; (void)sigSz; + ret = ed448_test_check_key(); + if (ret < 0) + return ret; #ifdef WOLFSSL_TEST_CERT ret = ed448_test_cert(); if (ret < 0) @@ -37641,15 +38323,20 @@ static /* not const */ byte xmss_sig[2500] = WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test_verify_only(void) { - XmssKey verifyKey; - word32 pkSz = 0; - word32 sigSz = 0; - const char * param = "XMSS-SHA2_10_256"; - int j = 0; - int ret2 = -1; - int ret = -1; + XmssKey verifyKey; + unsigned char pub_raw[XMSS_SHA256_PUBLEN]; + word32 pub_len = sizeof(pub_raw); + word32 pkSz = 0; + word32 sigSz = 0; + const char * param = "XMSS-SHA2_10_256"; + int j = 0; + int ret2 = -1; + int ret = -1; + int n_diff = 0; WOLFSSL_ENTER("xmss_test_verify_only"); + XMEMSET(pub_raw, 0, sizeof(pub_raw)); + ret = wc_XmssKey_Init(&verifyKey, NULL, INVALID_DEVID); if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); } @@ -37686,6 +38373,27 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test_verify_only(void) return WC_TEST_RET_ENC_EC(ret); } + /* Now test the ExportPubRaw API, verify we recover the original pub. */ + ret = wc_XmssKey_ExportPubRaw(&verifyKey, pub_raw, &pub_len); + if (ret != 0) { + printf("error: wc_XmssKey_ExportPubRaw returned %d, expected 0\n", ret); + return WC_TEST_RET_ENC_EC(ret); + } + + if (pub_len != XMSS_SHA256_PUBLEN) { + printf("error: xmss pub len %u, expected %d\n", pub_len, + XMSS_SHA256_PUBLEN); + return WC_TEST_RET_ENC_EC(pub_len); + } + + n_diff = XMEMCMP(pub_raw, xmss_pub, sizeof(xmss_pub)); + + if (n_diff != 0) { + printf("error: exported and imported pub raw do not match: %d\n", + n_diff); + return WC_TEST_RET_ENC_EC(n_diff); + } + /* Flip bits in message. This should fail. */ xmss_msg[sizeof(xmss_msg) / 2] ^= 1; ret2 = wc_XmssKey_Verify(&verifyKey, xmss_sig, sizeof(xmss_sig), @@ -37892,7 +38600,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void) #endif /* if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) */ #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_SMALL_STACK) -#if defined(WOLFSSL_WC_LMS) && (LMS_MAX_HEIGHT >= 10) +#if (defined(WOLFSSL_WC_LMS) && (LMS_MAX_HEIGHT >= 10)) || \ + defined(HAVE_LIBLMS) /* A simple LMS verify only test. * @@ -38116,18 +38825,23 @@ static byte lms_L1H10W8_sig[LMS_L1H10W8_SIGLEN] = WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test_verify_only(void) { - int ret = -1; - int ret2 = -1; - int j = 0; - LmsKey verifyKey; - word32 sigSz = 0; - word32 msgSz = sizeof(lms_msg); - word32 pubLen = 0; - int levels = 0; - int height = 0; - int winternitz = 0; + LmsKey verifyKey; + unsigned char pub_raw[HSS_MAX_PUBLIC_KEY_LEN]; + word32 pub_len = sizeof(pub_raw); + word32 sigSz = 0; + word32 msgSz = sizeof(lms_msg); + word32 pubSz = 0; + int levels = 0; + int height = 0; + int winternitz = 0; + int ret = -1; + int ret2 = -1; + int j = 0; + int n_diff = 0; WOLFSSL_ENTER("lms_test_verify_only"); + XMEMSET(pub_raw, 0, sizeof(pub_raw)); + ret = wc_LmsKey_Init(&verifyKey, NULL, INVALID_DEVID); if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); } @@ -38148,12 +38862,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test_verify_only(void) return -1; } - ret = wc_LmsKey_GetPubLen(&verifyKey, &pubLen); + ret = wc_LmsKey_GetPubLen(&verifyKey, &pubSz); if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); } - if (pubLen != HSS_MAX_PUBLIC_KEY_LEN) { - printf("error: got %u, expected %d\n", pubLen, HSS_MAX_PUBLIC_KEY_LEN); - return WC_TEST_RET_ENC_EC(pubLen); + if (pubSz != HSS_MAX_PUBLIC_KEY_LEN) { + printf("error: got %u, expected %d\n", pubSz, HSS_MAX_PUBLIC_KEY_LEN); + return WC_TEST_RET_ENC_EC(pubSz); } ret = wc_LmsKey_GetSigLen(&verifyKey, &sigSz); @@ -38171,6 +38885,27 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test_verify_only(void) return WC_TEST_RET_ENC_EC(ret); } + /* Now test the ExportPubRaw API, verify we recover the original pub. */ + ret = wc_LmsKey_ExportPubRaw(&verifyKey, pub_raw, &pub_len); + if (ret != 0) { + printf("error: wc_LmsKey_ExportPubRaw returned %d, expected 0\n", ret); + return WC_TEST_RET_ENC_EC(ret); + } + + if (pub_len != HSS_MAX_PUBLIC_KEY_LEN) { + printf("error: LMS pub len %u, expected %d\n", pub_len, + HSS_MAX_PUBLIC_KEY_LEN); + return WC_TEST_RET_ENC_EC(pub_len); + } + + n_diff = XMEMCMP(pub_raw, lms_L1H10W8_pub, sizeof(lms_L1H10W8_pub)); + + if (n_diff != 0) { + printf("error: exported and imported pub raw do not match: %d\n", + n_diff); + return WC_TEST_RET_ENC_EC(n_diff); + } + /* Flip bits in message. This should fail. */ lms_msg[msgSz / 2] ^= 1; ret2 = wc_LmsKey_Verify(&verifyKey, lms_L1H10W8_sig, LMS_L1H10W8_SIGLEN, @@ -41672,7 +42407,9 @@ static int myOriEncryptCb(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* oriType, int i; /* make sure buffers are large enough */ - if ((*oriValueSz < (2 + cekSz)) || (*oriTypeSz < sizeof(oriType))) + if (*oriValueSz < (2 + cekSz)) + return WC_TEST_RET_ENC_NC; + if (*oriTypeSz < sizeof(asnDataOid)) return WC_TEST_RET_ENC_NC; /* our simple encryption algorithm will be take the bitwise complement */ @@ -50227,8 +50964,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) PRIVATE_KEY_LOCK(); #endif #ifdef HAVE_ED25519 + PRIVATE_KEY_UNLOCK(); if (ret == 0) ret = ed25519_test(); + PRIVATE_KEY_LOCK(); #endif #ifdef HAVE_CURVE25519 if (ret == 0) @@ -50284,8 +51023,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) #endif #ifndef NO_PWDBASED #if defined(HAVE_PBKDF2) && !defined(NO_SHA256) && !defined(NO_HMAC) + PRIVATE_KEY_UNLOCK(); if (ret == 0) ret = pbkdf2_test(); + PRIVATE_KEY_LOCK(); #endif #endif #if defined(WOLFSSL_CMAC) && !defined(NO_AES) diff --git a/wolfssl.vcproj b/wolfssl.vcproj index f9b5e87d0c..02cd2dac3a 100644 --- a/wolfssl.vcproj +++ b/wolfssl.vcproj @@ -235,6 +235,10 @@ RelativePath=".\wolfcrypt\src\des3.c" > + + @@ -251,6 +255,14 @@ RelativePath=".\wolfcrypt\src\error.c" > + + + + @@ -279,6 +291,14 @@ RelativePath=".\wolfcrypt\src\integer.c" > + + + + @@ -343,6 +363,10 @@ RelativePath=".\wolfcrypt\src\sha512.c" > + + @@ -391,6 +415,10 @@ RelativePath=".\wolfcrypt\src\wolfevent.c" > + + + + + @@ -317,6 +320,8 @@ + + @@ -335,6 +340,7 @@ + @@ -346,6 +352,7 @@ + diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 258cb034e2..ea828a84c3 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -343,7 +343,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 +500,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 +686,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 */ @@ -1560,7 +1561,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 @@ -1915,10 +1915,10 @@ enum Misc { #ifdef HAVE_PQC #ifndef MIN_FALCONKEY_SZ - #define MIN_FALCONKEY_SZ 897 + #define MIN_FALCONKEY_SZ 1281 #endif #ifndef MIN_DILITHIUMKEY_SZ - #define MIN_DILITHIUMKEY_SZ 1312 + #define MIN_DILITHIUMKEY_SZ 2528 #endif #endif @@ -2175,9 +2175,9 @@ 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); +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 WOLFSSL_LOCAL int GetPrivateKeySigSize(WOLFSSL* ssl); @@ -2273,6 +2273,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 @@ -2864,7 +2866,7 @@ typedef enum { TLSX_KEY_QUIC_TP_PARAMS = 0x0039, /* RFC 9001, ch. 8.2 */ #endif #ifdef WOLFSSL_DUAL_ALG_CERTS - TLSX_CKS = 0xff92, /* X9.146; ff indcates personal + TLSX_CKS = 0xff92, /* X9.146; ff indicates personal * use and 92 is hex for 146. */ #endif #endif @@ -2986,9 +2988,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) @@ -3575,7 +3577,7 @@ struct WOLFSSL_CTX { int certChainCnt; #endif DerBuffer* privateKey; - byte privateKeyType:6; + byte privateKeyType; byte privateKeyId:1; byte privateKeyLabel:1; int privateKeySz; @@ -3584,7 +3586,10 @@ struct WOLFSSL_CTX { #ifdef WOLFSSL_DUAL_ALG_CERTS DerBuffer* altPrivateKey; byte altPrivateKeyType; + byte altPrivateKeyId:1; + byte altPrivateKeyLabel:1; int altPrivateKeySz; + int altPrivateKeyDevId; #endif /* WOLFSSL_DUAL_ALG_CERTS */ #ifdef OPENSSL_ALL WOLFSSL_EVP_PKEY* privateKeyPKey; @@ -4548,15 +4553,18 @@ 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 */ + 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 */ + 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 */ @@ -5861,6 +5869,8 @@ struct WOLFSSL { #ifdef HAVE_SECRET_CALLBACK SessionSecretCb sessionSecretCb; void* sessionSecretCtx; + TlsSecretCb tlsSecretCb; + void* tlsSecretCtx; #ifdef WOLFSSL_TLS13 Tls13SecretCb tls13SecretCb; void* tls13SecretCtx; @@ -6741,6 +6751,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/wolfssl/openssl/sha.h b/wolfssl/openssl/sha.h index c36441498f..ab38c5c096 100644 --- a/wolfssl/openssl/sha.h +++ b/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/wolfssl/openssl/sha3.h b/wolfssl/openssl/sha3.h index 1b0d63bc51..4407bca61c 100644 --- a/wolfssl/openssl/sha3.h +++ b/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/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 5cd96e26f5..5de9bb1611 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -1337,6 +1337,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) diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 804ec44bbb..e06bf979f7 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -793,9 +793,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 +804,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 @@ -1096,6 +1100,10 @@ WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_load_verify_locations( WOLFSSL_API const char** wolfSSL_get_system_CA_dirs(word32* num); #endif /* !_WIN32 */ WOLFSSL_API int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx); +#if defined(USE_WINDOWS_API) && defined(WOLFSSL_WIN_USER_CA_CERTS) +WOLFSSL_API int wolfSSL_CTX_load_windows_user_CA_certs(WOLFSSL_CTX* ctx, + const char* userStore, const char* userDwFlags, const char* userPvPara); +#endif #ifdef WOLFSSL_TRUST_PEER_CERT WOLFSSL_API int wolfSSL_CTX_trust_peer_cert( WOLFSSL_CTX* ctx, const char* file, int type); @@ -1361,8 +1369,13 @@ 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); +/* This callback is used to set the master secret during resumption */ WOLFSSL_API int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb, void*); +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); @@ -3096,6 +3109,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 +3138,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) @@ -4531,7 +4566,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); @@ -4858,10 +4893,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 +5021,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); diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 1c369cef50..81d135b0a2 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/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,21 @@ 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; + struct XtsAes { + Aes aes; + #ifdef WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS + Aes aes_decrypt; + #endif + Aes tweak; + }; + + #ifndef WC_AESXTS_TYPE_DEFINED + typedef struct XtsAes XtsAes; + #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)) || \ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 01eb03c206..77ce5680c4 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -969,6 +969,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_PQC) + 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 +1018,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_PQC) + 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 @@ -2017,10 +2024,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; @@ -2308,7 +2314,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); @@ -2358,7 +2365,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)) || \ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 0f58152dfe..d3df2a0765 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -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; diff --git a/wolfssl/wolfcrypt/cmac.h b/wolfssl/wolfcrypt/cmac.h index e59df2845f..a92e83207c 100644 --- a/wolfssl/wolfcrypt/cmac.h +++ b/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/wolfssl/wolfcrypt/dh.h b/wolfssl/wolfcrypt/dh.h index e94cb59316..93e8475367 100644 --- a/wolfssl/wolfcrypt/dh.h +++ b/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/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 2d7ee320e1..73f2fa5602 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/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, @@ -508,9 +519,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; diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index 9748d6dfa9..efba65020b 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/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/wolfssl/wolfcrypt/ed448.h b/wolfssl/wolfcrypt/ed448.h index 48011fce61..5884bda131 100644 --- a/wolfssl/wolfcrypt/ed448.h +++ b/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/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 99afb9660b..4a62f25a6d 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/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 */ diff --git a/wolfssl/wolfcrypt/ext_lms.h b/wolfssl/wolfcrypt/ext_lms.h index ccdfdcb30e..fae812fd1a 100644 --- a/wolfssl/wolfcrypt/ext_lms.h +++ b/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/wolfssl/wolfcrypt/ext_xmss.h b/wolfssl/wolfcrypt/ext_xmss.h index 9abf15835e..5f51bf54dd 100644 --- a/wolfssl/wolfcrypt/ext_xmss.h +++ b/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/wolfssl/wolfcrypt/fe_operations.h b/wolfssl/wolfcrypt/fe_operations.h index cdd27db5dd..8a1cab7fe9 100644 --- a/wolfssl/wolfcrypt/fe_operations.h +++ b/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/wolfssl/wolfcrypt/fips_test.h b/wolfssl/wolfcrypt/fips_test.h index dc37477d41..452e651eb4 100644 --- a/wolfssl/wolfcrypt/fips_test.h +++ b/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/wolfssl/wolfcrypt/hmac.h b/wolfssl/wolfcrypt/hmac.h index 929d8b2b0d..7a5c457246 100644 --- a/wolfssl/wolfcrypt/hmac.h +++ b/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,13 @@ 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 + /* 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 +187,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/wolfssl/wolfcrypt/kdf.h b/wolfssl/wolfcrypt/kdf.h index 7fa3c7e786..eb917cb7b4 100644 --- a/wolfssl/wolfcrypt/kdf.h +++ b/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); diff --git a/wolfssl/wolfcrypt/lms.h b/wolfssl/wolfcrypt/lms.h index 483f349c1e..fe87388f26 100644 --- a/wolfssl/wolfcrypt/lms.h +++ b/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/wolfssl/wolfcrypt/mem_track.h b/wolfssl/wolfcrypt/mem_track.h index 585756426c..c6d81633de 100644 --- a/wolfssl/wolfcrypt/mem_track.h +++ b/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/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index 9a1d7b06d2..714f565574 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -216,17 +216,22 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, byte haFlag; /* flag used for checking handshake count */ } WOLFSSL_HEAP_HINT; + 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); 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 +277,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/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h index 72905c936c..8747f1655b 100644 --- a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h +++ b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h @@ -200,7 +200,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. ** @@ -820,8 +820,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 { \ diff --git a/wolfssl/wolfcrypt/port/Renesas/renesas-fspsm-crypt.h b/wolfssl/wolfcrypt/port/Renesas/renesas-fspsm-crypt.h index 9671fafa91..e719b93f59 100644 --- a/wolfssl/wolfcrypt/port/Renesas/renesas-fspsm-crypt.h +++ b/wolfssl/wolfcrypt/port/Renesas/renesas-fspsm-crypt.h @@ -123,7 +123,7 @@ WOLFSSL_LOCAL int wc_fspsm_Open(); WOLFSSL_LOCAL void wc_fspsm_Close(); WOLFSSL_LOCAL int wc_fspsm_hw_lock(); WOLFSSL_LOCAL void wc_fspsm_hw_unlock( void ); -WOLFSSL_LOCAL int wc_fspsm_usable(const struct WOLFSSL *ssl, +WOLFSSL_LOCAL int wc_fspsm_usable(const struct WOLFSSL *ssl, uint8_t session_key_generated); typedef struct { @@ -319,7 +319,7 @@ WOLFSSL_API int FSPSM_CALLBACK_CTX_FUNC(struct WOLFSSL* ssl, void* user_ctx); WOLFSSL_API void FSPSM_INFORM_CERT_SIGN(const uint8_t *sign); -#endif /* WOLFSSL_RENESAS_FSPSM_TLS && +#endif /* WOLFSSL_RENESAS_FSPSM_TLS && * !WOLFSSL_RENESAS_FSPSM_CRYPT_ONLY */ typedef struct FSPSM_RSA_CTX { diff --git a/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h b/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h index 6b1bbfdae9..43030a2cb3 100644 --- a/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h +++ b/wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h @@ -32,7 +32,7 @@ #if defined(WOLFSSL_RENESAS_TSIP) || \ defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY) - #include "r_tsip_rx_if.h" + #include "r_tsip_rx_if.h" #endif @@ -93,7 +93,7 @@ typedef enum { #ifdef WOLFSSL_RENESAS_TSIP_CRYPTONLY TSIP_KEY_TYPE_RSA1024 = 3, #endif - + } wolfssl_TSIP_KEY_TYPE; struct WOLFSSL; @@ -101,11 +101,11 @@ struct KeyShareEntry; /* MsgBag stands for message bag and acts as a buffer for holding plain text * handshake messages exchanged between client and server. - * MsgBag was introduced as a workaround for the TSIP's limitation that TSIP + * MsgBag was introduced as a workaround for the TSIP's limitation that TSIP * can not process multiple hash algorithms at the same time. If the - * limitation is resolved in a future TSIP, MsgBag should be removed. + * limitation is resolved in a future TSIP, MsgBag should be removed. * The contents in this MsgBag is used for transcript hashing. The hash value - * is used for the key derivation and Finished-message. + * is used for the key derivation and Finished-message. * The capacity of the MsgBag is defined as MSGBAG_SIZE and the actual * size is 8KB. The size should be large enough to hold all the handshake * messages including the server and client certificate messages. @@ -121,9 +121,9 @@ typedef struct MsgBag } MsgBag; #ifdef WOLFSSL_RENESAS_TSIP_CRYPTONLY - + typedef void* renesas_tsip_key; - + /* flags Crypt Only */ struct tsip_keyflgs_cryt { uint8_t aes256_key_set:1; @@ -147,7 +147,7 @@ typedef struct TsipUserCtx { /* public key index for verification of RootCA cert */ uint32_t user_key_id; - + /* WOLFSSL object associated with */ struct WOLFSSL* ssl; struct WOLFSSL_CTX* ctx; @@ -183,10 +183,10 @@ typedef struct TsipUserCtx { /* ECDHE pre-master secret */ tsip_tls13_ephemeral_shared_secret_key_index_t sharedSecret13Idx; - + /* Handshake secret for Tls13 handshake */ tsip_tls13_ephemeral_handshake_secret_key_index_t handshakeSecret13Idx; - + /* the key to decrypt server-finished message */ tsip_tls13_ephemeral_server_finished_key_index_t serverFinished13Idx; @@ -226,12 +226,12 @@ typedef struct TsipUserCtx { /* signature data area for TLS1.3 CertificateVerify message */ byte sigDataCertVerify[TSIP_TLS_MAX_SIGDATA_SZ]; - + #if (WOLFSSL_RENESAS_TSIP_VER >=109) /* out from R_SCE_TLS_ServerKeyExchangeVerify */ uint32_t encrypted_ephemeral_ecdh_public_key[ENCRYPTED_ECDHE_PUBKEY_SZ]; - - /* ephemeral ECDH pubkey index + + /* ephemeral ECDH pubkey index * got from R_TSIP_GenerateTlsP256EccKeyIndex. * Input to R_TSIP_TlsGeneratePreMasterSecretWithEccP256Key. */ @@ -251,33 +251,33 @@ typedef struct TsipUserCtx { #endif /* WOLFSSL_RENESAS_TSIP_TLS */ /* for tsip crypt only mode */ #ifdef WOLFSSL_RENESAS_TSIP_CRYPTONLY - + renesas_tsip_key rsa1024pri_keyIdx; renesas_tsip_key rsa1024pub_keyIdx; renesas_tsip_key rsa2048pri_keyIdx; renesas_tsip_key rsa2048pub_keyIdx; - + /* sign/verify hash type : * md5, sha1 or sha256 */ int sing_hash_type; - + /* flags shows status if tsip keys are installed */ union { uint8_t chr; struct tsip_keyflgs_cryt bits; } keyflgs_crypt; - + #endif /* installed key handling */ tsip_aes_key_index_t user_aes256_key_index; uint8_t user_aes256_key_set:1; tsip_aes_key_index_t user_aes128_key_index; uint8_t user_aes128_key_set:1; - + /* TSIP defined cipher suite number */ uint32_t tsip_cipher; - + /* flags */ #ifdef WOLFSSL_RENESAS_TSIP_TLS #if !defined(NO_RSA) @@ -315,7 +315,7 @@ typedef TsipUserCtx user_PKCbInfo; typedef struct { - TsipUserCtx* userCtx; + TsipUserCtx* userCtx; } TsipPKCbInfo; @@ -387,12 +387,12 @@ WOLFSSL_API void tsip_inform_user_keys_ex( byte* provisioning_key, /* key got from DLM server */ byte* iv, /* iv used for public key */ byte* encrypted_public_key,/*RSA2048 or ECDSAp256 public key*/ - word32 public_key_type); /* 0: RSA-2048 2:ECDSA P-256 */ + word32 public_key_type); /* 0: RSA-2048 2:ECDSA P-256 */ #else WOLFSSL_API void tsip_inform_user_keys( - byte* encrypted_session_key, + byte* encrypted_session_key, byte* iv, byte* encrypted_user_tls_key); @@ -404,7 +404,7 @@ WOLFSSL_API void tsip_inform_user_keys( WOLFSSL_LOCAL int tsip_SignRsaPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc); WOLFSSL_LOCAL int tsip_VerifyRsaPkcsCb( - WOLFSSL* ssl, + WOLFSSL* ssl, unsigned char* sig, unsigned int sigSz, unsigned char** out, const unsigned char* keyDer, unsigned int keySz, @@ -427,7 +427,7 @@ WOLFSSL_LOCAL int tsip_GetMessageSha256(struct WOLFSSL* ssl, byte* hash, WOLFSSL_LOCAL int tsip_Tls13GetHmacMessages(struct WOLFSSL* ssl, byte* mac); -WOLFSSL_LOCAL int tsip_Tls13GenEccKeyPair(struct WOLFSSL* ssl, +WOLFSSL_LOCAL int tsip_Tls13GenEccKeyPair(struct WOLFSSL* ssl, struct KeyShareEntry* kse); WOLFSSL_LOCAL int tsip_Tls13GenSharedSecret(struct WOLFSSL* ssl, @@ -466,13 +466,13 @@ WOLFSSL_LOCAL int tsip_Tls13VerifyHandshake(struct WOLFSSL* ssl, const byte* input, byte* hash, word32* pHashSz); -WOLFSSL_LOCAL int tsip_Tls13AesDecrypt(struct WOLFSSL* ssl, +WOLFSSL_LOCAL int tsip_Tls13AesDecrypt(struct WOLFSSL* ssl, byte* output, const byte* input, word16 sz); WOLFSSL_LOCAL int tsip_Tls13AesEncrypt(struct WOLFSSL* ssl, byte* output, const byte* input, word16 sz); -WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, +WOLFSSL_LOCAL int tsip_Tls13CertificateVerify(struct WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 totalSz); @@ -483,7 +483,7 @@ WOLFSSL_LOCAL int tsip_Tls13SendCertVerify(struct WOLFSSL*ssl); #if (WOLFSSL_RENESAS_TSIP_VER >=109) -WOLFSSL_LOCAL int wc_tsip_AesCipher(int devIdArg, struct wc_CryptoInfo* info, +WOLFSSL_LOCAL int wc_tsip_AesCipher(int devIdArg, struct wc_CryptoInfo* info, void* ctx); WOLFSSL_LOCAL int wc_tsip_generateMasterSecretEx( byte cipherSuiteFirst, @@ -530,7 +530,7 @@ WOLFSSL_LOCAL int wc_tsip_RsaVerify( void* ctx); WOLFSSL_LOCAL int wc_tsip_EccVerify( - WOLFSSL* ssl, + WOLFSSL* ssl, const byte* sig, word32 sigSz, const byte* hash, word32 hashSz, const byte* key, word32 keySz, @@ -553,7 +553,7 @@ WOLFSSL_LOCAL int wc_tsip_AesCbcDecrypt( byte* out, const byte* in, word32 sz); - + WOLFSSL_LOCAL int wc_tsip_AesGcmEncrypt( Aes* aes, byte* out, const byte* in, word32 sz, @@ -561,7 +561,7 @@ WOLFSSL_LOCAL int wc_tsip_AesGcmEncrypt( byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz, void* ctx); - + WOLFSSL_LOCAL int wc_tsip_AesGcmDecrypt( Aes* aes, byte* out, const byte* in, word32 sz, @@ -572,17 +572,17 @@ WOLFSSL_LOCAL int wc_tsip_AesGcmDecrypt( #endif /* NO_AES */ WOLFSSL_LOCAL int wc_tsip_ShaXHmacVerify( const WOLFSSL *ssl, - const byte* message, + const byte* message, word32 messageSz, word32 macSz, word32 content); WOLFSSL_LOCAL int wc_tsip_Sha1HmacGenerate( const WOLFSSL *ssl, - const byte* myInner, + const byte* myInner, word32 innerSz, const byte* in, - word32 sz, + word32 sz, byte* digest); WOLFSSL_LOCAL int wc_tsip_Sha256HmacGenerate( @@ -605,7 +605,7 @@ WOLFSSL_LOCAL int tsip_usable(const WOLFSSL *ssl, uint8_t session_key_generated); WOLFSSL_LOCAL void tsip_inform_sflash_signedcacert( - const byte* ps_flash, + const byte* ps_flash, const byte* psigned_ca_cert, word32 len); @@ -636,7 +636,7 @@ WOLFSSL_LOCAL int wc_tsip_generateSessionKey( int devId); WOLFSSL_LOCAL int wc_tsip_MakeRsaKey(int size, void* ctx); -WOLFSSL_LOCAL int wc_tsip_RsaVerifyPkcs(wc_CryptoInfo* info, +WOLFSSL_LOCAL int wc_tsip_RsaVerifyPkcs(wc_CryptoInfo* info, TsipUserCtx* tuc); WOLFSSL_LOCAL int wc_tsip_GenerateRandBlock(byte* output, word32 size); diff --git a/wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h b/wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h index 1213eeee85..e269115572 100644 --- a/wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h +++ b/wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h @@ -36,12 +36,12 @@ WOLFSSL_LOCAL int Renesas_cmn_EccSignCb(WOLFSSL* ssl, const unsigned char* keyDer, unsigned int keySz, void* ctx); WOLFSSL_LOCAL int Renesas_cmn_genMasterSecret(WOLFSSL* ssl, void* ctx); -WOLFSSL_LOCAL int Renesas_cmn_generatePremasterSecret(WOLFSSL* ssl, +WOLFSSL_LOCAL int Renesas_cmn_generatePremasterSecret(WOLFSSL* ssl, byte *premaster, word32 preSz, void* ctx); -WOLFSSL_LOCAL int Renesas_cmn_RsaEnc(WOLFSSL* ssl, const unsigned char* in, +WOLFSSL_LOCAL int Renesas_cmn_RsaEnc(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, unsigned char* out, word32* outSz, const unsigned char* keyDer, unsigned int keySz, void* ctx); -WOLFSSL_LOCAL int Renesas_cmn_VerifyHmac(WOLFSSL *ssl, const byte* message, +WOLFSSL_LOCAL int Renesas_cmn_VerifyHmac(WOLFSSL *ssl, const byte* message, word32 messageSz, word32 macSz, word32 content, void* ctx); WOLFSSL_LOCAL int Renesas_cmn_EccVerify(WOLFSSL* ssl, const unsigned char* sig, unsigned int sigSz, const unsigned char* hash, unsigned int hashSz, @@ -55,7 +55,7 @@ WOLFSSL_LOCAL int Renesas_cmn_RsaSignCheckCb(WOLFSSL* ssl, unsigned char** out, const unsigned char* keyDer, unsigned int keySz, void* ctx); - + WOLFSSL_LOCAL int Renesas_cmn_TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz, int content, int verify, int epochOrder); WOLFSSL_LOCAL int Renesas_cmn_usable(const WOLFSSL *ssl, byte seskey_gennerated); @@ -71,8 +71,8 @@ WOLFSSL_LOCAL int Renesas_cmn_SigPkCbEccVerify(const unsigned char* sig, unsigne WOLFSSL_LOCAL void* Renesas_cmn_GetCbCtxBydevId(int devId); int wc_CryptoCb_CryptInitRenesasCmn(WOLFSSL* ssl, void* ctx); void wc_CryptoCb_CleanupRenesasCmn(int* id); -int wc_Renesas_cmn_RootCertVerify(const byte* cert, word32 cert_len, - word32 key_n_start, word32 key_n_len, word32 key_e_start, +int wc_Renesas_cmn_RootCertVerify(const byte* cert, word32 cert_len, + word32 key_n_start, word32 key_n_len, word32 key_e_start, word32 key_e_len, word32 cm_row); WOLFSSL_LOCAL int Renesas_cmn_Cleanup(WOLFSSL* ssl); WOLFSSL_LOCAL byte Renesas_cmn_checkCA(word32 cmIdx); diff --git a/wolfssl/wolfcrypt/port/Renesas/renesas_tsip_types.h b/wolfssl/wolfcrypt/port/Renesas/renesas_tsip_types.h index 93738780af..d340a1d3f7 100644 --- a/wolfssl/wolfcrypt/port/Renesas/renesas_tsip_types.h +++ b/wolfssl/wolfcrypt/port/Renesas/renesas_tsip_types.h @@ -19,7 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - + #ifndef __RENESAS_TSIP_TYPES_H__ #define __RENESAS_TSIP_TYPES_H__ @@ -48,7 +48,7 @@ typedef struct { #if defined(WOLF_CRYPTO_CB) word32 flags; int devId; -#endif +#endif } wolfssl_TSIP_Hash; /* RAW hash function APIs are not implemented with TSIP */ diff --git a/wolfssl/wolfcrypt/port/caam/wolfcaam.h b/wolfssl/wolfcrypt/port/caam/wolfcaam.h index 6c96edc416..1123ecba4b 100644 --- a/wolfssl/wolfcrypt/port/caam/wolfcaam.h +++ b/wolfssl/wolfcrypt/port/caam/wolfcaam.h @@ -36,7 +36,7 @@ #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_SECO_CAAM) || \ - defined(WOLFSSL_IMXRT1170_CAAM) + defined(WOLFSSL_IMXRT1170_CAAM) /* unique devId for CAAM use on crypto callbacks */ @@ -75,9 +75,9 @@ WOLFSSL_LOCAL int caamWriteToPartition(CAAM_ADDRESS addr, const unsigned char* i WOLFSSL_LOCAL int caamReadPartition(CAAM_ADDRESS addr, unsigned char* out, int outSz); WOLFSSL_API int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, - word32* outSz); + word32* outSz); WOLFSSL_API int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, - word32* outSz); + word32* outSz); WOLFSSL_API int wc_caamOpenBlob_ex(byte* data, word32 dataSz, byte* out, word32* outSz, int type, byte* mod, word32 modSz); @@ -97,7 +97,7 @@ WOLFSSL_API int wc_caamCoverKey(byte* in, word32 inSz, byte* out, word32* outSz, #define WC_CAAM_MAX_ENTROPY 44 #if !defined(WOLFSSL_QNX_CAAM) && !defined(WOLFSSL_SECO_CAAM) && \ - !defined(WOLFSSL_IMXRT1170_CAAM) + !defined(WOLFSSL_IMXRT1170_CAAM) WOLFSSL_API int wc_caamSetResource(IODevice ioDev); #ifndef WC_CAAM_READ #define WC_CAAM_READ(reg) wc_caamReadRegister((reg)) diff --git a/wolfssl/wolfcrypt/port/liboqs/liboqs.h b/wolfssl/wolfcrypt/port/liboqs/liboqs.h index 58da9ba2be..b558f51846 100644 --- a/wolfssl/wolfcrypt/port/liboqs/liboqs.h +++ b/wolfssl/wolfcrypt/port/liboqs/liboqs.h @@ -43,7 +43,7 @@ implementations for Post-Quantum cryptography algorithms. #if defined(HAVE_LIBOQS) #include "oqs/oqs.h" - + int wolfSSL_liboqsInit(void); diff --git a/wolfssl/wolfcrypt/port/nxp/ksdk_port.h b/wolfssl/wolfcrypt/port/nxp/ksdk_port.h index c272a96971..98f9ff2002 100644 --- a/wolfssl/wolfcrypt/port/nxp/ksdk_port.h +++ b/wolfssl/wolfcrypt/port/nxp/ksdk_port.h @@ -34,13 +34,13 @@ int ksdk_port_init(void); /* software algorithm, by wolfcrypt */ #if defined(FREESCALE_LTC_TFM) - int wolfcrypt_mp_mul(mp_int *A, mp_int *B, mp_int *C); - int wolfcrypt_mp_mod(mp_int *a, mp_int *b, mp_int *c); - int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); - int wolfcrypt_mp_mod(mp_int *a, mp_int *b, mp_int *c); - int wolfcrypt_mp_invmod(mp_int *a, mp_int *b, mp_int *c); - int wolfcrypt_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y); - int wolfcrypt_mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng); + int wolfcrypt_mp_mul(mp_int *A, mp_int *B, mp_int *C); + int wolfcrypt_mp_mod(mp_int *a, mp_int *b, mp_int *c); + int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + int wolfcrypt_mp_mod(mp_int *a, mp_int *b, mp_int *c); + int wolfcrypt_mp_invmod(mp_int *a, mp_int *b, mp_int *c); + int wolfcrypt_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y); + int wolfcrypt_mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng); /* Exported mp_mulmod function */ int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); @@ -48,40 +48,40 @@ int ksdk_port_init(void); #endif /* FREESCALE_LTC_TFM */ #if defined(FREESCALE_LTC_ECC) - #include "fsl_ltc.h" + #include "fsl_ltc.h" - typedef enum _fsl_ltc_ecc_coordinate_system - { - kLTC_Weierstrass = 0U, /*< Point coordinates on an elliptic curve in Weierstrass form */ - kLTC_Curve25519 = 1U, /*< Point coordinates on an Curve25519 elliptic curve in Montgomery form */ - kLTC_Ed25519 = 2U, /*< Point coordinates on an Ed25519 elliptic curve in twisted Edwards form */ - } fsl_ltc_ecc_coordinate_system_t; + typedef enum _fsl_ltc_ecc_coordinate_system + { + kLTC_Weierstrass = 0U, /*< Point coordinates on an elliptic curve in Weierstrass form */ + kLTC_Curve25519 = 1U, /*< Point coordinates on an Curve25519 elliptic curve in Montgomery form */ + kLTC_Ed25519 = 2U, /*< Point coordinates on an Ed25519 elliptic curve in twisted Edwards form */ + } fsl_ltc_ecc_coordinate_system_t; - int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m); + int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m); - #ifdef HAVE_CURVE25519 - int nxp_ltc_curve25519(ECPoint *q, const byte *n, const ECPoint *p, fsl_ltc_ecc_coordinate_system_t type); - const ECPoint *nxp_ltc_curve25519_GetBasePoint(void); - status_t LTC_PKHA_Curve25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); - status_t LTC_PKHA_WeierstrassToCurve25519(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); - status_t LTC_PKHA_Curve25519ComputeY(ltc_pkha_ecc_point_t *ltcPoint); - #endif + #ifdef HAVE_CURVE25519 + int nxp_ltc_curve25519(ECPoint *q, const byte *n, const ECPoint *p, fsl_ltc_ecc_coordinate_system_t type); + const ECPoint *nxp_ltc_curve25519_GetBasePoint(void); + status_t LTC_PKHA_Curve25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_WeierstrassToCurve25519(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_Curve25519ComputeY(ltc_pkha_ecc_point_t *ltcPoint); + #endif - #ifdef HAVE_ED25519 - status_t LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); - status_t LTC_PKHA_WeierstrassToEd25519(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); - status_t LTC_PKHA_Ed25519_PointMul(const ltc_pkha_ecc_point_t *ltcPointIn, - const uint8_t *N, - size_t sizeN, - ltc_pkha_ecc_point_t *ltcPointOut, - fsl_ltc_ecc_coordinate_system_t typeOut); - const ltc_pkha_ecc_point_t *LTC_PKHA_Ed25519_BasePoint(void); - status_t LTC_PKHA_Ed25519_PointDecompress(const uint8_t *pubkey, size_t pubKeySize, ltc_pkha_ecc_point_t *ltcPointOut); - status_t LTC_PKHA_sc_reduce(uint8_t *a); - status_t LTC_PKHA_sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b, const uint8_t *c); - status_t LTC_PKHA_SignatureForVerify(uint8_t *rcheck, const unsigned char *a, const unsigned char *b, ed25519_key *key); - status_t LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t *ltcPointIn, uint8_t *p); - #endif + #ifdef HAVE_ED25519 + status_t LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_WeierstrassToEd25519(const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_Ed25519_PointMul(const ltc_pkha_ecc_point_t *ltcPointIn, + const uint8_t *N, + size_t sizeN, + ltc_pkha_ecc_point_t *ltcPointOut, + fsl_ltc_ecc_coordinate_system_t typeOut); + const ltc_pkha_ecc_point_t *LTC_PKHA_Ed25519_BasePoint(void); + status_t LTC_PKHA_Ed25519_PointDecompress(const uint8_t *pubkey, size_t pubKeySize, ltc_pkha_ecc_point_t *ltcPointOut); + status_t LTC_PKHA_sc_reduce(uint8_t *a); + status_t LTC_PKHA_sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b, const uint8_t *c); + status_t LTC_PKHA_SignatureForVerify(uint8_t *rcheck, const unsigned char *a, const unsigned char *b, ed25519_key *key); + status_t LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t *ltcPointIn, uint8_t *p); + #endif #endif /* FREESCALE_LTC_ECC */ diff --git a/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h b/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h index 433b73abe1..a2d4928ae6 100644 --- a/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h +++ b/wolfssl/wolfcrypt/port/xilinx/xil-sha3.h @@ -35,7 +35,7 @@ #endif /* Sha3 digest */ -typedef struct Sha3 { +typedef struct wc_Sha3 { #ifdef WOLFSSL_XILINX_CRYPT_VERSAL wc_Xsecure xSec; #else diff --git a/wolfssl/wolfcrypt/pwdbased.h b/wolfssl/wolfcrypt/pwdbased.h index fb75f4493b..bcf09399f6 100644 --- a/wolfssl/wolfcrypt/pwdbased.h +++ b/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/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index d4ab8e338b..9dd6163289 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/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/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 3daa02c57f..0f31c86054 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/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 diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index bc544c70bd..0ec26c0b4d 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -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 @@ -995,8 +1051,14 @@ 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) @@ -2008,6 +2070,7 @@ extern void uITRON4_free(void *p) ; #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 +2755,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 */ @@ -2833,6 +2898,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 @@ -3194,6 +3262,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] @@ -3312,11 +3387,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) @@ -3438,6 +3521,10 @@ extern void uITRON4_free(void *p) ; #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 +3537,20 @@ extern void uITRON4_free(void *p) ; #endif #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/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index e8bcc9b0de..eb599abed4 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/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/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 323c53adfa..d8239c2e34 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/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)) @@ -182,6 +186,11 @@ struct wc_Sha256 { 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/wolfssl/wolfcrypt/sha3.h b/wolfssl/wolfcrypt/sha3.h index 2b9283a03e..149c714c49 100644 --- a/wolfssl/wolfcrypt/sha3.h +++ b/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,12 @@ struct wc_Sha3 { void* heap; +#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 +146,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); diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index 7592c46880..96bbc28e4e 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/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,6 +151,9 @@ 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 */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 01ed929f49..89f01e2597 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -430,6 +430,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 */ @@ -1633,6 +1636,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/wolfssl/wolfcrypt/xmss.h b/wolfssl/wolfcrypt/xmss.h index 7f19aee2bf..37aab34d00 100644 --- a/wolfssl/wolfcrypt/xmss.h +++ b/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/wrapper/Ada/.gitignore b/wrapper/Ada/.gitignore new file mode 100644 index 0000000000..b672fdeaf3 --- /dev/null +++ b/wrapper/Ada/.gitignore @@ -0,0 +1 @@ +obj diff --git a/wrapper/Ada/README.md b/wrapper/Ada/README.md index 0af9eafc02..76f4b8e8bd 100644 --- a/wrapper/Ada/README.md +++ b/wrapper/Ada/README.md @@ -2,7 +2,7 @@ The source code for the Ada/SPARK binding of the WolfSSL library is the WolfSSL Ada package in the wolfssl.ads and wolfssl.adb files. -The source code here also demonstrates a TLS v1.3 server and client +The source code here also demonstrates a (D)TLS v1.3 server and client using the WolfSSL Ada binding. The implementation is cross-platform and compiles on Linux, Mac OS X and Windows. @@ -15,7 +15,8 @@ for the secondary stack. The GNAT User's Guide recommends avoiding the secondary stack using the restriction No_Secondary_Stack (see the GNAT configuration file gnat.adc which instructs compilation of the WolfSSL Ada binding under -this restriction). +this restriction). Note, however, that the examples do make use of the +secondary stack. Portability: The WolfSSL Ada binding makes no usage of controlled types and has no dependency upon the Ada.Finalization package. @@ -91,13 +92,13 @@ Make sure the executables for the compiler and GPRBuild are on the PATH and use gprbuild to build the source code. ## Files -The TLS v1.3 client example in the Ada/SPARK programming language +The (D)TLS v1.3 client example in the Ada/SPARK programming language using the WolfSSL library can be found in the files: tls_client_main.adb tls_client.ads tls_client.adb -The TLS v1.3 server example in the Ada/SPARK programming language +The (D)TLS v1.3 server example in the Ada/SPARK programming language using the WolfSSL library can be found in the files: tls_server_main.adb tls_server.ads diff --git a/wrapper/Ada/default.gpr b/wrapper/Ada/default.gpr index bbd3b34f1e..42dcd745c0 100644 --- a/wrapper/Ada/default.gpr +++ b/wrapper/Ada/default.gpr @@ -26,10 +26,6 @@ project Default is for Spec_Suffix ("C") use ".h"; end Naming; - package Builder is - for Global_Configuration_Pragmas use "gnat.adc"; - end Builder; - package Compiler is for Switches ("C") use ("-DWOLFSSL_USER_SETTINGS", -- Use the user_settings.h file. diff --git a/wrapper/Ada/spark_sockets.adb b/wrapper/Ada/spark_sockets.adb index e315f230e3..a662a010d9 100644 --- a/wrapper/Ada/spark_sockets.adb +++ b/wrapper/Ada/spark_sockets.adb @@ -19,6 +19,7 @@ -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA -- +with Ada.Streams; with Interfaces.C; package body SPARK_Sockets is @@ -33,16 +34,35 @@ package body SPARK_Sockets is return (Exists => False); end Inet_Addr; - procedure Create_Socket (Socket : in out Optional_Socket) is + procedure Create_Socket + (Socket : in out Optional_Socket; + Family : GNAT.Sockets.Family_Type; + Mode : GNAT.Sockets.Mode_Type) is S : Socket_Type; begin - GNAT.Sockets.Create_Socket (S); + GNAT.Sockets.Create_Socket (S, Family, Mode); Socket := (Exists => True, Socket => S); exception when others => Socket := (Exists => False); end Create_Socket; + procedure Create_Stream_Socket (Socket : in out Optional_Socket) is + begin + Create_Socket + (Socket => Socket, + Family => GNAT.Sockets.Family_Inet, + Mode => GNAT.Sockets.Socket_Stream); + end Create_Stream_Socket; + + procedure Create_Datagram_Socket (Socket : in out Optional_Socket) is + begin + Create_Socket + (Socket => Socket, + Family => GNAT.Sockets.Family_Inet, + Mode => GNAT.Sockets.Socket_Datagram); + end Create_Datagram_Socket; + function Connect_Socket (Socket : Socket_Type; Server : Sock_Addr_Type) return Subprogram_Result is @@ -99,6 +119,22 @@ package body SPARK_Sockets is return Failure; end Listen_Socket; + function Receive_Socket + (Socket : Socket_Type) + return Subprogram_Result is + + Item : Ada.Streams.Stream_Element_Array (1 .. 4096); + Last : Ada.Streams.Stream_Element_Offset; + From : GNAT.Sockets.Sock_Addr_Type; + + begin + GNAT.Sockets.Receive_Socket (Socket, Item, Last, From); + return Success; + exception + when others => + return Failure; + end Receive_Socket; + procedure Accept_Socket (Server : Socket_Type; Socket : out Optional_Socket; Address : out Sock_Addr_Type; diff --git a/wrapper/Ada/spark_sockets.ads b/wrapper/Ada/spark_sockets.ads index ee9864c6ff..5ac2998630 100644 --- a/wrapper/Ada/spark_sockets.ads +++ b/wrapper/Ada/spark_sockets.ads @@ -83,7 +83,10 @@ package SPARK_Sockets with SPARK_Mode is end case; end record; - procedure Create_Socket (Socket : in out Optional_Socket) with + procedure Create_Stream_Socket (Socket : in out Optional_Socket) with + Pre => not Socket.Exists; + + procedure Create_Datagram_Socket (Socket : in out Optional_Socket) with Pre => not Socket.Exists; function Connect_Socket (Socket : Socket_Type; @@ -116,6 +119,8 @@ package SPARK_Sockets with SPARK_Mode is -- appropriate in usual cases. It can be adjusted according to each -- application's particular requirements. + function Receive_Socket (Socket : Socket_Type) return Subprogram_Result; + procedure Accept_Socket (Server : Socket_Type; Socket : out Optional_Socket; Address : out Sock_Addr_Type; diff --git a/wrapper/Ada/tls_client.adb b/wrapper/Ada/tls_client.adb index 88f5a60df2..3ec39320a5 100644 --- a/wrapper/Ada/tls_client.adb +++ b/wrapper/Ada/tls_client.adb @@ -47,12 +47,18 @@ package body Tls_Client with SPARK_Mode is Ada.Text_IO.Put (Text); end Put; - procedure Put (Number : Natural) is + procedure Put (Number : Natural) + with + Annotate => (GNATprove, Might_Not_Return) + is begin Natural_IO.Put (Item => Number, Width => 0, Base => 10); end Put; - procedure Put (Number : Byte_Index) is + procedure Put (Number : Byte_Index) + with + Annotate => (GNATprove, Might_Not_Return) + is begin Natural_IO.Put (Item => Natural (Number), Width => 0, Base => 10); end Put; @@ -137,6 +143,7 @@ package body Tls_Client with SPARK_Mode is Output : WolfSSL.Write_Result; Result : WolfSSL.Subprogram_Result; + DTLS : Boolean; begin Result := WolfSSL.Initialize; if Result /= Success then @@ -144,14 +151,29 @@ package body Tls_Client with SPARK_Mode is return; end if; - if Argument_Count < 1 then - Put_Line ("usage: tcl_client "); + if Argument_Count < 1 + or Argument_Count > 2 + or (Argument_Count = 2 and then Argument (2) /= "--dtls") + then + Put_Line ("usage: tls_client_main [--dtls]"); return; end if; - SPARK_Sockets.Create_Socket (C); + + DTLS := (SPARK_Terminal.Argument_Count = 2); + + if DTLS then + SPARK_Sockets.Create_Datagram_Socket (C); + else + SPARK_Sockets.Create_Stream_Socket (C); + end if; + if not C.Exists then - Put_Line ("ERROR: Failed to create socket."); - return; + declare + Mode : constant String := (if DTLS then "datagram" else "stream"); + begin + Put_Line ("ERROR: Failed to create " & Mode & " socket."); + return; + end; end if; Addr := SPARK_Sockets.Inet_Addr (Argument (1)); @@ -167,18 +189,26 @@ package body Tls_Client with SPARK_Mode is Addr => Addr.Addr, Port => P); - Result := SPARK_Sockets.Connect_Socket (Socket => C.Socket, - Server => A); - if Result /= Success then - Put_Line ("ERROR: Failed to connect to server."); - SPARK_Sockets.Close_Socket (C); - Set (Exit_Status_Failure); - return; + if not DTLS then + Result := SPARK_Sockets.Connect_Socket (Socket => C.Socket, + Server => A); + if Result /= Success then + Put_Line ("ERROR: Failed to connect to server."); + SPARK_Sockets.Close_Socket (C); + Set (Exit_Status_Failure); + return; + end if; end if; -- Create and initialize WOLFSSL_CTX. - WolfSSL.Create_Context (Method => WolfSSL.TLSv1_3_Client_Method, - Context => Ctx); + WolfSSL.Create_Context + (Method => + (if DTLS then + WolfSSL.DTLSv1_3_Client_Method + else + WolfSSL.TLSv1_3_Client_Method), + Context => Ctx); + if not WolfSSL.Is_Valid (Ctx) then Put_Line ("ERROR: failed to create WOLFSSL_CTX."); SPARK_Sockets.Close_Socket (C); @@ -186,6 +216,11 @@ package body Tls_Client with SPARK_Mode is return; end if; + -- Require mutual authentication. + WolfSSL.Set_Verify + (Context => Ctx, + Mode => WolfSSL.Verify_Peer & WolfSSL.Verify_Fail_If_No_Peer_Cert); + -- Load client certificate into WOLFSSL_CTX. Result := WolfSSL.Use_Certificate_File (Context => Ctx, File => CERT_FILE, @@ -241,6 +276,19 @@ package body Tls_Client with SPARK_Mode is return; end if; + if DTLS then + Result := WolfSSL.DTLS_Set_Peer(Ssl => Ssl, + Address => A); + if Result /= Success then + Put_Line ("ERROR: Failed to set the DTLS peer."); + SPARK_Sockets.Close_Socket (C); + WolfSSL.Free (Ssl); + WolfSSL.Free (Context => Ctx); + Set (Exit_Status_Failure); + return; + end if; + end if; + -- Attach wolfSSL to the socket. Result := WolfSSL.Attach (Ssl => Ssl, Socket => SPARK_Sockets.To_C (C.Socket)); diff --git a/wrapper/Ada/tls_client.ads b/wrapper/Ada/tls_client.ads index 50a52b3ccd..aa1ad36e01 100644 --- a/wrapper/Ada/tls_client.ads +++ b/wrapper/Ada/tls_client.ads @@ -32,6 +32,7 @@ package Tls_Client with SPARK_Mode is Pre => (not Client.Exists and not WolfSSL.Is_Valid (Ssl) and not WolfSSL.Is_Valid (Ctx)), Post => (not Client.Exists and not WolfSSL.Is_Valid (Ssl) and - not WolfSSL.Is_Valid (Ctx)); + not WolfSSL.Is_Valid (Ctx)), + Annotate => (GNATprove, Might_Not_Return); end Tls_Client; diff --git a/wrapper/Ada/tls_server.adb b/wrapper/Ada/tls_server.adb index 2858f26fdc..28a032fdcf 100644 --- a/wrapper/Ada/tls_server.adb +++ b/wrapper/Ada/tls_server.adb @@ -105,6 +105,7 @@ package body Tls_Server with SPARK_Mode is Ch : Character; Result : WolfSSL.Subprogram_Result; + DTLS : Boolean; Shall_Continue : Boolean := True; Input : WolfSSL.Read_Result; @@ -117,12 +118,31 @@ package body Tls_Server with SPARK_Mode is return; end if; - SPARK_Sockets.Create_Socket (Socket => L); - if not L.Exists then - Put_Line ("ERROR: Failed to create socket."); + if SPARK_Terminal.Argument_Count > 1 + or (SPARK_Terminal.Argument_Count = 1 + and then SPARK_Terminal.Argument (1) /= "--dtls") + then + Put_Line ("usage: tls_server_main [--dtls]"); return; end if; + DTLS := (SPARK_Terminal.Argument_Count = 1); + + if DTLS then + SPARK_Sockets.Create_Datagram_Socket (Socket => L); + else + SPARK_Sockets.Create_Stream_Socket (Socket => L); + end if; + + if not L.Exists then + declare + Mode : constant String := (if DTLS then "datagram" else "stream"); + begin + Put_Line ("ERROR: Failed to create " & Mode & " socket."); + return; + end; + end if; + Option := (Name => Reuse_Address, Enabled => True); Result := SPARK_Sockets.Set_Socket_Option (Socket => L.Socket, Level => Socket_Level, @@ -144,17 +164,32 @@ package body Tls_Server with SPARK_Mode is return; end if; - Result := SPARK_Sockets.Listen_Socket (Socket => L.Socket, - Length => 5); + if DTLS then + Result := SPARK_Sockets.Receive_Socket (Socket => L.Socket); + else + Result := SPARK_Sockets.Listen_Socket (Socket => L.Socket, + Length => 5); + end if; + if Result /= Success then - Put_Line ("ERROR: Failed to configure listener socket."); - SPARK_Sockets.Close_Socket (L); - return; + declare + Operation : constant String := (if DTLS then "receiver" else "listener"); + begin + Put_Line ("ERROR: Failed to configure " & Operation & " socket."); + SPARK_Sockets.Close_Socket (L); + return; + end; end if; -- Create and initialize WOLFSSL_CTX. - WolfSSL.Create_Context (Method => WolfSSL.TLSv1_3_Server_Method, - Context => Ctx); + WolfSSL.Create_Context + (Method => + (if DTLS then + WolfSSL.DTLSv1_3_Server_Method + else + WolfSSL.TLSv1_3_Server_Method), + Context => Ctx); + if not WolfSSL.Is_Valid (Ctx) then Put_Line ("ERROR: failed to create WOLFSSL_CTX."); SPARK_Sockets.Close_Socket (L); @@ -217,16 +252,18 @@ package body Tls_Server with SPARK_Mode is pragma Loop_Invariant (not WolfSSL.Is_Valid (Ssl)); pragma Loop_Invariant (WolfSSL.Is_Valid (Ctx)); - Put_Line ("Waiting for a connection..."); - SPARK_Sockets.Accept_Socket (Server => L.Socket, - Socket => C, - Address => A, - Result => Result); - if Result /= Success then - Put_Line ("ERROR: failed to accept the connection."); - SPARK_Sockets.Close_Socket (L); - WolfSSL.Free (Context => Ctx); - return; + if not DTLS then + Put_Line ("Waiting for a connection..."); + SPARK_Sockets.Accept_Socket (Server => L.Socket, + Socket => C, + Address => A, + Result => Result); + if Result /= Success then + Put_Line ("ERROR: failed to accept the connection."); + SPARK_Sockets.Close_Socket (L); + WolfSSL.Free (Context => Ctx); + return; + end if; end if; -- Create a WOLFSSL object. @@ -234,32 +271,45 @@ package body Tls_Server with SPARK_Mode is if not WolfSSL.Is_Valid (Ssl) then Put_Line ("ERROR: failed to create WOLFSSL object."); SPARK_Sockets.Close_Socket (L); - SPARK_Sockets.Close_Socket (C); + + if not DTLS then + SPARK_Sockets.Close_Socket (C); + end if; + WolfSSL.Free (Context => Ctx); Set (Exit_Status_Failure); return; end if; -- Attach wolfSSL to the socket. - Result := WolfSSL.Attach (Ssl => Ssl, - Socket => SPARK_Sockets.To_C (C.Socket)); + Result := WolfSSL.Attach + (Ssl => Ssl, + Socket => SPARK_Sockets.To_C (if DTLS then L.Socket else C.Socket)); if Result /= Success then Put_Line ("ERROR: Failed to set the file descriptor."); WolfSSL.Free (Ssl); SPARK_Sockets.Close_Socket (L); - SPARK_Sockets.Close_Socket (C); + + if not DTLS then + SPARK_Sockets.Close_Socket (C); + end if; + WolfSSL.Free (Context => Ctx); Set (Exit_Status_Failure); return; end if; - -- Establish TLS connection. + -- Establish (D)TLS connection. Result := WolfSSL.Accept_Connection (Ssl); if Result /= Success then Put_Line ("Accept error."); WolfSSL.Free (Ssl); SPARK_Sockets.Close_Socket (L); - SPARK_Sockets.Close_Socket (C); + + if not DTLS then + SPARK_Sockets.Close_Socket (C); + end if; + WolfSSL.Free (Context => Ctx); Set (Exit_Status_Failure); return; @@ -268,11 +318,15 @@ package body Tls_Server with SPARK_Mode is Put_Line ("Client connected successfully."); Input := WolfSSL.Read (Ssl); - if not Input.Success then + if not Input.Success then Put_Line ("Read error."); WolfSSL.Free (Ssl); SPARK_Sockets.Close_Socket (L); - SPARK_Sockets.Close_Socket (C); + + if not DTLS then + SPARK_Sockets.Close_Socket (C); + end if; + WolfSSL.Free (Context => Ctx); Set (Exit_Status_Failure); return; @@ -306,15 +360,24 @@ package body Tls_Server with SPARK_Mode is end if; for I in 1 .. 3 loop + Result := WolfSSL.Shutdown (Ssl); - exit when Result = Success; + + exit when DTLS or Result = Success; delay 0.001; -- Delay is expressed in seconds. + end loop; - if Result /= Success then + if not DTLS and then Result /= Success then Put_Line ("ERROR: Failed to shutdown WolfSSL context."); end if; + WolfSSL.Free (Ssl); - SPARK_Sockets.Close_Socket (C); + + if DTLS then + Shall_Continue := False; + else + SPARK_Sockets.Close_Socket (C); + end if; Put_Line ("Shutdown complete."); end loop; diff --git a/wrapper/Ada/user_settings.h b/wrapper/Ada/user_settings.h index df4ada44ec..b66bb3224d 100644 --- a/wrapper/Ada/user_settings.h +++ b/wrapper/Ada/user_settings.h @@ -75,13 +75,9 @@ extern "C" { #define WOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE /* DTLS */ -#if 0 - #define WOLFSSL_DTLS - #define WOLFSSL_MULTICAST - - /* DTLS v1.3 is not yet included with enable-all */ - //#define WOLFSSL_DTLS13 -#endif +#define WOLFSSL_DTLS +// #define WOLFSSL_MULTICAST +#define WOLFSSL_DTLS13 /* DG Disabled SSLv3 and TLSv1.0 - should avoid using */ //#define WOLFSSL_ALLOW_SSLV3 diff --git a/wrapper/Ada/wolfssl.adb b/wrapper/Ada/wolfssl.adb index f1eac8f8ae..068466ae3f 100644 --- a/wrapper/Ada/wolfssl.adb +++ b/wrapper/Ada/wolfssl.adb @@ -19,7 +19,12 @@ -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA -- +pragma Warnings (Off, "* is an internal GNAT unit"); +with GNAT.Sockets.Thin_Common; +pragma Warnings (On, "* is an internal GNAT unit"); +with Interfaces.C.Extensions; with Interfaces.C.Strings; +with System; package body WolfSSL is @@ -97,6 +102,46 @@ package body WolfSSL is return WolfTLSv1_3_Client_Method; end TLSv1_3_Client_Method; + function WolfDTLSv1_2_Server_Method return Method_Type with + Convention => C, + External_Name => "wolfDTLSv1_2_server_method", + Import => True; + + function DTLSv1_2_Server_Method return Method_Type is + begin + return WolfDTLSv1_2_Server_Method; + end DTLSv1_2_Server_Method; + + function WolfDTLSv1_2_Client_Method return Method_Type with + Convention => C, + External_Name => "wolfDTLSv1_2_client_method", + Import => True; + + function DTLSv1_2_Client_Method return Method_Type is + begin + return WolfDTLSv1_2_Client_Method; + end DTLSv1_2_Client_Method; + + function WolfDTLSv1_3_Server_Method return Method_Type with + Convention => C, + External_Name => "wolfDTLSv1_3_server_method", + Import => True; + + function DTLSv1_3_Server_Method return Method_Type is + begin + return WolfDTLSv1_3_Server_Method; + end DTLSv1_3_Server_Method; + + function WolfDTLSv1_3_Client_Method return Method_Type with + Convention => C, + External_Name => "wolfDTLSv1_3_client_method", + Import => True; + + function DTLSv1_3_Client_Method return Method_Type is + begin + return WolfDTLSv1_3_Client_Method; + end DTLSv1_3_Client_Method; + function WolfSSL_CTX_new (Method : Method_Type) return Context_Type with Convention => C, External_Name => "wolfSSL_CTX_new", Import => True; @@ -487,6 +532,41 @@ package body WolfSSL is return Subprogram_Result (Result); end Use_Private_Key_Buffer; + function WolfSSL_DTLS_Set_Peer + (ssl : WolfSSL_Type; + peer : GNAT.Sockets.Thin_Common.Sockaddr_Access; + peerSz : Interfaces.C.unsigned) + return int with + Convention => C, + External_Name => "wolfSSL_dtls_set_peer", + Import => True; + + function DTLS_Set_Peer + (Ssl : WolfSSL_Type; + Address : GNAT.Sockets.Sock_Addr_Type) + return Subprogram_Result is + + Sin : aliased GNAT.Sockets.Thin_Common.Sockaddr; + Length : Interfaces.C.int; + + begin + + GNAT.Sockets.Thin_Common.Set_Address + (Sin => Sin'Unchecked_Access, + Address => Address, + Length => Length); + + pragma Assert (Length >= 0); + + return + Subprogram_Result + (WolfSSL_DTLS_Set_Peer + (ssl => Ssl, + peer => Sin'Unchecked_Access, + peerSz => Interfaces.C.unsigned (Length))); + + end DTLS_Set_Peer; + function WolfSSL_Set_Fd (Ssl : WolfSSL_Type; Fd : int) return int with Convention => C, External_Name => "wolfSSL_set_fd", diff --git a/wrapper/Ada/wolfssl.ads b/wrapper/Ada/wolfssl.ads index a3f536e5d4..3615446308 100644 --- a/wrapper/Ada/wolfssl.ads +++ b/wrapper/Ada/wolfssl.ads @@ -19,6 +19,7 @@ -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA -- +with GNAT.Sockets; with Interfaces.C; -- This package is annotated "with SPARK_Mode" that SPARK can verify @@ -70,6 +71,22 @@ package WolfSSL with SPARK_Mode is -- This function is used to indicate that the application is a client -- and will only support the TLS 1.3 protocol. + function DTLSv1_2_Server_Method return Method_Type; + -- This function is used to indicate that the application is a server + -- and will only support the DTLS 1.2 protocol. + + function DTLSv1_2_Client_Method return Method_Type; + -- This function is used to indicate that the application is a client + -- and will only support the DTLS 1.2 protocol. + + function DTLSv1_3_Server_Method return Method_Type; + -- This function is used to indicate that the application is a server + -- and will only support the DTLS 1.3 protocol. + + function DTLSv1_3_Client_Method return Method_Type; + -- This function is used to indicate that the application is a client + -- and will only support the DTLS 1.3 protocol. + procedure Create_Context (Method : Method_Type; Context : out Context_Type); -- This function creates a new SSL context, taking a desired SSL/TLS @@ -270,6 +287,14 @@ package WolfSSL with SPARK_Mode is -- Format specifies the format type of the buffer; ASN1 or PEM. -- Please see the examples for proper usage. + function DTLS_Set_Peer + (Ssl : WolfSSL_Type; + Address : GNAT.Sockets.Sock_Addr_Type) + return Subprogram_Result with + Pre => Is_Valid (Ssl); + -- This function wraps the corresponding WolfSSL C function to allow + -- clients to use Ada socket types when implementing a DTLS client. + function Attach (Ssl : WolfSSL_Type; Socket : Integer) return Subprogram_Result with diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index ec6dcba2c4..0b26805576 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -1,20 +1,26 @@ if(CONFIG_WOLFSSL) zephyr_interface_library_named(wolfSSL) - + if(CONFIG_WOLFSSL_BUILTIN) - target_compile_definitions(wolfSSL INTERFACE - WOLFSSL_SETTINGS_FILE="${CONFIG_WOLFSSL_SETTINGS_FILE}" - ) - + if(CONFIG_WOLFSSL_SETTINGS_FILE) + target_compile_definitions(wolfSSL INTERFACE + WOLFSSL_SETTINGS_FILE="${CONFIG_WOLFSSL_SETTINGS_FILE}" + ) + zephyr_include_directories( + ${APPLICATION_CONFIG_DIR} + ${APPLICATION_CONFIG_DIR}/src + ) + endif() + zephyr_include_directories( ${ZEPHYR_CURRENT_MODULE_DIR} ${ZEPHYR_CURRENT_MODULE_DIR}/wolfssl ${ZEPHYR_CURRENT_MODULE_DIR}/zephyr ) - + zephyr_library() zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/zephyr/zephyr_init.c) - + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/src/crl.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/src/dtls13.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/src/internal.c) @@ -25,8 +31,29 @@ if(CONFIG_WOLFSSL) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/src/tls.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/src/tls13.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/src/wolfio.c) - + + # FIPS Boundary + if(CONFIG_WOLFCRYPT_FIPS) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wolfcrypt_first.c) + endif() + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/hmac.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/random.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/kdf.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/rsa.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ecc.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/aes.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha256.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha512.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha3.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/dh.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/cmac.c) + if(CONFIG_WOLFCRYPT_FIPS) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fips.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fips_test.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wolfcrypt_last.c) + endif() + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/arc4.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/asm.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/asn.c) @@ -36,7 +63,6 @@ if(CONFIG_WOLFSSL) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/camellia.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/chacha.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/chacha20_poly1305.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/cmac.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/coding.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/compress.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/cpuid.c) @@ -44,10 +70,8 @@ if(CONFIG_WOLFSSL) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/curve25519.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/curve448.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/des3.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/dh.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/dilithium.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/dsa.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ecc.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ecc_fp.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/eccsi.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ed25519.c) @@ -58,15 +82,11 @@ if(CONFIG_WOLFSSL) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fe_448.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fe_low_mem.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fe_operations.c) - #zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fips.c) - #zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fips_test.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ge_448.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ge_low_mem.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ge_operations.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/hash.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/hmac.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/integer.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/kdf.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/logging.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/md2.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/md4.c) @@ -77,15 +97,9 @@ if(CONFIG_WOLFSSL) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/pkcs7.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/poly1305.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/pwdbased.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/random.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ripemd.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/rsa.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sakke.c) #zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/selftest.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha256.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha3.c) - zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha512.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/signature.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/siphash.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sp_arm32.c) @@ -104,8 +118,6 @@ if(CONFIG_WOLFSSL) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_encrypt.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_pkcs11.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_port.c) - #zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wolfcrypt_first.c) - #zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wolfcrypt_last.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wolfevent.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wolfmath.c) @@ -115,7 +127,38 @@ if(CONFIG_WOLFSSL) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/psa/psa_hash.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/psa/psa_pkcbs.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/st/stm32.c) - + + if(CONFIG_WOLFCRYPT_ARMASM) + # tested with board: "qemu_kvm_arm64" + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-aes.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-32-aes-asm_c.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-sha256.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-32-sha256-asm_c.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-sha512.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-sha512-asm_c.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-sha3-asm_c.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-poly1305.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-chacha.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/arm/armv8-curve25519_c.c) + + # Note: The cmake/gcc-m-cpu.cmake make need updated to add "+crypto -mstrict-align" + set(TOOLCHAIN_C_FLAGS "-mcpu=cortex-a53+crypto -mstrict-align") + endif() + + if(CONFIG_WOLFCRYPT_INTELASM) + # tested with board: "qemu_x86_64" + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha256_asm.S) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha512_asm.S) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/sha3_asm.S) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/chacha_asm.S) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/poly1305_asm.S) + + # AESNI + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/aes_asm.S) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/aes_gcm_x86_asm.S) + set(TOOLCHAIN_C_FLAGS "-march=native -maes -msse4 -mpclmul ") + endif() + zephyr_library_link_libraries(wolfSSL) target_compile_definitions(wolfSSL INTERFACE WOLFSSL_ZEPHYR) @@ -125,14 +168,14 @@ if(CONFIG_WOLFSSL) endif() else() assert(CONFIG_WOLFSSL_LIBRARY "wolfSSL was enabled, but neither BUILTIN or LIBRARY was selected.") - + # NB: CONFIG_WOLFSSL_LIBRARY is not regression tested and is # therefore susceptible to bit rot - + target_include_directories(wolfSSL INTERFACE ${CONFIG_WOLFSSL_INSTALL_PATH} ) - + zephyr_link_libraries( wolfssl_external -L${CONFIG_WOLFSSL_INSTALL_PATH} @@ -142,7 +185,7 @@ if(CONFIG_WOLFSSL) # wolfssl to link with gcc we need to ensure it is placed # after wolfssl_external on the linkers command line. endif() - + target_link_libraries(wolfSSL INTERFACE zephyr_interface) endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 6d58cc02e4..5c6fa73ef1 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -53,7 +53,6 @@ endchoice config WOLFSSL_SETTINGS_FILE string "wolfSSL settings file" depends on WOLFSSL_BUILTIN - default "user_settings-tls-generic.h" help Use a specific wolfSSL settings file. The default config file file can be tweaked with Kconfig. The default settings is @@ -64,6 +63,26 @@ config WOLFSSL_SETTINGS_FILE rsource "Kconfig.tls-generic" +config WOLFCRYPT_FIPS + bool "wolfCrypt FIPS support" + depends on WOLFSSL_BUILTIN + help + Enables FIPS support in wolfCrypt. Requires the wolfSSL FIPS ready + download that includes fips.c/fips_test.c. + +config WOLFCRYPT_ARMASM + bool "wolfCrypt ARM Assembly support" + depends on WOLFSSL_BUILTIN + help + wolfCrypt ARM (ARMv8/ARMv7) assembly support for AES, SHA-2, SHA-3, + ChaCha20/Poly1305 and Curve25519 + +config WOLFCRYPT_INTELASM + bool "wolfCrypt Intel Assembly support" + depends on WOLFSSL_BUILTIN + help + wolfCrypt Intel Aassembly support (AVX/AVX2/AESNI) + config WOLFSSL_DEBUG bool "wolfSSL debug activation" depends on WOLFSSL_BUILTIN diff --git a/zephyr/include.am b/zephyr/include.am index 83b69368dd..ef67bcc108 100644 --- a/zephyr/include.am +++ b/zephyr/include.am @@ -8,9 +8,7 @@ EXTRA_DIST+= zephyr/Kconfig.tls-generic EXTRA_DIST+= zephyr/zephyr_init.c EXTRA_DIST+= zephyr/module.yml EXTRA_DIST+= zephyr/wolfssl/options.h -EXTRA_DIST+= zephyr/nrf5340dk_nrf5340_user_settings.h EXTRA_DIST+= zephyr/user_settings.h -EXTRA_DIST+= zephyr/user_settings-tls-generic.h EXTRA_DIST+= zephyr/README.md EXTRA_DIST+= zephyr/samples/wolfssl_benchmark/ EXTRA_DIST+= zephyr/samples/wolfssl_benchmark/CMakeLists.txt diff --git a/zephyr/nrf5340dk_nrf5340_user_settings.h b/zephyr/nrf5340dk_nrf5340_user_settings.h deleted file mode 100644 index a10b54bd23..0000000000 --- a/zephyr/nrf5340dk_nrf5340_user_settings.h +++ /dev/null @@ -1,133 +0,0 @@ -/* nrf5340dk_nrf5340_user_settings.h - * - * 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 - */ - -#ifndef WOLFSSL_OPTIONS_H -#define WOLFSSL_OPTIONS_H - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Platform */ -#undef WOLFSSL_ZEPHYR -#define WOLFSSL_ZEPHYR - -#define WOLFSSL_GENERAL_ALIGNMENT 4 -#define SIZEOF_LONG_LONG 8 - -/* Enable PSA Crypto API for CryptoCell 312 crypto use */ -#define WOLFSSL_HAVE_PSA -#define WOLFSSL_PSA_GLOBAL_LOCK - -/* Enable SP Math */ -#define WOLFSSL_SP_MATH -#define WOLFSSL_SP_MATH_ALL -#define WOLFSSL_HAVE_SP_RSA -#define WOLFSSL_HAVE_SP_DH -#define WOLFSSL_HAVE_SP_ECC - -/* Enable SP Math assembly support for ARM32 */ -#define SP_WORD_SIZE 32 -#define WOLFSSL_SP_ASM -#define WOLFSSL_SP_ARM32 -#define WOLFSSL_SP_ARM32_ASM - -/* Crypto */ -#define WC_RSA_BLINDING -#define WC_RSA_PSS -#define WOLFSSL_DH_CONST -#define HAVE_FFDHE_2048 - -#define HAVE_ECC -#define ECC_USER_CURVES -/* #define HAVE_ECC192 */ -/* #define HAVE_ECC224 */ -#undef NO_ECC256 -/* #define HAVE_ECC384 */ -/* #define HAVE_ECC521 */ -#define ECC_SHAMIR -#define ECC_TIMING_RESISTANT - -#define WOLFSSL_AES_DIRECT -#define HAVE_AES_ECB -#define HAVE_AES_CBC -#define HAVE_AESCCM -#define HAVE_AESGCM -#define GCM_TABLE_4BIT - -/* AES-CTR is not working correctly with Nordic PSA Crypto API */ -/* #define WOLFSSL_AES_COUNTER */ - -#define HAVE_CHACHA -#define HAVE_POLY1305 -#define HAVE_ONE_TIME_AUTH - -/* Nordic Security PSA Crypto CryptoCell integration does not support SHA-1 */ -#define NO_SHA -#define WOLFSSL_SHA224 -#define WOLFSSL_SHA384 -#define WOLFSSL_SHA512 -#define WOLFSSL_SHA3 - -#define HAVE_HKDF -#define WOLFSSL_CMAC - -/* Benchmark / Test */ -#define BENCH_EMBEDDED -#define USE_CERT_BUFFERS_256 -#define USE_CERT_BUFFERS_2048 -#define NO_FILESYSTEM - -/* RNG */ -#define HAVE_HASHDRBG - -/* Features */ -#define WOLFSSL_TLS13 -#define WOLFSSL_OLD_PRIME_CHECK -#define HAVE_TLS_EXTENSIONS -#define HAVE_SUPPORTED_CURVES -#define HAVE_EXTENDED_MASTER -#define WOLFSSL_BASE64_ENCODE -#define WC_NO_ASYNC_THREADING - -/* Disable features that require SHA-1 (see note above) */ -#define NO_OLD_TLS -#define NO_DSA - -/* Disable other features (re-enable if needed) */ -#define NO_RC4 -#define NO_PSK -#define NO_MD4 -#define NO_PWDBASED -#define NO_DES3 - -#if defined(CONFIG_WOLFSSL_DEBUG) -#undef DEBUG_WOLFSSL -#define DEBUG_WOLFSSL -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* WOLFSSL_OPTIONS_H */ - diff --git a/zephyr/samples/wolfssl_benchmark/boards/nrf5340dk_nrf5340_cpuapp.conf b/zephyr/samples/wolfssl_benchmark/boards/nrf5340dk_nrf5340_cpuapp.conf index b651b7b889..98d8bc4963 100644 --- a/zephyr/samples/wolfssl_benchmark/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/zephyr/samples/wolfssl_benchmark/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -1,5 +1,5 @@ # Set user_settings.h file to be used for native wolfSSL build settings -CONFIG_WOLFSSL_SETTINGS_FILE="nrf5340dk_nrf5340_user_settings.h" +#CONFIG_WOLFSSL_SETTINGS_FILE="user_settings_custom.h" ##### PSA and CC3XX ##### # Enable Nordic Security Module diff --git a/zephyr/samples/wolfssl_benchmark/boards/nrf5340dk_nrf5340_cpuapp_ns.conf b/zephyr/samples/wolfssl_benchmark/boards/nrf5340dk_nrf5340_cpuapp_ns.conf index a0e2052157..aa3bbe18ad 100644 --- a/zephyr/samples/wolfssl_benchmark/boards/nrf5340dk_nrf5340_cpuapp_ns.conf +++ b/zephyr/samples/wolfssl_benchmark/boards/nrf5340dk_nrf5340_cpuapp_ns.conf @@ -2,7 +2,7 @@ CONFIG_BUILD_WITH_TFM=y CONFIG_TFM_PROFILE_TYPE_NOT_SET=y # Set user_settings.h file to be used for native wolfSSL build settings -CONFIG_WOLFSSL_SETTINGS_FILE="nrf5340dk_nrf5340_user_settings.h" +#CONFIG_WOLFSSL_SETTINGS_FILE="user_settings_custom.h" ##### PSA and CC3XX ##### # Enable Nordic Security Module diff --git a/zephyr/samples/wolfssl_benchmark/prj.conf b/zephyr/samples/wolfssl_benchmark/prj.conf index b7e4eee439..41ccf7f948 100644 --- a/zephyr/samples/wolfssl_benchmark/prj.conf +++ b/zephyr/samples/wolfssl_benchmark/prj.conf @@ -26,6 +26,10 @@ CONFIG_LOG_BUFFER_SIZE=15360 #CONFIG_WOLFSSL_DEBUG=y # Entropy +CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ENTROPY_GENERATOR=y CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR=y +# Optional ARM or Intel Assembly +#CONFIG_WOLFCRYPT_ARMASM=y +#CONFIG_WOLFCRYPT_INTELASM=y diff --git a/zephyr/samples/wolfssl_test/boards/nrf5340dk_nrf5340_cpuapp.conf b/zephyr/samples/wolfssl_test/boards/nrf5340dk_nrf5340_cpuapp.conf index b651b7b889..98d8bc4963 100644 --- a/zephyr/samples/wolfssl_test/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/zephyr/samples/wolfssl_test/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -1,5 +1,5 @@ # Set user_settings.h file to be used for native wolfSSL build settings -CONFIG_WOLFSSL_SETTINGS_FILE="nrf5340dk_nrf5340_user_settings.h" +#CONFIG_WOLFSSL_SETTINGS_FILE="user_settings_custom.h" ##### PSA and CC3XX ##### # Enable Nordic Security Module diff --git a/zephyr/samples/wolfssl_test/boards/nrf5340dk_nrf5340_cpuapp_ns.conf b/zephyr/samples/wolfssl_test/boards/nrf5340dk_nrf5340_cpuapp_ns.conf index a0e2052157..aa3bbe18ad 100644 --- a/zephyr/samples/wolfssl_test/boards/nrf5340dk_nrf5340_cpuapp_ns.conf +++ b/zephyr/samples/wolfssl_test/boards/nrf5340dk_nrf5340_cpuapp_ns.conf @@ -2,7 +2,7 @@ CONFIG_BUILD_WITH_TFM=y CONFIG_TFM_PROFILE_TYPE_NOT_SET=y # Set user_settings.h file to be used for native wolfSSL build settings -CONFIG_WOLFSSL_SETTINGS_FILE="nrf5340dk_nrf5340_user_settings.h" +#CONFIG_WOLFSSL_SETTINGS_FILE="user_settings_custom.h" ##### PSA and CC3XX ##### # Enable Nordic Security Module diff --git a/zephyr/samples/wolfssl_test/prj.conf b/zephyr/samples/wolfssl_test/prj.conf index a989213b4c..6c8a5ca437 100644 --- a/zephyr/samples/wolfssl_test/prj.conf +++ b/zephyr/samples/wolfssl_test/prj.conf @@ -24,6 +24,6 @@ CONFIG_LOG_BUFFER_SIZE=15360 #CONFIG_WOLFSSL_DEBUG=y # Entropy +CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ENTROPY_GENERATOR=y CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR=y - diff --git a/zephyr/samples/wolfssl_tls_sock/src/tls_sock.c b/zephyr/samples/wolfssl_tls_sock/src/tls_sock.c index 7be365321f..b930554435 100644 --- a/zephyr/samples/wolfssl_tls_sock/src/tls_sock.c +++ b/zephyr/samples/wolfssl_tls_sock/src/tls_sock.c @@ -62,6 +62,20 @@ static const char msgHTTPIndex[] = "\n" "\n"; +#ifdef HAVE_FIPS +static void myFipsCb(int ok, int err, const char* hash) +{ + printf("in my Fips callback, ok = %d, err = %d\n", ok, err); + printf("message = %s\n", wc_GetErrorString(err)); + printf("hash = %s\n", hash); + + if (err == IN_CORE_FIPS_E) { + printf("In core integrity hash check failure, copy above hash\n"); + printf("into verifyCore[] in fips_test.c and rebuild\n"); + } +} +#endif + /* DO NOT use this in production. You should implement a way * to get the current date. */ static int verifyIgnoreDateError(int preverify, WOLFSSL_X509_STORE_CTX* store) @@ -485,6 +499,9 @@ int main() { THREAD_TYPE serverThread; +#ifdef HAVE_FIPS + wolfCrypt_SetCb_fips(myFipsCb); +#endif wolfSSL_Init(); #ifdef DEBUG_WOLFSSL wolfSSL_Debugging_ON(); diff --git a/zephyr/samples/wolfssl_tls_thread/boards/nrf5340dk_nrf5340_cpuapp.conf b/zephyr/samples/wolfssl_tls_thread/boards/nrf5340dk_nrf5340_cpuapp.conf index b651b7b889..98d8bc4963 100644 --- a/zephyr/samples/wolfssl_tls_thread/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/zephyr/samples/wolfssl_tls_thread/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -1,5 +1,5 @@ # Set user_settings.h file to be used for native wolfSSL build settings -CONFIG_WOLFSSL_SETTINGS_FILE="nrf5340dk_nrf5340_user_settings.h" +#CONFIG_WOLFSSL_SETTINGS_FILE="user_settings_custom.h" ##### PSA and CC3XX ##### # Enable Nordic Security Module diff --git a/zephyr/samples/wolfssl_tls_thread/boards/nrf5340dk_nrf5340_cpuapp_ns.conf b/zephyr/samples/wolfssl_tls_thread/boards/nrf5340dk_nrf5340_cpuapp_ns.conf index a0e2052157..aa3bbe18ad 100644 --- a/zephyr/samples/wolfssl_tls_thread/boards/nrf5340dk_nrf5340_cpuapp_ns.conf +++ b/zephyr/samples/wolfssl_tls_thread/boards/nrf5340dk_nrf5340_cpuapp_ns.conf @@ -2,7 +2,7 @@ CONFIG_BUILD_WITH_TFM=y CONFIG_TFM_PROFILE_TYPE_NOT_SET=y # Set user_settings.h file to be used for native wolfSSL build settings -CONFIG_WOLFSSL_SETTINGS_FILE="nrf5340dk_nrf5340_user_settings.h" +#CONFIG_WOLFSSL_SETTINGS_FILE="user_settings_custom.h" ##### PSA and CC3XX ##### # Enable Nordic Security Module diff --git a/zephyr/samples/wolfssl_tls_thread/prj.conf b/zephyr/samples/wolfssl_tls_thread/prj.conf index 4a1e290a6b..95ebedcbb6 100644 --- a/zephyr/samples/wolfssl_tls_thread/prj.conf +++ b/zephyr/samples/wolfssl_tls_thread/prj.conf @@ -1,6 +1,7 @@ # Kernel options CONFIG_MAIN_STACK_SIZE=16384 CONFIG_ENTROPY_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_INIT_STACKS=y CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=65536 @@ -35,7 +36,7 @@ CONFIG_LOG_MODE_IMMEDIATE=y CONFIG_WOLFSSL=y CONFIG_WOLFSSL_BUILTIN=y -CONFIG_WOLFSSL_TLS_VERSION_1_2=y +CONFIG_WOLFSSL_TLS_VERSION_1_3=y CONFIG_WOLFSSL_KEY_EXCHANGE_ALL_ENABLED=y CONFIG_WOLFSSL_CIPHER_ALL_ENABLED=y CONFIG_WOLFSSL_MAC_ALL_ENABLED=y diff --git a/zephyr/samples/wolfssl_tls_thread/src/tls_threaded.c b/zephyr/samples/wolfssl_tls_thread/src/tls_threaded.c index 490e3362e2..cd7aad9016 100644 --- a/zephyr/samples/wolfssl_tls_thread/src/tls_threaded.c +++ b/zephyr/samples/wolfssl_tls_thread/src/tls_threaded.c @@ -89,6 +89,20 @@ static const char msgHTTPIndex[] = "\n" "\n"; +#ifdef HAVE_FIPS +static void myFipsCb(int ok, int err, const char* hash) +{ + printf("in my Fips callback, ok = %d, err = %d\n", ok, err); + printf("message = %s\n", wc_GetErrorString(err)); + printf("hash = %s\n", hash); + + if (err == IN_CORE_FIPS_E) { + printf("In core integrity hash check failure, copy above hash\n"); + printf("into verifyCore[] in fips_test.c and rebuild\n"); + } +} +#endif + /* wolfSSL client wants to read data from the server. */ static int recv_client(WOLFSSL* ssl, char* buff, int sz, void* ctx) { @@ -575,6 +589,9 @@ int main() utctime.tv_nsec = 0; clock_settime(CLOCK_REALTIME, &utctime); +#ifdef HAVE_FIPS + wolfCrypt_SetCb_fips(myFipsCb); +#endif wolfSSL_Init(); #ifdef DEBUG_WOLFSSL wolfSSL_Debugging_ON(); diff --git a/zephyr/user_settings-tls-generic.h b/zephyr/user_settings-tls-generic.h deleted file mode 100644 index 32a28bbc2c..0000000000 --- a/zephyr/user_settings-tls-generic.h +++ /dev/null @@ -1,153 +0,0 @@ -/* user_settings-tls-generic.h - * generated from configure options - * - * 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 - */ - -#ifndef WOLFSSL_OPTIONS_H -#define WOLFSSL_OPTIONS_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#if 0 -#undef SINGLE_THREADED -#define SINGLE_THREADED -#endif - -#undef TFM_TIMING_RESISTANT -#define TFM_TIMING_RESISTANT - -#undef ECC_TIMING_RESISTANT -#define ECC_TIMING_RESISTANT - -#undef WC_RSA_BLINDING -#define WC_RSA_BLINDING - -#undef HAVE_AESGCM -#define HAVE_AESGCM - -#undef WOLFSSL_SHA512 -#define WOLFSSL_SHA512 - -#undef WOLFSSL_SHA384 -#define WOLFSSL_SHA384 - -#undef NO_DSA -#define NO_DSA - -#undef HAVE_ECC -#define HAVE_ECC - -#undef TFM_ECC256 -#define TFM_ECC256 - -#undef WOLFSSL_BASE64_ENCODE -#define WOLFSSL_BASE64_ENCODE - -#undef NO_RC4 -#define NO_RC4 - -#undef WOLFSSL_SHA224 -#define WOLFSSL_SHA224 - -#undef WOLFSSL_SHA3 -#define WOLFSSL_SHA3 - -#undef HAVE_POLY1305 -#define HAVE_POLY1305 - -#undef HAVE_ONE_TIME_AUTH -#define HAVE_ONE_TIME_AUTH - -#undef HAVE_CHACHA -#define HAVE_CHACHA - -#undef HAVE_HASHDRBG -#define HAVE_HASHDRBG - -#undef NO_FILESYSTEM -#define NO_FILESYSTEM - -#undef HAVE_TLS_EXTENSIONS -#define HAVE_TLS_EXTENSIONS - -#undef HAVE_SUPPORTED_CURVES -#define HAVE_SUPPORTED_CURVES - -#undef HAVE_EXTENDED_MASTER -#define HAVE_EXTENDED_MASTER - -#undef NO_PSK -#define NO_PSK - -#undef NO_MD4 -#define NO_MD4 - -#undef NO_PWDBASED -#define NO_PWDBASED - -#undef USE_FAST_MATH -#define USE_FAST_MATH - -#undef WOLFSSL_NO_ASM -#define WOLFSSL_NO_ASM - -#undef WOLFSSL_X86_BUILD -#define WOLFSSL_X86_BUILD - -#undef WC_NO_ASYNC_THREADING -#define WC_NO_ASYNC_THREADING - -#undef NO_DES3 -#define NO_DES3 - -#undef WOLFSSL_STATIC_MEMORY -#define WOLFSSL_STATIC_MEMORY - -#undef WOLFSSL_TLS13 -#define WOLFSSL_TLS13 - -#undef HAVE_HKDF -#define HAVE_HKDF - -#undef WC_RSA_PSS -#define WC_RSA_PSS - -#undef HAVE_FFDHE_2048 -#define HAVE_FFDHE_2048 - -#if 0 -#undef WOLFSSL_HAVE_SP_RSA -#define WOLFSSL_HAVE_SP_RSA -#undef WOLFSSL_HAVE_SP_DH -#define WOLFSSL_HAVE_SP_DH -#undef WOLFSSL_HAVE_SP_ECC -#define WOLFSSL_HAVE_SP_ECC -#endif - -#ifdef __cplusplus -} -#endif - - -#endif /* WOLFSSL_OPTIONS_H */ - diff --git a/zephyr/user_settings.h b/zephyr/user_settings.h index ba0ba9b2e7..8c8f2e3032 100644 --- a/zephyr/user_settings.h +++ b/zephyr/user_settings.h @@ -1,6 +1,6 @@ /* user_settings.h * - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,120 +23,405 @@ #define USER_SETTINGS_H #ifdef CONFIG_WOLFSSL -#ifdef CONFIG_WOLFSSL_SETTINGS_FILE - -#include CONFIG_WOLFSSL_SETTINGS_FILE +/* If a custom user_settings file is provided use it instead */ +#ifdef WOLFSSL_SETTINGS_FILE +#include WOLFSSL_SETTINGS_FILE #else #ifdef __cplusplus extern "C" { #endif + +/* ------------------------------------------------------------------------- */ +/* Platform */ +/* ------------------------------------------------------------------------- */ +#define WOLFSSL_GENERAL_ALIGNMENT 4 /* platform requires 32-bit alignment on uint32_t */ +#define SIZEOF_LONG_LONG 8 /* long long is 8 bytes / 64-bit */ +//#define WOLFSSL_NO_ASM /* optionally disable inline assembly support */ +#define WOLFSSL_IGNORE_FILE_WARN /* ignore file includes not required */ +//#define WOLFSSL_SMALL_STACK /* option to reduce stack size, offload to heap */ +#define BENCH_EMBEDDED /* use smaller buffers in benchmark / tests */ + +/* Network stack */ +/* Default is POSIX sockets */ +//#define WOLFSSL_USER_IO /* Use the SetIO callbacks, not the internal wolfio.c socket code */ +//#define WOLFSSL_LWIP +//#define WOLFSSL_LWIP_NATIVE +//#define FREERTOS_TCP + +/* RTOS */ +/* Default is POSIX mutex and pthreads*/ +//#define SINGLE_THREADED +//#define FREERTOS +#define NO_FILESYSTEM +#define NO_WRITEV + +/* ------------------------------------------------------------------------- */ +/* Hardware */ +/* ------------------------------------------------------------------------- */ +/* CryptoCell support */ #if 0 -#undef SINGLE_THREADED -#define SINGLE_THREADED + //#define WOLFSSL_CRYPTOCELL + //#define WOLFSSL_CRYPTOCELL_AES +#endif +/* PSA support */ +#ifdef CONFIG_MBEDTLS_PSA_CRYPTO_C + #define WOLFSSL_HAVE_PSA + #ifndef SINGLE_THREADED + #define WOLFSSL_PSA_GLOBAL_LOCK + #endif + #define WC_NO_HASHDRBG /* use PSA RNG directly via wc_psa_get_random */ #endif -#undef TFM_TIMING_RESISTANT -#define TFM_TIMING_RESISTANT +/* ------------------------------------------------------------------------- */ +/* FIPS */ +/* ------------------------------------------------------------------------- */ +#ifdef CONFIG_WOLFCRYPT_FIPS + /* FIPS Ready */ + #define HAVE_FIPS_VERSION 5 + #define HAVE_FIPS_VERSION_MINOR 3 +#endif -#undef ECC_TIMING_RESISTANT -#define ECC_TIMING_RESISTANT -#undef WC_RSA_BLINDING -#define WC_RSA_BLINDING +/* ------------------------------------------------------------------------- */ +/* TLS */ +/* ------------------------------------------------------------------------- */ +/* TLS v1.2 (on by default) */ +#ifdef CONFIG_WOLFSSL_TLS_VERSION_1_2 + #undef WOLFSSL_NO_TLS12 +#else + #define WOLFSSL_NO_TLS12 +#endif +//#define NO_WOLFSSL_SERVER /* Optionally disable TLS server code */ +//#define NO_WOLFSSL_CLIENT /* Optionally disable TLS client code */ -#undef HAVE_AESGCM -#define HAVE_AESGCM +/* TLS v1.3 */ +#if defined(CONFIG_WOLFSSL_TLS_VERSION_1_3) || defined(CONFIG_WOLFSSL_TLS13_ENABLED) + #define WOLFSSL_TLS13 +#endif -#undef WOLFSSL_SHA512 -#define WOLFSSL_SHA512 +/* Disable older TLS version prior to 1.2 */ +#define NO_OLD_TLS -#undef WOLFSSL_SHA384 -#define WOLFSSL_SHA384 +/* Enable default TLS extensions */ +#define HAVE_TLS_EXTENSIONS +#define HAVE_SUPPORTED_CURVES +#define HAVE_EXTENDED_MASTER +#define HAVE_ENCRYPT_THEN_MAC +#define HAVE_SERVER_RENEGOTIATION_INFO +#define HAVE_SNI /* optional Server Name Indicator (SNI) */ + +/* ASN */ +#define WOLFSSL_ASN_TEMPLATE /* use newer ASN template asn.c code (default) */ +#if 0 /* optional space reductions */ + #define WOLFSSL_NO_ASN_STRICT + #define IGNORE_NAME_CONSTRAINTS +#endif -#undef NO_DSA -#define NO_DSA +/* Session Cache */ +#if 1 + #define SMALL_SESSION_CACHE + #ifdef WOLFSSL_TLS13 + #define HAVE_SESSION_TICKET /* session tickets required for resumption in TLS v1.3 */ + #endif +#else + #define NO_SESSION_CACHE /* disable session resumption */ +#endif -#undef HAVE_ECC -#define HAVE_ECC +/* PSK */ +#define NO_PSK /* disable pre-shared-key support */ -#undef TFM_ECC256 -#define TFM_ECC256 -#undef WOLFSSL_BASE64_ENCODE -#define WOLFSSL_BASE64_ENCODE +/* ------------------------------------------------------------------------- */ +/* Algorithms */ +/* ------------------------------------------------------------------------- */ +/* RNG */ +#ifndef WC_NO_HASHDRBG + #define HAVE_HASHDRBG /* Use DRBG SHA2-256 and seed */ +#endif -#undef NO_RC4 -#define NO_RC4 +/* ECC */ +#if 1 + #define HAVE_ECC + #define ECC_USER_CURVES /* Enable only ECC curves specific */ + #undef NO_ECC256 /* Enable SECP256R1 only (on by default) */ + #define ECC_TIMING_RESISTANT /* Enable Timing Resistance */ + + //#define ECC_SHAMIR /* Optional ECC calculation speed improvement if not using SP implementation */ + //#define WOLFSSL_CUSTOM_CURVES /* enable other curves (not just prime) */ + //#define HAVE_ECC_SECPR2 + //#define HAVE_ECC_SECPR3 + //#define HAVE_ECC_BRAINPOOL + //#define HAVE_ECC_KOBLITZ + //#define HAVE_ECC_CDH /* Co-factor */ + //#define HAVE_COMP_KEY /* Compressed key support */ + //#define FP_ECC /* Fixed point caching - speed repeated operations against same key */ + //#define HAVE_ECC_ENCRYPT + //#define WOLFCRYPT_HAVE_ECCSI + //#define WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT +#endif -#undef WOLFSSL_SHA224 -#define WOLFSSL_SHA224 +#define WOLFSSL_OLD_PRIME_CHECK /* Use faster DH prime checking */ + +/* RSA */ +#if 1 + #undef NO_RSA + #define WC_RSA_BLINDING + //#define WC_RSA_NO_PADDING + //#define RSA_LOW_MEM + + #if 0 + #define WOLFSSL_KEY_GEN /* For RSA Key gen only */ + #endif + #if defined(WOLFSSL_TLS13) || defined(CONFIG_WOLFSSL_RSA_PSS) + /* TLS v1.3 requires RSA PSS padding */ + #define WC_RSA_PSS + //#define WOLFSSL_PSS_LONG_SALT + #endif +#else + #define NO_RSA +#endif -#undef WOLFSSL_SHA3 -#define WOLFSSL_SHA3 +/* DH */ +#if 0 + #undef NO_DH /* on by default */ + #define WOLFSSL_DH_CONST /* don't rely on pow/log */ + #define HAVE_FFDHE_2048 + #define HAVE_FFDHE_3072 + #define HAVE_DH_DEFAULT_PARAMS + //#define WOLFSSL_DH_EXTRA /* Enable additional DH key import/export */ +#else + #define NO_DH +#endif -#undef HAVE_POLY1305 -#define HAVE_POLY1305 +/* ChaCha20 / Poly1305 */ +#if 1 + #define HAVE_CHACHA + #define HAVE_POLY1305 -#undef HAVE_ONE_TIME_AUTH -#define HAVE_ONE_TIME_AUTH + /* Needed for Poly1305 */ + #define HAVE_ONE_TIME_AUTH +#endif -#undef HAVE_CHACHA -#define HAVE_CHACHA +/* Ed25519 / Curve25519 */ +#if 0 + #define HAVE_CURVE25519 + #define HAVE_ED25519 /* ED25519 Requires SHA512 */ -#undef HAVE_HASHDRBG -#define HAVE_HASHDRBG + /* Optionally use small math (less flash usage, but much slower) */ + //#define CURVED25519_SMALL +#endif -#undef NO_FILESYSTEM -#define NO_FILESYSTEM +/* SHA-1 */ +#if 0 + #undef NO_SHA /* on by default */ + //#define USE_SLOW_SHA /* 1k smaller, but 25% slower */ +#else + #define NO_SHA +#endif -#undef HAVE_TLS_EXTENSIONS -#define HAVE_TLS_EXTENSIONS +/* SHA2-256 */ +#if 1 + #undef NO_SHA256 /* on by default */ + //#define USE_SLOW_SHA256 /* ~2k smaller and about 25% slower */ + #define WOLFSSL_SHA224 +#else + #define NO_SHA256 +#endif -#undef HAVE_SUPPORTED_CURVES -#define HAVE_SUPPORTED_CURVES +/* SHA2-384/512 */ +#if 1 + #define WOLFSSL_SHA384 + #define WOLFSSL_SHA512 + //#define USE_SLOW_SHA512 /* Over twice as small, but 50% slower */ +#endif -#undef HAVE_EXTENDED_MASTER -#define HAVE_EXTENDED_MASTER +/* SHA-3 */ +#if 1 + #define WOLFSSL_SHA3 +#endif + +/* AES */ +#define HAVE_AES_ECB +/* AES-CBC */ +#if 1 + #define HAVE_AES_CBC +#else + #define NO_AES_CBC +#endif +/* AES-GCM */ +#if 1 + #define HAVE_AESGCM + #define GCM_SMALL /* GCM Method: GCM_TABLE_4BIT, GCM_SMALL, GCM_WORD32 or GCM_TABLE */ + //#define WOLFSSL_AESGCM_STREAM +#endif +//#define HAVE_AES_DECRYPT +//#define WOLFSSL_AES_COUNTER +//#define WOLFSSL_AES_CFB +//#define WOLFSSL_AES_OFB +//#define HAVE_AESCCM +//#define WOLFSSL_AES_XTS + +//#define NO_AES_128 +//#define NO_AES_192 +//#define NO_AES_256 +//#define WOLFSSL_AES_SMALL_TABLES +//#define WOLFSSL_AES_NO_UNROLL + + +/* HKDF */ +#if defined(WOLFSSL_TLS13) || defined(CONFIG_WOLFSSL_HKDF) + #define HAVE_HKDF +#endif + +/* CMAC - Zephyr nRF BTLE needs CMAC */ +#if 1 + #define WOLFSSL_AES_DIRECT + #define WOLFSSL_CMAC +#endif -#undef NO_PSK -#define NO_PSK -#undef NO_MD4 +/* Optional Features */ +#define WOLFSSL_BASE64_ENCODE /* Enable Base64 encoding */ +//#define WC_NO_CACHE_RESISTANT /* systems with cache should enable this for AES, ECC, RSA and DH */ +//#define WOLFSSL_CERT_GEN +//#define WOLFSSL_CERT_REQ +//#define WOLFSSL_CERT_EXT +//#define NO_PWDBASED + + +/* Disable Algorithms */ +#define NO_DSA +#define NO_RC4 #define NO_MD4 +#define NO_MD5 +#define NO_DES3 +#define WOLFSSL_NO_SHAKE128 +#define WOLFSSL_NO_SHAKE256 + + + +/* ------------------------------------------------------------------------- */ +/* Math */ +/* ------------------------------------------------------------------------- */ +/* Math Options */ +/* Multi-precision - generic math for all keys sizes and curves */ +#if 1 + #define WOLFSSL_SP_MATH /* no multi-precision math, only single */ +#elif 1 + /* wolf mp math (sp_int.c) */ + #define WOLFSSL_SP_MATH_ALL /* use SP math for all key sizes and curves */ + //#define WOLFSSL_SP_NO_MALLOC + + /* use smaller version of code */ + #define WOLFSSL_SP_SMALL + + /* Define the maximum math bits used */ + #if !defined(NO_RSA) || !defined(NO_DH) + #define SP_INT_BITS 2048 + #elif defined(HAVE_ECC) + #define SP_INT_BITS 256 + #endif + +#elif 1 + /* Fast Math (tfm.c) (stack based and timing resistant) */ + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + + /* Define the maximum math bits used (2 * max) */ + #if !defined(NO_RSA) || !defined(NO_DH) + #define FP_MAX_BITS (2*2048) + #ifdef HAVE_ECC + #define ALT_ECC_SIZE /* use heap allocation for ECC point */ + #endif + #elif defined(HAVE_ECC) + #define FP_MAX_BITS (2*256) + #endif + #ifdef HAVE_ECC + //#define TFM_ECC256 /* optional speedup for ECC-256 bit */ + #endif +#else + /* Normal (integer.c) (heap based, not timing resistant) - not recommended */ + #define USE_INTEGER_HEAP_MATH +#endif -#undef NO_PWDBASED -#define NO_PWDBASED +/* Single Precision (optional) */ +/* Math written for specific curves and key sizes */ +#if 1 + #ifdef HAVE_ECC + #define WOLFSSL_HAVE_SP_ECC + //#define WOLFSSL_SP_NO_256 + //#define WOLFSSL_SP_384 + //#define WOLFSSL_SP_521 + #endif + #ifndef NO_RSA + #define WOLFSSL_HAVE_SP_RSA + //#define WOLFSSL_SP_NO_2048 + //#define WOLFSSL_SP_NO_3072 + //#define WOLFSSL_SP_4096 + #endif + #ifndef NO_DH + #define WOLFSSL_HAVE_SP_DH + #endif + + #define WOLFSSL_SP_SMALL /* use smaller version of code */ + //#define WOLFSSL_SP_NO_MALLOC /* disable heap in wolf/SP math */ + //#define SP_DIV_WORD_USE_DIV /* no div64 */ + + #if 0 + /* optional speedup with inline assembly */ + //#define WOLFSSL_SP_ARM_CORTEX_M_ASM /* Cortex-M3+ */ + //#define WOLFSSL_SP_ARM_THUMB_ASM /* Cortex-M0+ thumb */ + //#define WOLFSSL_SP_ARM32_ASM /* Cortex-R */ + //#define WOLFSSL_SP_ARM64_ASM /* Cortex-A */ + //#define WOLFSSL_SP_USE_UDIV + #endif +#endif -#undef USE_FAST_MATH -#define USE_FAST_MATH +/* ------------------------------------------------------------------------- */ +/* Assembly Speedups for Symmetric Algorithms */ +/* ------------------------------------------------------------------------- */ -#undef WOLFSSL_NO_ASM -#define WOLFSSL_NO_ASM +#ifdef CONFIG_WOLFCRYPT_ARMASM + #define WOLFSSL_ARMASM + #define WOLFSSL_NO_HASH_RAW + #define WOLFSSL_ARMASM_INLINE /* use inline .c versions */ + #define WOLFSSL_ARMASM_NO_NEON -#undef WOLFSSL_X86_BUILD -#define WOLFSSL_X86_BUILD + /* Default is ARMv8 */ -#undef WC_NO_ASYNC_THREADING -#define WC_NO_ASYNC_THREADING + #if 0 /* ARMv7 */ + #define WOLFSSL_ARM_ARCH 7 + #define WOLFSSL_ARMASM_NO_HW_CRYPTO /* enable if processor does not support aes/sha instructions */ + #endif +#endif -#undef NO_DES3 -#define NO_DES3 +#ifdef CONFIG_WOLFCRYPT_INTELASM + #define USE_INTEL_SPEEDUP + #define WOLFSSL_X86_64_BUILD /* 64-bit */ + //#define WOLFSSL_X86_BUILD /* 32-bit */ -#undef WOLFSSL_STATIC_MEMORY -#define WOLFSSL_STATIC_MEMORY + /* Issues with building AESNI "_mm_aesimc_si128" always_inline */ + //#define WOLFSSL_AESNI +#endif -#if 0 -#undef WOLFSSL_HAVE_SP_RSA -#define WOLFSSL_HAVE_SP_RSA -#undef WOLFSSL_HAVE_SP_DH -#define WOLFSSL_HAVE_SP_DH -#undef WOLFSSL_HAVE_SP_ECC -#define WOLFSSL_HAVE_SP_ECC + +/* ------------------------------------------------------------------------- */ +/* Debugging */ +/* ------------------------------------------------------------------------- */ +#undef DEBUG_WOLFSSL +#undef NO_ERROR_STRINGS +#ifdef CONFIG_WOLFSSL_DEBUG + #define DEBUG_WOLFSSL +#else + #if 1 + #define NO_ERROR_STRINGS + #endif #endif + #ifdef __cplusplus } #endif diff --git a/zephyr/wolfssl/options.h b/zephyr/wolfssl/options.h index e69de29bb2..5c637481bb 100644 --- a/zephyr/wolfssl/options.h +++ b/zephyr/wolfssl/options.h @@ -0,0 +1 @@ +/* default blank options to appease code that may require it */