diff --git a/.github/SECURITY.md b/.github/SECURITY.md
new file mode 100644
index 0000000..2bab9b6
--- /dev/null
+++ b/.github/SECURITY.md
@@ -0,0 +1,12 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+If you discover a vulnerability, please report it to support@wolfssl.com
+
+ 1. Include a detailed description
+ 2. Include method to reproduce and/or method of discovery
+ 3. We will evaluate the report promptly and respond to you with findings.
+ 4. We will credit you with the report if you would like.
+
+**Please keep the vulnerability private** until a fix has been released.
diff --git a/.github/workflows/arduino.yml b/.github/workflows/arduino.yml
new file mode 100644
index 0000000..982814a
--- /dev/null
+++ b/.github/workflows/arduino.yml
@@ -0,0 +1,409 @@
+name: Arduino CI Build (4 of 4) Arduino-wolfSSL
+
+#
+# Test local Arduino examples with LATEST github master branch wolfssl
+#
+# These 4 workflows across 3 repos are interdependent for the current $REPO_OWNER:
+#
+# Arduino CI Build 1: https://github.com/$REPO_OWNER/wolfssl # /.github/workflows/arduino.yml
+# - Builds Arduino library from local clone of wolfssl master branch
+# - Fetches examples from https://github.com/$REPO_OWNER/wolfssl-examples
+#
+# Arduino CI Build 2: https://github.com/$REPO_OWNER/wolfssl-examples # /.github/workflows/arduino-release.yml
+# - Tests examples based on latest published release of Arduino library, NOT latest on wolfssl github.
+# - Should be identical to Arduino CI Build 3 in every way but wolfssl install.
+# - Copies only compile script from wolfssl-examples
+# - Builds local examples
+# - No other repos used
+#
+# Arduino CI Build 3: https://github.com/$REPO_OWNER/wolfssl-examples # /.github/workflows/arduino.yml
+# - Fetches current wolfSSL from https://github.com/$REPO_OWNER/wolfssl
+# - Creates an updated Arduino library
+# - Compiles local examples
+# - Contains the source of `compile-all-examples.sh` and respective board-list.txt
+#
+# THIS Arduino CI Build 4: https://github.com/$REPO_OWNER/Arduino-wolfssl # /.github/workflows/arduino.yml
+# - Assembles and installs an updated Arduino wolfssl library from LOCAL Arduino-wolfSSL repo master (main) source
+# - Copies only compile script and board list from wolfssl-examples (no examples copied)
+# - Builds local examples
+# - No other repos used
+#
+#
+# ** NOTE TO MAINTAINERS **
+#
+# Consider using winmerge or similar tool to keep the 4 arduino[-release].yml files in relative sync.
+# Although there are some specific differences, most of the contents are otherwise identical.
+#
+# See https://github.com/wolfSSL/Arduino-wolfSSL
+#
+# To test locally:
+# cd [your WOLFSSL_ROOT], e.g. cd /mnt/c/workspace/wolfssl-$USER
+# [optional checkout] e.g. git checkout tags/v5.8.4-stable
+# pushd ./IDE/ARDUINO
+# export ARDUINO_ROOT="$HOME/Arduino/libraries"
+# ./wolfssl-arduino.sh INSTALL
+# cd [your WOLFSSL_EXAMPLES_ROOT] e.g. /mnt/c/workspace/wolfssl-examples-$USER
+#
+
+# START OF COMMON SECTION
+on:
+ push:
+ branches: [ '**', 'master', 'main', 'release/**' ]
+
+ pull_request:
+ branches: [ '**' ]
+
+ workflow_dispatch:
+
+concurrency:
+ # Same branch push cancels other jobs. Other PR branches untouched
+
+ group: ${{ github.workflow }}-${{ github.ref_name }}
+ cancel-in-progress: true
+
+# END OF COMMON SECTION
+
+jobs:
+ build:
+ name: Compile (${{ matrix.fqbn }})
+ # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ # if: github.repository_owner == 'wolfssl'
+ # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ fqbn:
+ # When editing this list, be sure to also edit file: board_list.txt
+ # The compile-all-examples.sh optionally takes a FQBN parameter to
+ # optionally compile all examples ONLY for the respective fully qualified board name.
+ # See https://github.com/wolfSSL/wolfssl-examples/blob/master/Arduino/sketches/board_list.txt
+
+ - arduino:avr:ethernet
+ - arduino:avr:leonardoeth
+ - arduino:avr:mega
+ - arduino:avr:nano
+ - arduino:avr:uno
+ - arduino:avr:yun
+ - arduino:samd:mkrwifi1010
+ - arduino:samd:mkr1000
+ - arduino:samd:mkrfox1200
+ - arduino:mbed_edge:edge_control
+ - arduino:mbed_nano:nanorp2040connect
+ - arduino:mbed_portenta:envie_m7
+ - arduino:mbed_portenta:portenta_x8
+ - arduino:renesas_uno:unor4wifi
+ - arduino:sam:arduino_due_x
+ - arduino:samd:arduino_zero_native
+ - arduino:samd:tian
+ - esp32:esp32:esp32
+ - esp32:esp32:esp32s2
+ - esp32:esp32:esp32s3
+ - esp32:esp32:esp32c3
+ - esp32:esp32:esp32c6
+ - esp32:esp32:esp32h2
+ - esp8266:esp8266:generic
+ - teensy:avr:teensy40
+
+ # Not yet supported, not in standard library
+ # - esp32:esp32:nano_nora
+
+ # End strategy matrix
+ env:
+ REPO_OWNER: ${{ github.repository_owner }}
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v4
+
+ - name: Install Arduino CLI
+ run: |
+ # Script to fetch and run install.sh from arduino/arduino-cli
+
+ # The install script will test to see if the recently installed apps in the path
+ # So set it up in advance:
+ mkdir -p "${PWD}/bin"
+ echo "${PWD}/bin" >> $GITHUB_PATH
+
+ # Sets the install directory to a consistent path at the repo root.
+ ROOT_BIN="$GITHUB_WORKSPACE/bin"
+
+ # Ensures that BINDIR exists before the installer runs
+ mkdir -p "$ROOT_BIN"
+
+ # Save as a global environment variable
+ echo "$ROOT_BIN" >> "$GITHUB_PATH"
+
+ # Download and run install script from Arduino:
+ # -S show errors; -L follow redirects; -v Verbose
+ set +e # don't abort on error
+ set -o pipefail
+
+ curl -vSL --retry 5 --retry-delay 10 \
+ https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh \
+ | sh -x
+ rc=$?
+ c_rc=${PIPESTATUS[0]} # curl's exit code
+ s_rc=${PIPESTATUS[1]} # sh's exit code
+
+ set -e # restore default abort-on-error
+
+ # If there was a curl error, we have our own local copy that is more reliable and can add our own debugging
+ if [ "$rc" -ne 0 ]; then
+ echo "Primary install failed: curl=$c_rc, sh=$s_rc. Falling back..." >&2
+ echo "Using local copy of arduino_install.sh"
+ pushd ./Arduino/sketches
+ chmod +x ./arduino_install.sh
+
+ # Mimic curl install, does not use current directory:
+ BINDIR="$ROOT_BIN" sh -x ./arduino_install.sh
+ popd
+ else
+ echo "Alternative install script not needed."
+ fi
+
+ - name: Confirm Arduino CLI Install
+ run: arduino-cli version
+
+ - name: Derive CORE_ID (vendor:arch from FQBN)
+ run: |
+ CORE_ID="$(echo '${{ matrix.fqbn }}' | cut -d: -f1-2)"
+ echo "CORE_ID=$CORE_ID" >> "$GITHUB_ENV"
+
+ - name: Setup Arduino CLI
+ run: |
+ arduino-cli config init
+
+ # wait 10 minutes for big downloads (or use 0 for no limit)
+ arduino-cli config set network.connection_timeout 600s
+
+ arduino-cli config add board_manager.additional_urls https://www.pjrc.com/teensy/package_teensy_index.json
+ arduino-cli config add board_manager.additional_urls https://arduino.esp8266.com/stable/package_esp8266com_index.json
+ arduino-cli core update-index
+
+ echo "CORE_ID: $CORE_ID"
+ arduino-cli core install "$CORE_ID"
+
+ # The above is instead of:
+ # arduino-cli core install esp32:esp32 # ESP32
+ # arduino-cli core install arduino:avr # Arduino Uno, Mega, Nano
+ # arduino-cli core install arduino:sam # Arduino Due
+ # arduino-cli core install arduino:samd # Arduino Zero
+ # arduino-cli core install teensy:avr # PJRC Teensy
+ # arduino-cli core install esp8266:esp8266 # ESP8266
+ # arduino-cli core install arduino:mbed_nano # nanorp2040connect
+ # arduino-cli core install arduino:mbed_portenta # portenta_h7_m7
+ # arduino-cli core install arduino:mbed_edge
+ # arduino-cli core install arduino:renesas_uno
+
+ # For reference:
+
+ # mbed nano not yet tested
+ # sudo "/home/$USER/.arduino15/packages/arduino/hardware/mbed_nano/4.2.4/post_install.sh"
+
+ # Always install networking (not part of FQBN matrix)
+ # The first one also creates directory: /home/runner/Arduino/libraries
+ arduino-cli lib install "ArduinoJson" # Example dependency
+ arduino-cli lib install "WiFiNINA" # ARDUINO_SAMD_NANO_33_IOT
+ arduino-cli lib install "Ethernet" # Install Ethernet library
+ arduino-cli lib install "Bridge" # Pseudo-network for things like arduino:samd:tian
+
+ - name: Set Job Environment Variables
+ run: |
+ # Script to assign some common environment variables after everything is installed
+
+ ICON_OK=$(printf "\xE2\x9C\x85")
+ ICON_FAIL=$(printf "\xE2\x9D\x8C")
+
+ echo "GITHUB_WORK=$(realpath "$GITHUB_WORKSPACE/../..")" >> "$GITHUB_ENV"
+ echo "ARDUINO_ROOT=$(realpath "$HOME/Arduino/libraries")" >> "$GITHUB_ENV"
+
+ # Show predefined summary:
+ echo "GITHUB_WORKSPACE = $GITHUB_WORKSPACE"
+
+ # Show assigned build:env values (e.g. "wolfssl", "gojimmpi" or other owners):
+ echo "REPO_OWNER = $REPO_OWNER"
+
+ echo "GITHUB_ENV=$GITHUB_ENV"
+
+ # Show our custom values:
+ echo "GITHUB_WORK = $GITHUB_WORK"
+ echo "ARDUINO_ROOT = $ARDUINO_ROOT"
+
+ # WOLFSSL_EXAMPLES_ROOT is the report root, not example location
+ echo "WOLFSSL_EXAMPLES_ROOT = $WOLFSSL_EXAMPLES_ROOT"
+
+ - name: Compute cache key parts
+ id: parts
+ shell: bash
+ run: |
+ # From FQBN "vendor:arch:board" get "vendor:arch"
+ CORE_ID="$(echo "${{ matrix.fqbn }}" | awk -F: '{print $1 ":" $2}')"
+ echo "CORE_ID=$CORE_ID" >> "$GITHUB_OUTPUT"
+
+ # Also expose vendor only for broad fallbacks
+ VENDOR="$(echo "$CORE_ID" | cut -d: -f1)"
+ echo "VENDOR=$VENDOR" >> "$GITHUB_OUTPUT"
+
+ - name: Cache Arduino packages
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.arduino15
+ ~/.cache/arduino
+ ~/.arduino15/staging
+
+ # Arduino libraries
+ # Specific to Arduino CI Build (2 of 4) Arduinbo Release wolfSSL for Local Examples
+ # Include all libraries, as the latest Arduino-wolfSSL will only change upon release.
+ ~/Arduino/libraries
+ # Ensure wolfssl is not cached, we're always using the latest. See separate cache.
+ !~/Arduino/libraries/wolfssl
+ key: arduino-${{ runner.os }}-${{ env.CORE_ID }}-${{ hashFiles('Arduino/sketches/board_list.txt') }}
+
+ restore-keys: |
+ arduino-${{ runner.os }}-${{ env.CORE_ID }}-
+ arduino-${{ runner.os }}-
+
+ # - name: Show wolfssl-examples
+ # (not used, as wolfssl source is already here in Arduino-wolfSSL)
+
+ # end Show wolfssl-examples
+
+ # - name: Shallow clone wolfssl
+ # (not used, as wolfssl source is already here in Arduino-wolfSSL)
+ #
+
+ # ** END ** Shallow clone wolfssl
+
+ - name: Get wolfssl-examples
+ run: |
+ # The wolfSSL examples should already be installed in this Arduino-wolfssl/examples directory
+
+ echo "Current pwd for wolfssl-examples clone fetch: $(pwd)"
+ echo "Examples found:"
+ find ./examples -type f | sort
+
+ # ** END ** Get wolfssl-examples
+
+ - name: Install wolfSSL Arduino library
+ run: |
+ # Script for installing wolfssl from this Arduino-wolfssl library repository
+ #
+ # Steps are equivalent of:
+ #
+ # arduino-cli lib install "wolfSSL"
+ #
+ # But using the current repo as the source (delete for matrix cache):
+ rm -rf "$ARDUINO_ROOT/wolfssl"
+ mkdir -p "$ARDUINO_ROOT/wolfssl"
+
+ # Methods of installing Arduino library:
+ # 1) arduino-cli lib install "wolfSSL"
+ # 2) manual copy of files (typical of the Arduino-wolfssl repo)
+ # 3) run ./wolfssl-arduino.sh INSTALL (typical of the wolfssl repo)
+
+ # Copy all file in current directory as root of the wolfssl library
+ echo "cp [root files] \"$ARDUINO_ROOT/wolfssl/src\""
+ for f in ./*; do
+ if [ -f "$f" ]; then
+ cp "$f" "$ARDUINO_ROOT/wolfssl/"
+ fi
+ done
+
+ # Only 2 directories are needed in the Arduino library: `src` and [optional] `examples`:
+ echo "cp -r \"./src\" \"$ARDUINO_ROOT/wolfssl/src\""
+ cp -r ./src "$ARDUINO_ROOT/wolfssl/src"
+
+ echo "cp -r \"./examples\" \"$ARDUINO_ROOT/wolfssl/examples\""
+ cp -r ./examples "$ARDUINO_ROOT/wolfssl/examples"
+
+ # ** END ** Install wolfSSL Arduino library
+
+ - name: List installed Arduino libraries
+ run: arduino-cli lib list
+
+ - name: Get compile-all-examples.sh
+ run: |
+ # Fetch compile script FROM THE CURRENT OWNER.
+ # This repo is Arduino-wolfssl; we'll fetch the script from the wolfssl-examples for the same repository owner.
+ echo "Respository owner: $REPO_OWNER"
+ echo "Current directory: $PWD"
+ echo "Current pwd for wolfssl-examples clone fetch: $PWD"
+ WOLFSSL_EXAMPLES_DIRECTORY="$ARDUINO_ROOT/wolfssl/examples"
+ echo "WOLFSSL_EXAMPLES_DIRECTORY=$WOLFSSL_EXAMPLES_DIRECTORY"
+
+ # Fetch script and board list into WOLFSSL_EXAMPLES_DIRECTORY
+ # TODO edit board list name upon release and publish of wolfSSL 5.8.4 in Arduino-wolfSSL:
+ curl -L "https://raw.githubusercontent.com/$REPO_OWNER/wolfssl-examples/master/Arduino/sketches/board_list_v5.8.2.txt" \
+ -o "$WOLFSSL_EXAMPLES_DIRECTORY/board_list.txt"
+
+ FILE="$WOLFSSL_EXAMPLES_DIRECTORY/board_list.txt"
+
+ # Ensure the board list file exists
+ if [[ ! -f "$FILE" ]]; then
+ echo "File not found: $FILE"
+ exit 1
+ fi
+
+ # Check if the first line is "404: Not Found" - which would indicate the curl path above is bad.
+ if [[ $(head -n 1 "$FILE") == "404: Not Found" ]]; then
+ echo "The first line is '404: Not Found'"
+ exit 1
+ fi
+
+ curl -L "https://raw.githubusercontent.com/$REPO_OWNER/wolfssl-examples/master/Arduino/sketches/compile-all-examples.sh" \
+ -o "$WOLFSSL_EXAMPLES_DIRECTORY/compile-all-examples.sh"
+
+ # Check if the first line is "404: Not Found" - which would indicate the curl path above is bad.
+ FILE="$WOLFSSL_EXAMPLES_DIRECTORY/compile-all-examples.sh"
+
+ # Ensure the file exists
+ if [[ ! -f "$FILE" ]]; then
+ echo "File not found: $FILE"
+ exit 1
+ fi
+
+ # Check if the first line is "404: Not Found"
+ if [[ $(head -n 1 "$FILE") == "404: Not Found" ]]; then
+ echo "The first line is '404: Not Found'"
+ exit 1
+ fi
+
+ pushd "$WOLFSSL_EXAMPLES_DIRECTORY"
+ echo "Current directory: $PWD"
+
+ echo "Current directory $PWD"
+ echo "Contents:"
+ ls -al
+ find ./ -type f | sort
+
+ # ensure we can execute the script here (permissions lost during curl fetch)
+ chmod +x ./compile-all-examples.sh
+ echo "Found compile script: $(ls -al ./compile-all-examples.sh)"
+ popd
+
+ # ** END ** Get compile-all-examples.sh
+
+ # This will fail with Arduino published wolfSSL v5.7.6 and older
+ # as the examples moved. See https://github.com/wolfSSL/wolfssl/pull/8514
+ #
+ - name: Compile Arduino Sketches for Various Boards
+ run: |
+ # Call the compile-all-examples.sh script to compile all the examples for each of the fqbn names in the local copy of board_list.txt
+
+ echo "Current directory: $PWD"
+ echo "ARDUINO_ROOT: $ARDUINO_ROOT"
+ WOLFSSL_EXAMPLES_DIRECTORY="$ARDUINO_ROOT/wolfssl/examples"
+ echo "WOLFSSL_EXAMPLES_DIRECTORY: $WOLFSSL_EXAMPLES_DIRECTORY"
+ echo "FQBN = ${{ matrix.fqbn }}"
+
+ echo "Change directory to Arduino examples..."
+ pushd "$WOLFSSL_EXAMPLES_DIRECTORY"
+ echo "Current directory: $PWD"
+ ls -al
+ echo "Calling ./compile-all-examples.sh"
+ bash ./compile-all-examples.sh ./board_list.txt "${{ matrix.fqbn }}"
+ popd
+ # End Compile Arduino Sketches for Various Boards
diff --git a/.gitignore b/.gitignore
index ace2698..1c295c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,425 +1,12 @@
-ctaocrypt/src/src/
-*.swp
-*.lo
-*.la
-*.o
-*.patch
-*.deps
-*.d
-*.libs
-*.cache
-.dirstamp
-*.user
-configure
-config.*
-!cmake/config.in
-*Debug/
-*Release/
-*.ncb
-*.suo
-*.sdf
-*.opensdf
-*.cmd
-ipch/
-build-aux/
-rpm/spec
-*.rpm
-stamp-h
-cyassl/options.h
-wolfssl/options.h
-.build_params
-libtool.m4
-aclocal.m4
-aminclude.am
-lt*.m4
-Makefile.in
-Makefile
-depcomp
-missing
-libtool
-tags
-.tags*
-cyassl-config
-wolfssl-config
-cyassl.sublime*
-fips.h
-fips.c
-fips_test.c
-fips
-wolfcrypt_first.c
-wolfcrypt_last.c
-selftest.c
-fipsv2.c
-src/async.c
-wolfssl/async.h
-wolfcrypt/src/async.c
-wolfssl/wolfcrypt/async.h
-wolfcrypt/src/port/intel/quickassist.c
-wolfcrypt/src/port/intel/quickassist_mem.c
-wolfcrypt/src/port/cavium/cavium_nitrox.c
-wolfssl/wolfcrypt/port/intel/quickassist.h
-wolfssl/wolfcrypt/port/intel/quickassist_mem.h
-wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h
-ctaocrypt/benchmark/benchmark
-ctaocrypt/test/testctaocrypt
-wolfcrypt/benchmark/benchmark
-wolfcrypt/test/testwolfcrypt
-examples/async/async_client
-examples/async/async_server
-examples/benchmark/tls_bench
-examples/client/client
-examples/echoclient/echoclient
-examples/echoserver/echoserver
-examples/server/server
-examples/sctp/sctp-server
-examples/sctp/sctp-server-dtls
-examples/sctp/sctp-client
-examples/sctp/sctp-client-dtls
-examples/asn1/asn1
-examples/pem/pem
-server_ready
-snifftest
-output
-mcapi/test
-testsuite/testsuite
-tests/unit
-testsuite/testsuite.test
-tests/unit.test
-tests/bio_write_test.txt
-tests/test-log-dump-to-file.txt
-tests/cert_cache.tmp
-test-write-dhparams.pem
-testsuite/*.der
-testsuite/*.pem
-testsuite/*.raw
-cert.der
-cert.pem
-certecc.der
-certecc.pem
-othercert.der
-othercert.pem
-certeccrsa.der
-certeccrsa.pem
-ntru-cert.der
-ntru-cert.pem
-ntru-key.raw
-key.der
-key.pem
-ecc-public-key.der
-ecc-key-pkcs8.der
-ecc-key.der
-ecc-key.pem
-certreq.der
-certreq.pem
-pkcs7cert.der
-pkcs7authEnvelopedDataAES128GCM.der
-pkcs7authEnvelopedDataAES128GCM_ECDH_SHA1KDF.der
-pkcs7authEnvelopedDataAES128GCM_KEKRI.der
-pkcs7authEnvelopedDataAES128GCM_ORI.der
-pkcs7authEnvelopedDataAES128GCM_PWRI.der
-pkcs7authEnvelopedDataAES192GCM.der
-pkcs7authEnvelopedDataAES256GCM.der
-pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der
-pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_authAttribs.der
-pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_bothAttribs.der
-pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_fw_bothAttribs.der
-pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_unauthAttribs.der
-pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der
-pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der
-pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der
-pkcs7authEnvelopedDataAES256GCM_IANDS.der
-pkcs7authEnvelopedDataAES256GCM_SKID.der
-pkcs7compressedData_data_zlib.der
-pkcs7compressedData_firmwarePkgData_zlib.der
-pkcs7encryptedDataAES128CBC.der
-pkcs7encryptedDataAES192CBC.der
-pkcs7encryptedDataAES256CBC.der
-pkcs7encryptedDataAES256CBC_attribs.der
-pkcs7encryptedDataAES256CBC_firmwarePkgData.der
-pkcs7encryptedDataAES256CBC_multi_attribs.der
-pkcs7encryptedDataDES.der
-pkcs7encryptedDataDES3.der
-pkcs7envelopedDataAES128CBC.der
-pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der
-pkcs7envelopedDataAES128CBC_KEKRI.der
-pkcs7envelopedDataAES128CBC_PWRI.der
-pkcs7envelopedDataAES128CBC_ORI.der
-pkcs7envelopedDataAES192CBC.der
-pkcs7envelopedDataAES256CBC.der
-pkcs7envelopedDataAES256CBC_IANDS.der
-pkcs7envelopedDataAES256CBC_SKID.der
-pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der
-pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der
-pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der
-pkcs7envelopedDataDES3.der
-pkcs7signedData_ECDSA_SHA224.der
-pkcs7signedData_ECDSA_SHA256_custom_contentType.der
-pkcs7signedData_ECDSA_SHA256.der
-pkcs7signedData_ECDSA_SHA256_firmwarePkgData.der
-pkcs7signedData_ECDSA_SHA256_SKID.der
-pkcs7signedData_ECDSA_SHA384.der
-pkcs7signedData_ECDSA_SHA512.der
-pkcs7signedData_ECDSA_SHA.der
-pkcs7signedData_ECDSA_SHA_noattr.der
-pkcs7signedData_RSA_SHA224.der
-pkcs7signedData_RSA_SHA256_custom_contentType.der
-pkcs7signedData_RSA_SHA256.der
-pkcs7signedData_RSA_SHA256_firmwarePkgData.der
-pkcs7signedData_RSA_SHA256_SKID.der
-pkcs7signedData_RSA_SHA256_with_ca_cert.der
-pkcs7signedData_RSA_SHA256_detachedSig.der
-pkcs7signedData_RSA_SHA384.der
-pkcs7signedData_RSA_SHA512.der
-pkcs7signedData_RSA_SHA.der
-pkcs7signedData_RSA_SHA_noattr.der
-pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256.der
-pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der
-pkcs7signedCompressedFirmwarePkgData_RSA_SHA256.der
-pkcs7signedCompressedFirmwarePkgData_RSA_SHA256_noattr.der
-pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der
-pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der
-pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der
-pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256_noattr.der
-pkcs7signedFirmwarePkgData_ECDSA_SHA256.der
-pkcs7signedFirmwarePkgData_ECDSA_SHA256_SKID.der
-pkcs7signedFirmwarePkgData_ECDSA_SHA256_noattr.der
-pkcs7signedFirmwarePkgData_RSA_SHA256.der
-pkcs7signedFirmwarePkgData_RSA_SHA256_SKID.der
-pkcs7signedFirmwarePkgData_RSA_SHA256_noattr.der
-pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der
-pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256.der
-pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der
-pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der
-pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der
-diff
-sslSniffer/sslSnifferTest/tracefile.txt
-tracefile.txt
-*.gz
-*.zip
-*.bak
-*.dummy
-*.xcworkspace
-xcuserdata
-compile
-NTRU_algorithm/
-NTRU/
-build-test/
-build/
-cyassl.xcodeproj/
-cyassl*rc*
-autoscan.log
-TAGS
-.DS_Store
-support/cyassl.pc
-support/wolfssl.pc
-cyassl/ctaocrypt/stamp-h1
-stamp-h1
-clang_output_*
-internal.plist
-cov-int
-cyassl.tgz
-*.log
-*.trs
-IDE/MDK-ARM/Projects/
-IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/inc
-IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/src
-IDE/MDK-ARM/LPC43xx/Drivers/
-IDE/MDK-ARM/LPC43xx/LPC43xx/
-*.gcno
-*.gcda
-*.gcov
-*.dgcov
-!linuxkm/Makefile
-/Kbuild
-linuxkm/*.ko
-linuxkm/*.ko.signed
-linuxkm/Module.symvers
-linuxkm/built-in.a
-linuxkm/modules.order
-linuxkm/wolfcrypt
-linuxkm/libwolfssl.mod
-linuxkm/libwolfssl.mod.c
-linuxkm/libwolfssl.lds
-linuxkm/module_exports.c
-linuxkm/linuxkm/get_thread_size
-
-# autotools generated
-scripts/unit.test
-wolfcrypt/test/test_paths.h
-
-# MPLAB Generated Files (OS X)
-mcapi/wolfcrypt_mcapi.X/nbproject/Makefile-*
-mcapi/wolfcrypt_mcapi.X/nbproject/Package-default.bash
-mcapi/wolfcrypt_test.X/nbproject/Makefile-*
-mcapi/wolfcrypt_test.X/nbproject/Package-default.bash
-mcapi/wolfssl.X/nbproject/Makefile-*
-mcapi/wolfssl.X/nbproject/Package-default.bash
-mcapi/zlib.X/nbproject/Makefile-*
-mcapi/zlib.X/nbproject/Package-default.bash
-mplabx/wolfcrypt_benchmark.X/nbproject/Makefile-*
-mplabx/wolfcrypt_benchmark.X/nbproject/Package-default.bash
-mplabx/wolfcrypt_test.X/nbproject/Makefile-*
-mplabx/wolfcrypt_test.X/nbproject/Package-default.bash
-mplabx/wolfssl.X/nbproject/Makefile-*
-mplabx/wolfssl.X/nbproject/Package-default.bash
-mplabx/wolfssl.X/nbproject/private
-mplabx/wolfcrypt_test.X/nbproject/private
-mplabx/wolfcrypt_benchmark.X/nbproject/private
-mplabx/wolfssl.X/dist/default/
-mplabx/wolfcrypt_test.X/dist/default/
-mplabx/wolfcrypt_benchmark.X/dist/default/
-*.dSYM
-
-# Vagrant folder
-.vagrant/
-
-# CodeWarrior Generated Files (Windows)
-mqx/cyassl/.settings
-mqx/cyassl_client/.settings
-mqx/cyassl_client/.cwGeneratedFileSetLog
-mqx/cyassl_client/SaAnalysispointsManager.apconfig
-mqx/util_lib/.settings
-mqx/wolfcrypt_test/.settings
-mqx/wolfcrypt_test/.cwGeneratedFileSetLog
-mqx/wolfcrypt_test/SaAnalysispointsManager.apconfig
-mqx/wolfcrypt_benchmark/.settings
-mqx/wolfcrypt_benchmark/.cwGeneratedFileSetLog
-mqx/wolfcrypt_benchmark/SaAnalysispointsManager.apconfig
-
-# wolfSSL CSharp wrapper
-wrapper/CSharp/x64/
-
-# Visual Studio Code Workspace Files
-*.vscode
-*.userprefs
-*.exe
-*.dll
-.vs
-Backup
-UpgradeLog.htm
-*.aps
-*.VC.db
-*.filters
-
-IDE/INTIME-RTOS/Debug_*
-IDE/VS-ARM/.vs
-
-# Hexiwear
-IDE/HEXIWEAR/wolfSSL_HW/Debug
-
-# Linux-SGX
-IDE/LINUX-SGX/*.a
-
-IDE/iotsafe/*.map
-IDE/iotsafe/*.elf
-IDE/iotsafe/*.bin
-
-# Binaries
-wolfcrypt/src/port/intel/qat_test
-/mplabx/wolfssl.X/dist/default/
-/mplabx/wolfcrypt_test.X/dist/default/
-
-# Arduino Generated Files
-/IDE/ARDUINO/wolfSSL
-scripts/memtest.txt
-/IDE/ARDUINO/Arduino_README_prepend.md.tmp
-/IDE/ARDUINO/library.properties.tmp
-/IDE/ARDUINO/library.properties.tmp.backup
-
-# Doxygen generated files
-doc/doxygen_warnings
-doc/html
-doc/pdf
-
-# XCODE Index
-IDE/XCODE/Index
-IDE/**/xcshareddata
-IDE/**/DerivedData
-
-# ARM DS-5 && Eclipse
-\.settings/
-\.cproject
-\.project
-\.autotools
-
-# Renesas e2studio
-/IDE/Renesas/e2studio/Projects/test/src/smc_gen
-/IDE/Renesas/e2studio/Projects/test/trash
-/IDE/Renesas/e2studio/Projects/test/*.launch
-/IDE/Renesas/e2studio/Projects/test/*.scfg
-
-/IDE/Renesas/e2studio/RX65N/GR-ROSE/.metadata
-/IDE/Renesas/e2studio/RX65N/GR-ROSE/smc/src
-/IDE/Renesas/e2studio/RX65N/GR-ROSE/smc/trash
-/IDE/Renesas/e2studio/RX65N/GR-ROSE/test/src/smc_gen
-/IDE/Renesas/e2studio/RX65N/GR-ROSE/test/generate
-
-/IDE/Renesas/e2studio/RX65N/RSK/.metadata
-/IDE/Renesas/e2studio/RX65N/RSK/smc/src
-/IDE/Renesas/e2studio/RX65N/RSK/smc/trash
-/IDE/Renesas/e2studio/RX65N/RSK/test/src/smc_gen
-/IDE/Renesas/e2studio/RX65N/RSK/test/generate
-
-/IDE/Renesas/e2studio/RX72N/EnvisionKit/.metadata
-/IDE/Renesas/e2studio/RX72N/EnvisionKit/smc/src
-/IDE/Renesas/e2studio/RX72N/EnvisionKit/smc/trash
-/IDE/Renesas/e2studio/RX72N/EnvisionKit/test/src/smc_gen
-/IDE/Renesas/e2studio/RX72N/EnvisionKit/test/generate
-
-# QNX CAAM
-/IDE/QNX/example-server/server-tls
-/IDE/QNX/example-client/client-tls
-/IDE/QNX/example-cmac/cmac-test
-/IDE/QNX/CAAM-DRIVER/wolfCrypt
-
-# Xilinx
-/IDE/XilinxSDK/data
-
-# Emacs
-*~
-
-# CMake
-CMakeFiles/
-CMakeCache.txt
-cmake_install.cmake
-
-# GDB Settings
-\.gdbinit
-
-libFuzzer
-
-# Pycharm and other IDEs
-\.idea
-
-# FIPS
-XXX-fips-test
-
-# ASYNC
-/wolfAsyncCrypt
-/async
-
-# Generated user_settings_asm.h.
-user_settings_asm.h
-
-# VisualGD
-**/.visualgdb
-
-# Espressif sdk config default should be saved in sdkconfig.defaults
-# we won't track the actual working sdkconfig files
-/IDE/Espressif/**/sdkconfig
-/IDE/Espressif/**/sdkconfig.old
-
-# auto-created CMake backups
-**/CMakeLists.txt.old
-
-# MagicCrypto (ARIA Cipher)
-MagicCrypto
-
-# CMake build directory
-/out
-/out_temp
-
-# debian packaging
-debian/changelog
-debian/control
-*.deb
+################################################################################
+# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
+################################################################################
+
+/.vs
+/src/wolfcrypt/src/fips.c
+/src/wolfcrypt/src/fips_test.c
+/src/wolfcrypt/src/selftest.c
+/src/wolfcrypt/src/wolfcrypt_first.c
+/src/wolfcrypt/src/wolfcrypt_last.c
+/src/wolfssl/wolfcrypt/fips.h
+/**/*.bak
diff --git a/COPYING b/COPYING
index d159169..94a9ed0 100644
--- a/COPYING
+++ b/COPYING
@@ -1,281 +1,622 @@
GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
+ Version 3, 29 June 2007
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
this License.
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
@@ -287,15 +628,15 @@ free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
+state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
- This program is free software; you can redistribute it and/or modify
+ This program 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
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -303,37 +644,31 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- , 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+ .
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/ChangeLog.md b/ChangeLog.md
index 140d730..ed7c9a8 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,7 +1,1009 @@
-# wolfSSL Release X.Y.Z (TBD)
+# wolfSSL Release 5.8.4 (Nov. 20, 2025)
+
+Release 5.8.4 has been developed according to wolfSSL's development and QA
+process (see link below) and successfully passed the quality criteria.
+https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance
+
+NOTE: * --enable-heapmath is deprecated
+ * MD5 is now disabled by default
+
+PR stands for Pull Request, and PR references a GitHub pull request number where the code change was added.
+
+## Vulnerabilities
+* [Low CVE-2025-12888] Vulnerability in X25519 constant-time cryptographic implementations due to timing side channels introduced by compiler optimizations and CPU architecture limitations, specifically with the Xtensa-based ESP32 chips. If targeting Xtensa it is recommended to use the low memory implementations of X25519, which is now turned on as the default for Xtensa. Thanks to Adrian Cinal for the report. Fixed in PR 9275.
+
+
+* [Med. CVE-2025-11936] Potential DoS vulnerability due to a memory leak through multiple KeyShareEntry with the same group in malicious TLS 1.3 ClientHello messages. This affects users who are running wolfSSL on the server side with TLS 1.3. Thanks to Jaehun Lee and Kyungmin Bae, Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9117.
+
+* [Low CVE-2025-11935] PSK with PFS (Perfect Forward Secrecy) downgrades to PSK without PFS during TLS 1.3 handshake. If the client sends a ClientHello that has a key share extension and the server responds with a ServerHello that does not have a key share extension the connection would previously continue on without using PFS. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9112.
+
+* [Low CVE-2025-11934] Signature Algorithm downgrade from ECDSA P521 to P256 during TLS 1.3 handshake. When a client sends ECDSA P521 as the supported signature algorithm the server previously could respond as ECDSA P256 being the accepted signature algorithm and the connection would continue with using ECDSA P256. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9113.
+
+
+* [Low CVE-2025-11933] DoS Vulnerability in wolfSSL TLS 1.3 CKS extension parsing. Previously duplicate CKS extensions were not rejected leading to a potential memory leak when processing a ClientHello. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9132.
+
+
+* [Low CVE-2025-11931] Integer Underflow Leads to Out-of-Bounds Access in XChaCha20-Poly1305 Decrypt. This issue is hit specifically with a call to the function wc_XChaCha20Poly1305_Decrypt() which is not used with TLS connections, only from direct calls from an application. Thanks to Luigino Camastra from Aisle Research for the report. Fixed in PR 9223.
+
+* [Low CVE-2025-11932] Timing Side-Channel in PSK Binder Verification. The server previously verified the TLS 1.3 PSK binder using a non-constant time method which could potentially leak information about the PSK binder. Thanks to Luigino Camastra from Aisle Research for the report. Fixed in PR 9223.
+
+* [Low CVE-2025-12889] With TLS 1.2 connections a client can use any digest, specifically a weaker digest, rather than those in the CertificateRequest. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9395
+
+## New Features
+* New ML-KEM / ML-DSA APIs and seed/import PKCS8 support; added _new/_delete APIs for ML-KEM/ML-DSA. (PR 9039, 9000, 9049)
+* Initial wolfCrypt FreeBSD kernel module support (PR 9392)
+* Expanded PKCS7/CMS capabilities: decode SymmetricKeyPackage / OneSymmetricKey, add wc_PKCS7_GetEnvelopedDataKariRid, and allow PKCS7 builds with AES keywrap unset. (PR 9018, 9029, 9032)
+* Add custom AES key wrap/unwrap callbacks and crypto callback copy/free operations. (PR 9002, 9309)
+* Add support for certificate_authorities extension in ClientHello and certificate manager CA-type selection/unloading. (PR 9209, 9046)
+* Large expansion of Rust wrapper modules: random, aes, rsa, ecc, dh, sha, hmac, cmac, ed25519/ed448, pbkdf2/PKCS#12, kdf/prf, SRTP KDFs, and conditional compilation options. (PR 9191, 9212, 9273, 9306, 9320, 9328, 9368, 9389, 9357, 9433)
+* Rust: support optional heap and dev_id parameters and enable conditional compilation based on C build options. (PR 9407, 9433)
+* STM32 fixes (benchmarking and platform fixes) and PSoC6 hardware acceleration additions. (PR 9228, 9256, 9185)
+* STM32U5 added support for SAES and DHUK. (PR 9087)
+* Add --enable-curl=tiny option for a smaller build when used with cURL. (PR 9174)
+
+## Improvements / Optimizations
+* Regression test fixes and expansion: TLS 1.3/1.2 tests, ARDUINO examples, libssh2 tests, hostap workflows, and nightly test improvements. (PR 9096, 9141, 9091, 9122, 9388)
+* Improved test ordering and CI test stability (random tests run order changes, FIPS test fixes). (PR 9204, 9257)
+* Docs and readme fixes, docstring updates, AsconAEAD comment placement, and example certificate renewals. (PR 9131, 9293, 9262, 9429)
+* Updated GPL exception lists (GPLv2 and GPLv3 exception updates: add Fetchmail and OpenVPN). (PR 9398, 9413)
+* Introduced WOLFSSL_DEBUG_CERTS and additional debug/logging refinements. (PR 8902, 9055)
+* Expanded crypto-callback support (SHA family, HKDF, SHA-224, sha512_family digest selection) and improved crypto-only build cases. (PR 9070, 9252, 9271, 9100, 9194)
+* AES & HW offload improvements including AES-CTR support in PKCS11 driver and AES ECB offload sizing fix. (PR 9277, 9364)
+* ESP32: PSRAM allocator support and SHA HW fixes for ESP-IDF v6/v5. (PR 8987, 9225, 9264)
+* Renesas FSP / RA examples updated and security-module TLS context improvements. (PR 9047, 9010, 9158, 9150)
+* Broad configure/CMake/Autotools workflow improvements (Apple options tracking, Watcom pinning, Debian packaging, ESP-IDF pinning). (PR 9037, 9167, 9161, 9264)
+* New assembly introspection / performance helpers for RISC-V and PPC32; benchmarking enhancements (cycle counts). (PR 9101, 9317)
+* Update to SGX build for using assembly optimizations. (PR 8463, 9138)
+* Testing with Fil-C compiler version to 0.674 (PR 9396)
+* Refactors and compressing of small stack code (PR 9153)
+
+## Bug Fixes
+* Removed the test feature using popen when defining the macro WOLFSSL_USE_POPEN_HOST and not having HAVE_GETADDRINFO defined, along with having the macro HAVE_HTTP_CLIENT set. There was the potential for vulnerable behavior with the use of popen when the API wolfSSL_BIO_new_connect() was called with this specific build. This exact build configuration is only intended for testing with QEMU and is not enabled with any autoconf/cmake flags. Thanks to linraymond2006 for the report. (PR 9038)
+* Fix for C# wrapper Ed25519 potential crash and heap overwrite with raw public key import when using the API Ed25519ImportPublic.This was a broken API with the C# wrapper that would crash on use. Thanks to Luigino Camastra from Aisle Research for the bug report. (PR 9291)
+* Coverity, cppcheck, MISRA, clang-tidy, ZeroPath and other static-analysis driven fixes across the codebase. (PR 9006, 9078, 9068, 9265, 9324)
+* TLS 1.2/DTLS improvements: client message order checks, DTLS cookie/exchange and replay protections, better DTLS early-data handling. (PR 9387, 9253, 9205, 9367)
+* Improved X.509 & cert handling: allow larger pathLen in Basic Constraints, restore inner server name for ECH, retrying cert candidate chains. (PR 8890, 9234, 8692)
+* Sniffer robustness: fix infinite recursion, better handling of OOO appData and partial overlaps, and improved retransmission detection. (PR 9051, 9106, 9140, 9094)
+* Numerous linuxkm (kernel-mode) fixes, relocation/PIE normalization, and FIPS-related build tweaks across many iterations. (PR 9025, 9035, 9067, 9111, 9121)
+* ML-KEM/Kyber and ML-DSA fixes for out-of-bounds and seed-import correctness; multiple ML-related safety fixes. (PR 9142, 9105, 9439)
+* Avoid uninitialized-variable and GCC warnings; several fixes for undefined-shift/overflow issues. (PR 9020, 9372, 9195)
+* Memory & leak fixes in X509 verification and various struct sizing fixes for WOLFSSL_NO_MALLOC usage. (PR 9258, 9036)
+* Fixed RSA / signing / verify-only warnings allowing WOLFSSL_NO_CT_OPS when WOLFSSL_RSA_VERIFY_ONLY is used and API cleanups for using const. (PR 9031, 9263)
+
+
+# wolfSSL Release 5.8.2 (July 17, 2025)
+
+Release 5.8.2 has been developed according to wolfSSL's development and QA
+process (see link below) and successfully passed the quality criteria.
+https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance
+
+NOTE: * wolfSSL is now GPLv3 instead of GPLv2
+ * --enable-heapmath is deprecated
+ * MD5 is now disabled by default
+
+
+PR stands for Pull Request, and PR (NUMBER) references a GitHub pull request number where the code change was added.
+
+## Vulnerabilities
+
+* [Low] There is the potential for a fault injection attack on ECC and Ed25519 verify operations. In versions of wolfSSL 5.7.6 and later the --enable-faultharden option is available to help mitigate against potential fault injection attacks. The mitigation added in wolfSSL version 5.7.6 is to help harden applications relying on the results of the verify operations, such as when used with wolfBoot. If doing ECC or Ed25519 verify operations on a device at risk for fault injection attacks then --enable-faultharden could be used to help mitigate it. Thanks to Kevin from Fraunhofer AISEC for the report.
+
+Hardening option added in PR https://github.com/wolfSSL/wolfssl/pull/8289
+
+
+* [High CVE-2025-7395] When using WOLFSSL_SYS_CA_CERTS and WOLFSSL_APPLE_NATIVE_CERT_VALIDATION on an Apple platform, the native trust store verification routine overrides errors produced elsewhere in the wolfSSL certificate verification process including failures due to hostname matching/SNI, OCSP, CRL, etc. This allows any trusted cert chain to override other errors detected during chain verification that should have resulted in termination of the TLS connection. If building wolfSSL on versions after 5.7.6 and before 5.8.2 with use of the system CA support and the apple native cert validation feature enabled on Apple devices (on by default for non-macOS Apple targets when using autotools or CMake) we recommend updating to the latest version of wolfSSL. Thanks to Thomas Leong from ExpressVPN for the report.
+
+Fixed in PR https://github.com/wolfSSL/wolfssl/pull/8833
+
+
+* [Med. CVE-2025-7394] In the OpenSSL compatibility layer implementation, the function RAND_poll() was not behaving as expected and leading to the potential for predictable values returned from RAND_bytes() after fork() is called. This can lead to weak or predictable random numbers generated in applications that are both using RAND_bytes() and doing fork() operations. This only affects applications explicitly calling RAND_bytes() after fork() and does not affect any internal TLS operations. Although RAND_bytes() documentation in OpenSSL calls out not being safe for use with fork() without first calling RAND_poll(), an additional code change was also made in wolfSSL to make RAND_bytes() behave similar to OpenSSL after a fork() call without calling RAND_poll(). Now the Hash-DRBG used gets reseeded after detecting running in a new process. If making use of RAND_bytes() and calling fork() we recommend updating to the latest version of wolfSSL. Thanks to Per Allansson from Appgate for the report.
+
+Fixed in the following PR’s
+https://github.com/wolfSSL/wolfssl/pull/8849
+https://github.com/wolfSSL/wolfssl/pull/8867
+https://github.com/wolfSSL/wolfssl/pull/8898
+
+
+
+* [Low CVE-2025-7396] In wolfSSL 5.8.0 the option of hardening the C implementation of Curve25519 private key operations was added with the addition of blinding support (https://www.wolfssl.com/curve25519-blinding-support-added-in-wolfssl-5-8-0/). In wolfSSL release 5.8.2 that blinding support is turned on by default in applicable builds. The blinding configure option is only for the base C implementation of Curve25519. It is not needed, or available with; ARM assembly builds, Intel assembly builds, and the small Curve25519 feature. While the attack would be very difficult to execute in practice, enabling blinding provides an additional layer of protection for devices that may be more susceptible to physical access or side-channel observation. Thanks to Arnaud Varillon, Laurent Sauvage, and Allan Delautre from Telecom Paris for the report.
+
+Blinding enabled by default in PR https://github.com/wolfSSL/wolfssl/pull/8736
+
+
+## New Features
+* Multiple sessions are now supported in the sniffer due to the removal of a cached check. (PR #8723)
+* New API ssl_RemoveSession() has been implemented for sniffer cleanup operations. (PR #8768)
+* The new ASN X509 API, `wc_GetSubjectPubKeyInfoDerFromCert`, has been introduced for retrieving public key information from certificates. (PR #8758)
+* `wc_PKCS12_create()` has been enhanced to support PBE_AES(256|128)_CBC key and certificate encryptions. (PR #8782, PR #8822, PR #8859)
+* `wc_PKCS7_DecodeEncryptedKeyPackage()` has been added for decoding encrypted key packages. (PR #8976)
+* All AES, SHA, and HMAC functionality has been implemented within the Linux Kernel Module. (PR #8998)
+* Additions to the compatibility layer have been introduced for X.509 extensions and RSA PSS. Adding the API i2d_PrivateKey_bio, BN_ucmp and X509v3_get_ext_by_NID. (PR #8897)
+* Added support for STM32N6. (PR #8914)
+* Implemented SHA-256 for PPC 32 assembly. (PR #8894)
+
+## Improvements / Optimizations
+
+### Linux Kernel Module (LinuxKM) Enhancements
+* Registered DH and FFDHE for the Linux Kernel Module. (PR #8707)
+* Implemented fixes for standard RNG in the Linux Kernel Module. (PR #8718)
+* Added an ECDSA workaround for the Linux Kernel Module. (PR #8727)
+* Added more PKCS1 pad SHA variants for RSA in the Linux Kernel Module. (PR #8730)
+* Set default priority to 100000 for LKCAPI in the Linux Kernel Module. (PR #8740)
+* Ensured ECDH never has FIPS enabled in the Linux Kernel Module. (PR #8751)
+* Implemented further Linux Kernel Module and SP tweaks. (PR #8773)
+* Added sig_alg support for Linux 6.13 RSA in the Linux Kernel Module. (PR #8796)
+* Optimized wc_linuxkm_fpu_state_assoc. (PR #8828)
+* Ensured DRBG is multithread-round-1 in the Linux Kernel Module. (PR #8840)
+* Prevented toggling of fips_enabled in the Linux Kernel Module. (PR #8873)
+* Refactored drbg_ctx clear in the Linux Kernel Module. (PR #8876)
+* Set sig_alg max_size and digest_size callbacks for RSA in the Linux Kernel Module. (PR #8915)
+* Added get_random_bytes for the Linux Kernel Module. (PR #8943)
+* Implemented distro fix for the Linux Kernel Module. (PR #8994)
+* Fixed page-flags-h in the Linux Kernel Module. (PR #9001)
+* Added MODULE_LICENSE for the Linux Kernel Module. (PR #9005)
+
+### Post-Quantum Cryptography (PQC) & Asymmetric Algorithms
+* Kyber has been updated to the MLKEM ARM file for Zephyr (PR #8781)
+* Backward compatibility has been implemented for ML_KEM IDs (PR #8827)
+* ASN.1 is now ensured to be enabled when only building PQ algorithms (PR #8884)
+* Building LMS with verify-only has been fixed (PR #8913)
+* Parameters for LMS SHA-256_192 have been corrected (PR #8912)
+* State can now be saved with the private key for LMS (PR #8836)
+* Support for OpenSSL format has been added for ML-DSA/Dilithium (PR #8947)
+* `dilithium_coeff_eta2[]` has been explicitly declared as signed (PR #8955)
+
+### Build System & Portability
+* Prepared for the inclusion of v5.8.0 in the Ada Alire index. (PR #8714)
+* Introduced a new build option to allow reuse of the Windows crypt provider handle. (PR #8706)
+* Introduced general fixes for various build configurations. (PR #8763)
+* Made improvements for portability using older GCC 4.8.2. (PR #8753)
+* Macro guards updated to allow tests to build with opensslall and no server. (PR #8776)
+* Added a check for STDC_NO_ATOMICS macro before use of atomics. (PR #8885)
+* Introduced CMakePresets.json and CMakeSettings.json. (PR #8905)
+* Added an option to not use constant time code with min/max. (PR #8830)
+* Implemented proper MacOS dispatch for conditional signal/wait. (PR #8928)
+* Disabled MD5 by default for both general and CMake builds. (PR #8895, PR #8948)
+* Improved to allow building OPENSSL_EXTRA without KEEP_PEER_CERT. (PR #8926)
+* Added introspection for Intel and ARM assembly speedups. (PR #8954)
+* Fixed cURL config to set HAVE_EX_DATA and HAVE_ALPN. (PR #8973)
+* Moved FREESCALE forced algorithm HAVE_ECC to IDE/MQX/user_settings.h. (PR #8977)
+
+### Testing & Debugging
+* Fixed the exit status for testwolfcrypt. (PR #8762)
+* Added WOLFSSL_DEBUG_PRINTF and WOLFSSL_DEBUG_CERTIFICATE_LOADS for improved debugging output. (PR #8769, PR #8770)
+* Guarded some benchmark tests with NO_SW_BENCH. (PR #8760)
+* Added an additional unit test for wolfcrypt PKCS12 file to improve code coverage. (PR #8831)
+* Added an additional unit test for increased DH code coverage. (PR #8837)
+* Adjusted for warnings with NO_TLS build and added GitHub actions test. (PR #8851)
+* Added additional compatibility layer RAND tests. (PR #8852)
+* Added an API unit test for checking domain name. (PR #8863)
+* Added bind v9.18.33 testing. (PR #8888)
+* Fixed issue with benchmark help options and descriptions not lining up. (PR #8957)
+
+### Certificates & ASN.1
+* Changed the algorithm for sum in ASN.1 OIDs. (PR #8655)
+* Updated PKCS7 to use X509 STORE for internal verification. (PR #8748)
+* Improved handling of temporary buffer size for X509 extension printing. (PR #8710)
+* Marked IP address as WOLFSSL_V_ASN1_OCTET_STRING for ALT_NAMES_OID. (PR #8842)
+* Fixed printing empty names in certificates. (PR #8880)
+* Allowed CA:FALSE on wolftpm. (PR #8925)
+* Fixed several inconsistent function prototype parameter names in wc/asn. (PR #8949)
+* Accounted for custom extensions when creating a Cert from a WOLFSSL_X509. (PR #8960)
+
+### TLS/DTLS & Handshake
+* Checked group correctness outside of TLS 1.3 too for TLSX_UseSupportedCurve. (PR #8785)
+* Dropped records that span datagrams in DTLS. (PR #8642)
+* Implemented WC_NID_netscape_cert_type. (PR #8800)
+* Refactored GetHandshakeHeader/GetHandShakeHeader into one function. (PR #8787)
+* Correctly set the current peer in dtlsProcessPendingPeer. (PR #8848)
+* Fixed set_groups for TLS. (PR #8824)
+* Allowed trusted_ca_keys with TLSv1.3. (PR #8860)
+* Moved Dtls13NewEpoch into DeriveTls13Keys. (PR #8858)
+* Cleared tls1_3 on downgrade. (PR #8861)
+* Always sent ACKs on detected retransmission for DTLS1.3. (PR #8882)
+* Removed DTLS from echo examples. (PR #8889)
+* Recalculated suites at SSL initialization. (PR #8757)
+* No longer using BIO for ALPN. (PR #8969)
+* Fixed wolfSSL_BIO_new_connect's handling of IPV6 addresses. (PR #8815)
+* Memory Management & Optimizations
+* Performed small stack refactors, improved stack size with mlkem and dilithium, and added additional tests. (PR #8779)
+* Implemented FREE_MP_INT_SIZE in heap math. (PR #8881)
+* Detected correct MAX_ENCODED_SIG_SZ based on max support in math lib. (PR #8931)
+* Fixed improper access of sp_int_minimal using sp_int. (PR #8985)
+
+### Cryptography & Hash Functions
+* Implemented WC_SIPHASH_NO_ASM for not using assembly optimizations with siphash. (PR #8789, PR #8791)
+* Added missing DH_MAX_SIZE define for FIPS and corrected wolfssl.rc FILETYPE to VFT_DLL. (PR #8794)
+* Implemented WC_SHA3_NO_ASM for not using assembly with SHA3. (PR #8817)
+* Improved Aarch64 XFENCE. (PR #8832)
+* Omitted frame pointer for ARM32/Thumb2/RISC-V 64 assembly. (PR #8893)
+* Fixed branch instruction in ARMv7a ASM. (PR #8933)
+* Enabled EVP HMAC to work with WOLFSSL_HMAC_COPY_HASH. (PR #8944)
+* Platform-Specific & Hardware Integration
+* Added HAVE_HKDF for wolfssl_test and explicit support for ESP32P4. (PR #8742)
+* Corrected Espressif default time setting. (PR #8829)
+* Made wc_tsip_* APIs public. (PR #8717)
+* Improved PlatformIO Certificate Bundle Support. (PR #8847)
+* Fixed the TSIP TLS example program. (PR #8857)
+* Added crypto callback functions for TROPIC01 secure element. (PR #8812)
+* Added Renesas RX TSIP AES CTR support. (PR #8854)
+* Fixed TSIP port using crypto callback. (PR #8937)
+
+### General Improvements & Refactoring
+* Attempted wolfssl_read_bio_file in read_bio even when XFSEEK is available. (PR #8703)
+* Refactored GetHandshakeHeader/GetHandShakeHeader into one function. (PR #8787)
+* Updated libspdm from 3.3.0 to 3.7.0. (PR #8906)
+* Fixed missing dashes on the end of header and footer for Falcon PEM key. (PR #8904)
+* Fixed minor code typos for macos signal and types.h max block size. (PR #8934)
+* Make the API wolfSSL_X509_STORE_CTX_get_error accessible to more build configurations for ease of getting the "store" error code and depth with certificate failure callback implementations. (PR #8903)
+
+## Bug Fixes
+* Fixed issues to support _WIN32_WCE (VS 2008 with WinCE 6.0/7.0). (PR #8709)
+* Fixed STM32 Hash with IRQ enabled. (PR #8705)
+* Fixed raw hash when using crypto instructions on RISC-V 64-bit. (PR #8733)
+* Fixed ECDH decode secret in the Linux Kernel Module. (PR #8729)
+* Passed in the correct hash type to wolfSSL_RSA_verify_ex. (PR #8726)
+* Fixed issues for Intel QuickAssist latest driver (4.28). (PR #8728)
+* Speculative fix for CodeSonar overflow issue in ssl_certman.c. (PR #8715)
+* Fixed Arduino progmem print and AVR WOLFSSL_USER_IO. (PR #8668)
+* Correctly advanced the index in wc_HKDF_Expand_ex. (PR #8737)
+* Fixed STM32 hash status check logic, including NO_AES_192 and NO_AES_256. (PR #8732)
+* Added missing call to wolfSSL_RefFree in FreeCRL to prevent memory leaks. (PR #8750)
+* Fixed sanity check on --group with unit test app and null sanity check with des decrypt. (PR #8711)
+* Fixed Curve25519 and static ephemeral issue with blinding. (PR #8766)
+* Fixed edge case issue with STM32 AES GCM auth padding. (PR #8745)
+* Removed redefinition of MlKemKey and fixed build issue in benchmark. (PR #8755)
+* Used proper heap hint when freeing CRL in error case. (PR #8713)
+* Added support for no malloc with wc_CheckCertSigPubKey. (PR #8725)
+* Fixed C# wrapper Release build. (PR #8802)
+* Handled malformed CCS and CCS before CH in TLS1.3. (PR #8788)
+* Fixed ML-DSA with WOLFSSL_DILITHIUM_NO_SIGN. (PR #8798)
+* Fixed AesGcmCrypt_1 no-stream in the Linux Kernel Module. (PR #8814)
+* Fixed return value usage for crypto_sig_sign in the Linux Kernel Module. (PR #8816)
+* Fixed issue with CSharp and Windows CE with conversion of ASCII and Unicode. (PR #8799)
+* Fixed Renesas SCE on RA6M4. (PR #8838)
+* Fixed tests for different configs for ML-DSA. (PR #8865)
+* Fixed bug in ParseCRL_Extensions around the size of a CRL number handled and CRL number OID. (PR #8587)
+* Fixed uninitialized wc_FreeRng in prime_test. (PR #8886)
+* Fixed ECC configuration issues with ECC verify only and no RNG. (PR #8901)
+* Fixed issues with max size, openssl.test netcat, and clang-tidy. (PR #8909)
+* Fixed for casting down and uninit issues in Dilithium/ML-DSA. (PR #8868)
+* Fixed memory allocation failure testing and related unit test cases. (PR #8945, PR #8952)
+* Fixed build issue with ML-DSA 44 only. (PR #8981)
+* Fixed possible memory leak with X509 reference counter when using x509small. (PR #8982)
+
+
+# wolfSSL Release 5.8.0 (Apr 24, 2025)
+
+Release 5.8.0 has been developed according to wolfSSL's development and QA
+process (see link below) and successfully passed the quality criteria.
+https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance
+
+NOTE: * --enable-heapmath is deprecated
+
+PR stands for Pull Request, and PR (NUMBER) references a GitHub pull request
+ number where the code change was added.
+
+
+## New Feature Additions
+* Algorithm registration in the Linux kernel module for all supported FIPS AES,
+ SHA, HMAC, ECDSA, ECDH, and RSA modes, key sizes, and digest sizes.
+* Implemented various fixes to support building for Open Watcom including OS/2
+ support and Open Watcom 1.9 compatibility (PR 8505, 8484)
+* Added support for STM32H7S (tested on NUCLEO-H7S3L8) (PR 8488)
+* Added support for STM32WBA (PR 8550)
+* Added Extended Master Secret Generation Callback to the --enable-pkcallbacks
+ build (PR 8303)
+* Implement AES-CTS (configure flag --enable-aescts) in wolfCrypt (PR 8594)
+* Added support for libimobiledevice commit 860ffb (PR 8373)
+* Initial ASCON hash256 and AEAD128 support based on NIST SP 800-232 IPD
+ (PR 8307)
+* Added blinding option when using a Curve25519 private key by defining the
+ macro WOLFSSL_CURVE25519_BLINDING (PR 8392)
+
+
+## Linux Kernel Module
+* Production-ready LKCAPI registration for cbc(aes), cfb(aes), gcm(aes),
+ rfc4106 (gcm(aes)), ctr(aes), ofb(aes), and ecb(aes), ECDSA with P192, P256,
+ P384, and P521 curves, ECDH with P192, P256, and P384 curves, and RSA with
+ bare and PKCS1 padding
+* Various fixes for LKCAPI wrapper for AES-CBC and AES-CFB (PR 8534, 8552)
+* Adds support for the legacy one-shot AES-GCM back end (PR 8614, 8567) for
+ compatibility with FIPS 140-3 Cert #4718.
+* On kernel >=6.8, for CONFIG_FORTIFY_SOURCE, use 5-arg fortify_panic() override
+ macro (PR 8654)
+* Update calls to scatterwalk_map() and scatterwalk_unmap() for linux commit
+ 7450ebd29c (merged for Linux 6.15) (PR 8667)
+* Inhibit LINUXKM_LKCAPI_REGISTER_ECDH on kernel <5.13 (PR 8673)
+* Fix for uninitialized build error with fedora (PR 8569)
+* Register ecdsa, ecdh, and rsa for use with linux kernel crypto (PR 8637, 8663,
+ 8646)
+* Added force zero shared secret buffer, and clear of old key with ecdh
+ (PR 8685)
+* Update fips-check.sh script to pickup XTS streaming support on aarch64 and
+ disable XTS-384 as an allowed use in FIPS mode (PR 8509, 8546)
+
+
+## Enhancements and Optimizations
+
+### Security & Cryptography
+* Add constant-time implementation improvements for encoding functions. We thank
+ Zhiyuan and Gilles for sharing a new constant-time analysis tool (CT-LLVM) and
+ reporting several non-constant-time implementations. (PR 8396, 8617)
+* Additional support for PKCS7 verify and decode with indefinite lengths
+ (PR 8520, 834, 8645)
+* Add more PQC hybrid key exchange algorithms such as support for combinations
+ with X25519 and X448 enabling compatibility with the PQC key exchange support
+ in Chromium browsers and Mozilla Firefox (PR 7821)
+* Add short-circuit comparisons to DH key validation for RFC 7919 parameters
+ (PR 8335)
+* Improve FIPS compatibility with various build configurations for more resource
+ constrained builds (PR 8370)
+* Added option to disable ECC public key order checking (PR 8581)
+* Allow critical alt and basic constraints extensions (PR 8542)
+* New codepoint for MLDSA to help with interoperability (PR 8393)
+* Add support for parsing trusted PEM certs having the header
+ “BEGIN_TRUSTED_CERT” (PR 8400)
+* Add support for parsing only of DoD certificate policy and Comodo Ltd PKI OIDs
+ (PR 8599, 8686)
+* Update ssl code in `src/*.c` to be consistent with wolfcrypt/src/asn.c
+ handling of ML_DSA vs Dilithium and add dual alg. test (PR 8360, 8425)
+
+### Build System, Configuration, CI & Protocols
+* Internal refactor for include of config.h and when building with
+ BUILDING_WOLFSSL macro. This refactor will give a warning of “deprecated
+ function” when trying to improperly use an internal API of wolfSSL in an
+ external application. (PR 8640, 8647, 8660, 8662, 8664)
+* Add WOLFSSL_CLU option to CMakeLists.txt (PR 8548)
+* Add CMake and Zephyr support for XMSS and LMS (PR 8494)
+* Added GitHub CI for CMake builds (PR 8439)
+* Added necessary macros when building wolfTPM Zephyr with wolfSSL (PR 8382)
+* Add MSYS2 build continuous integration test (PR 8504)
+* Update DevKitPro doc to list calico dependency with build commands (PR 8607)
+* Conversion compiler warning fixes and additional continuous integration test
+ added (PR 8538)
+* Enable DTLS 1.3 by default in --enable-jni builds (PR 8481)
+* Enabled TLS 1.3 middlebox compatibility by default for --enable-jni builds
+ (PR 8526)
+
+### Performance Improvements
+* Performance improvements AES-GCM and HMAC (in/out hash copy) (PR 8429)
+* LMS fixes and improvements adding API to get Key ID from raw private key,
+ change to identifiers to match standard, and fix for when
+ WOLFSSL_LMS_MAX_LEVELS is 1 (PR 8390, 8684, 8613, 8623)
+* ML-KEM/Kyber improvements and fixes; no malloc builds, small memory usage,
+ performance improvement, fix for big-endian (PR 8397, 8412, 8436, 8467, 8619,
+ 8622, 8588)
+* Performance improvements for AES-GCM and when doing multiple HMAC operations
+ (PR 8445)
+
+### Assembly and Platform-Specific Enhancements
+* Poly1305 arm assembly changes adding ARM32 NEON implementation and fix for
+ Aarch64 use (PR 8344, 8561, 8671)
+* Aarch64 assembly enhancement to use more CPU features, fix for FreeBSD/OpenBSD
+ (PR 8325, 8348)
+* Only perform ARM assembly CPUID checks if support was enabled at build time
+ (PR 8566)
+* Optimizations for ARM32 assembly instructions on platforms less than ARMv7
+ (PR 8395)
+* Improve MSVC feature detection for static assert macros (PR 8440)
+* Improve Espressif make and CMake for ESP8266 and ESP32 series (PR 8402)
+* Espressif updates for Kconfig, ESP32P4 and adding a sample user_settings.h
+ (PR 8422, PR 8641)
+
+### OpenSSL Compatibility Layer
+* Modification to the push/pop to/from in OpenSSL compatibility layer. This is
+ a pretty major API change in the OpenSSL compatibility stack functions.
+ Previously the API would push/pop from the beginning of the list but now they
+ operate on the tail of the list. This matters when using the sk_value with
+ index values. (PR 8616)
+* OpenSSL Compat Layer: OCSP response improvements (PR 8408, 8498)
+* Expand the OpenSSL compatibility layer to include an implementation of
+ BN_CTX_get (PR 8388)
+
+### API Additions and Modifications
+* Refactor Hpke to allow multiple uses of a context instead of just one shot
+ mode (PR 6805)
+* Add support for PSK client callback with Ada and use with Alire (thanks
+ @mgrojo, PR 8332, 8606)
+* Change wolfSSL_CTX_GenerateEchConfig to generate multiple configs and add
+ functions wolfSSL_CTX_SetEchConfigs and wolfSSL_CTX_SetEchConfigsBase64 to
+ rotate the server's echConfigs (PR 8556)
+* Added the public API wc_PkcsPad to do PKCS padding (PR 8502)
+* Add NULL_CIPHER_TYPE support to wolfSSL_EVP_CipherUpdate (PR 8518)
+* Update Kyber APIs to ML-KEM APIs (PR 8536)
+* Add option to disallow automatic use of "default" devId using the macro
+ WC_NO_DEFAULT_DEVID (PR 8555)
+* Detect unknown key format on ProcessBufferTryDecode() and handle RSA-PSSk
+ format (PR 8630)
+
+### Porting and Language Support
+* Update Python port to support version 3.12.6 (PR 8345)
+* New additions for MAXQ with wolfPKCS11 (PR 8343)
+* Port to ntp 4.2.8p17 additions (PR 8324)
+* Add version 0.9.14 to tested libvncserver builds (PR 8337)
+
+### General Improvements and Cleanups
+* Cleanups for STM32 AES GCM (PR 8584)
+* Improvements to isascii() and the CMake key log option (PR 8596)
+* Arduino documentation updates, comments and spelling corrections (PR 8381,
+ 8384, 8514)
+* Expanding builds with WOLFSSL_NO_REALLOC for use with --enable-opensslall and
+ --enable-all builds (PR 8369, 8371)
+
+
+## Fixes
+* Fix a use after free caused by an early free on error in the X509 store
+ (PR 8449)
+* Fix to account for existing PKCS8 header with
+ wolfSSL_PEM_write_PKCS8PrivateKey (PR 8612)
+* Fixed failing CMake build issue when standard threads support is not found in
+ the system (PR 8485)
+* Fix segmentation fault in SHA-512 implementation for AVX512 targets built with
+ gcc -march=native -O2 (PR 8329)
+* Fix Windows socket API compatibility warning with mingw32 build (PR 8424)
+* Fix potential null pointer increments in cipher list parsing (PR 8420)
+* Fix for possible stack buffer overflow read with wolfSSL_SMIME_write_PKCS7.
+ Thanks to the team at Code Intelligence for the report. (PR 8466)
+* Fix AES ECB implementation for Aarch64 ARM assembly (PR 8379)
+* Fixed building with VS2008 and .NET 3.5 (PR 8621)
+* Fixed possible error case memory leaks in CRL and EVP_Sign_Final (PR 8447)
+* Fixed SSL_set_mtu compatibility function return code (PR 8330)
+* Fixed Renesas RX TSIP (PR 8595)
+* Fixed ECC non-blocking tests (PR 8533)
+* Fixed CMake on MINGW and MSYS (PR 8377)
+* Fixed Watcom compiler and added new CI test (PR 8391)
+* Fixed STM32 PKA ECC 521-bit support (PR 8450)
+* Fixed STM32 PKA with P521 and shared secret (PR 8601)
+* Fixed crypto callback macro guards with `DEBUG_CRYPTOCB` (PR 8602)
+* Fix outlen return for RSA private decrypt with WOLF_CRYPTO_CB_RSA_PAD
+ (PR 8575)
+* Additional sanity check on r and s lengths in DecodeECC_DSA_Sig_Bin (PR 8350)
+* Fix compat. layer ASN1_TIME_diff to accept NULL output params (PR 8407)
+* Fix CMake lean_tls build (PR 8460)
+* Fix for QUIC callback failure (PR 8475)
+* Fix missing alert types in AlertTypeToString for print out with debugging
+ enabled (PR 8572)
+* Fixes for MSVS build issues with PQC configure (PR 8568)
+* Fix for SE050 port and minor improvements (PR 8431, 8437)
+* Fix for missing rewind function in zephyr and add missing files for compiling
+ with assembly optimizations (PR 8531, 8541)
+* Fix for quic_record_append to return the correct code (PR 8340, 8358)
+* Fixes for Bind 9.18.28 port (PR 8331)
+* Fix to adhere more closely with RFC8446 Appendix D and set haveEMS when
+ negotiating TLS 1.3 (PR 8487)
+* Fix to properly check for signature_algorithms from the client in a TLS 1.3
+ server (PR 8356)
+* Fix for when BIO data is less than seq buffer size. Thanks to the team at Code
+ Intelligence for the report (PR 8426)
+* ARM32/Thumb2 fixes for WOLFSSL_NO_VAR_ASSIGN_REG and td4 variable declarations
+ (PR 8590, 8635)
+* Fix for Intel AVX1/SSE2 assembly to not use vzeroupper instructions unless ymm
+ or zmm registers are used (PR 8479)
+* Entropy MemUse fix for when block size less than update bits (PR 8675)
+
+
+# wolfSSL Release 5.7.6 (Dec 31, 2024)
+
+Release 5.7.6 has been developed according to wolfSSL's development and QA
+process (see link below) and successfully passed the quality criteria.
+https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance
+
+NOTE:
+ * --enable-heapmath is deprecated.
+ * In this release, the default cipher suite preference is updated to prioritize
+ TLS_AES_256_GCM_SHA384 over TLS_AES_128_GCM_SHA256 when enabled.
+ * This release adds a sanity check for including wolfssl/options.h or
+ user_settings.h.
+
+
+PR stands for Pull Request, and PR (NUMBER) references a GitHub pull request
+ number where the code change was added.
+
+
+## Vulnerabilities
+* [Med] An OCSP (non stapling) issue was introduced in wolfSSL version 5.7.4
+ when performing OCSP requests for intermediate certificates in a certificate
+ chain. This affects only TLS 1.3 connections on the server side. It would not
+ impact other TLS protocol versions or connections that are not using the
+ traditional OCSP implementation. (Fix in pull request 8115)
+
+
+## New Feature Additions
+* Add support for RP2350 and improve RP2040 support, both with RNG optimizations
+ (PR 8153)
+* Add support for STM32MP135F, including STM32CubeIDE support and HAL support
+ for SHA2/SHA3/AES/RNG/ECC optimizations. (PR 8223, 8231, 8241)
+* Implement Renesas TSIP RSA Public Enc/Private support (PR 8122)
+* Add support for Fedora/RedHat system-wide crypto-policies (PR 8205)
+* Curve25519 generic keyparsing API added with wc_Curve25519KeyToDer and
+ wc_Curve25519KeyDecode (PR 8129)
+* CRL improvements and update callback, added the functions
+ wolfSSL_CertManagerGetCRLInfo and wolfSSL_CertManagerSetCRLUpdate_Cb (PR 8006)
+* For DTLS, add server-side stateless and CID quality-of-life API. (PR 8224)
+
+
+## Enhancements and Optimizations
+* Add a CMake dependency check for pthreads when required. (PR 8162)
+* Update OS_Seed declarations for legacy compilers and FIPS modules (boundary
+ not affected). (PR 8170)
+* Enable WOLFSSL_ALWAYS_KEEP_SNI by default when using --enable-jni. (PR 8283)
+* Change the default cipher suite preference, prioritizing
+ TLS_AES_256_GCM_SHA384 over TLS_AES_128_GCM_SHA256. (PR 7771)
+* Add SRTP-KDF (FIPS module v6.0.0) to checkout script for release bundling
+ (PR 8215)
+* Make library build when no hardware crypto available for Aarch64 (PR 8293)
+* Update assembly code to avoid `uint*_t` types for better compatibility with
+ older C standards. (PR 8133)
+* Add initial documentation for writing ASN template code to decode BER/DER.
+ (PR 8120)
+* Perform full reduction in sc_muladd for EdDSA with Curve448 (PR 8276)
+* Allow SHA-3 hardware cryptography instructions to be explicitly not used in
+ MacOS builds (PR 8282)
+* Make Kyber and ML-KEM available individually and together. (PR 8143)
+* Update configuration options to include Kyber/ML-KEM and fix defines used in
+ wolfSSL_get_curve_name. (PR 8183)
+* Make GetShortInt available with WOLFSSL_ASN_EXTRA (PR 8149)
+* Improved test coverage and minor improvements of X509 (PR 8176)
+* Add sanity checks for configuration methods, ensuring the inclusion of
+ wolfssl/options.h or user_settings.h. (PR 8262)
+* Enable support for building without TLS (NO_TLS). Provides reduced code size
+ option for non-TLS users who want features like the certificate manager or
+ compatibility layer. (PR 8273)
+* Exposed get_verify functions with OPENSSL_EXTRA. (PR 8258)
+* ML-DSA/Dilithium: obtain security level from DER when decoding (PR 8177)
+* Implementation for using PKCS11 to retrieve certificate for SSL CTX (PR 8267)
+* Add support for the RFC822 Mailbox attribute (PR 8280)
+* Initialize variables and adjust types resolve warnings with Visual Studio in
+ Windows builds. (PR 8181)
+* Refactors and expansion of opensslcoexist build (PR 8132, 8216, 8230)
+* Add DTLS 1.3 interoperability, libspdm and DTLS CID interoperability tests
+ (PR 8261, 8255, 8245)
+* Remove trailing error exit code in wolfSSL install setup script (PR 8189)
+* Update Arduino files for wolfssl 5.7.4 (PR 8219)
+* Improve Espressif SHA HW/SW mutex messages (PR 8225)
+* Apply post-5.7.4 release updates for Espressif Managed Component examples
+ (PR 8251)
+* Expansion of c89 conformance (PR 8164)
+* Added configure option for additional sanity checks with --enable-faultharden
+ (PR 8289)
+* Aarch64 ASM additions to check CPU features before hardware crypto instruction
+ use (PR 8314)
+
+
+## Fixes
+* Fix a memory issue when using the compatibility layer with
+ WOLFSSL_GENERAL_NAME and handling registered ID types. (PR 8155)
+* Fix a build issue with signature fault hardening when using public key
+ callbacks (HAVE_PK_CALLBACKS). (PR 8287)
+* Fix for handling heap hint pointer properly when managing multiple WOLFSSL_CTX
+ objects and free’ing one of them (PR 8180)
+* Fix potential memory leak in error case with Aria. (PR 8268)
+* Fix Set_Verify flag behaviour on Ada wrapper. (PR 8256)
+* Fix a compilation error with the NO_WOLFSSL_DIR flag. (PR 8294)
+* Resolve a corner case for Poly1305 assembly code on Aarch64. (PR 8275)
+* Fix incorrect version setting in CSRs. (PR 8136)
+* Correct debugging output for cryptodev. (PR 8202)
+* Fix for benchmark application use with /dev/crypto GMAC auth error due to size
+ of AAD (PR 8210)
+* Add missing checks for the initialization of sp_int/mp_int with DSA to free
+ memory properly in error cases. (PR 8209)
+* Fix return value of wolfSSL_CTX_set_tlsext_use_srtp (8252)
+* Check Root CA by Renesas TSIP before adding it to ca-table (PR 8101)
+* Prevent adding a certificate to the CA cache for Renesas builds if it does not
+ set CA:TRUE in basic constraints. (PR 8060)
+* Fix attribute certificate holder entityName parsing. (PR 8166)
+* Resolve build issues for configurations without any wolfSSL/openssl
+ compatibility layer headers. (PR 8182)
+* Fix for building SP RSA small and RSA public only (PR 8235)
+* Fix for Renesas RX TSIP RSA Sign/Verify with wolfCrypt only (PR 8206)
+* Fix to ensure all files have settings.h included (like wc_lms.c) and guards
+ for building all `*.c` files (PR 8257 and PR 8140)
+* Fix x86 target build issues in Visual Studio for non-Windows operating
+ systems. (PR 8098)
+* Fix wolfSSL_X509_STORE_get0_objects to handle no CA (PR 8226)
+* Properly handle reference counting when adding to the X509 store. (PR 8233)
+* Fix for various typos and improper size used with FreeRTOS_bind in the Renesas
+ example. Thanks to Hongbo for the report on example issues. (PR 7537)
+* Fix for potential heap use after free with wolfSSL_PEM_read_bio_PrivateKey.
+ Thanks to Peter for the issue reported. (PR 8139)
+
+
+# wolfSSL Release 5.7.4 (Oct 24, 2024)
+
+Release 5.7.4 has been developed according to wolfSSL's development and QA
+process (see link below) and successfully passed the quality criteria.
+https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance
+
+NOTE: * --enable-heapmath is being deprecated and will be removed by end of 2024
+
+PR stands for Pull Request, and PR (NUMBER) references a GitHub pull request
+ number where the code change was added.
+
+
+## Vulnerabilities
+* [Low] When the OpenSSL compatibility layer is enabled, certificate
+ verification behaved differently in wolfSSL than OpenSSL, in the
+ X509_STORE_add_cert() and X509_STORE_load_locations() implementations.
+ Previously, in cases where an application explicitly loaded an intermediate
+ certificate, wolfSSL was verifying only up to that intermediate certificate,
+ rather than verifying up to the root CA. This only affects use cases where the
+ API is called directly, and does not affect TLS connections. Users that call
+ the API X509_STORE_add_cert() or X509_STORE_load_locations() directly in their
+ applications are recommended to update the version of wolfSSL used or to have
+ additional sanity checks on certificates loaded into the X509_STORE when
+ verifying a certificate. (https://github.com/wolfSSL/wolfssl/pull/8087)
+
+
+## PQC TLS Experimental Build Fix
+* When using TLS with post quantum algorithms enabled, the connection uses a
+ smaller EC curve than agreed on. Users building with --enable-experimental and
+ enabling PQC cipher suites with TLS connections are recommended to update the
+ version of wolfSSL used. Thanks to Daniel Correa for the report.
+ (https://github.com/wolfSSL/wolfssl/pull/8084)
+
+
+## New Feature Additions
+* RISC-V 64 new assembly optimizations added for SHA-256, SHA-512, ChaCha20,
+ Poly1305, and SHA-3 (PR 7758,7833,7818,7873,7916)
+* Implement support for Connection ID (CID) with DTLS 1.2 (PR 7995)
+* Add support for (DevkitPro)libnds (PR 7990)
+* Add port for Mosquitto OSP (Open Source Project) (PR 6460)
+* Add port for init sssd (PR 7781)
+* Add port for eXosip2 (PR 7648)
+* Add support for STM32G4 (PR 7997)
+* Add support for MAX32665 and MAX32666 TPU HW and ARM ASM Crypto Callback
+ Support (PR 7777)
+* Add support for building wolfSSL to be used in libspdm (PR 7869)
+* Add port for use with Nucleus Plus 2.3 (PR 7732)
+* Initial support for RFC5755 x509 attribute certificates (acerts). Enabled with
+ --enable-acert (PR 7926)
+* PKCS#11 RSA Padding offload allows tokens to perform CKM_RSA_PKCS
+ (sign/encrypt), CKM_RSA_PKCS_PSS (sign), and CKM_RSA_PKCS_OAEP (encrypt).
+ (PR 7750)
+* Added “new” and “delete” style functions for heap/pool allocation and freeing
+ of low level crypto structures (PR 3166 and 8089)
+
+
+## Enhancements and Optimizations
+* Increase default max alt. names from 128 to 1024 (PR 7762)
+* Added new constant time DH agree function wc_DhAgree_ct (PR 7802)
+* Expanded compatibility layer with the API EVP_PKEY_is_a (PR 7804)
+* Add option to disable cryptocb test software test using
+ --disable-cryptocb-sw-test (PR 7862)
+* Add a call to certificate verify callback before checking certificate dates
+ (PR 7895)
+* Expanded algorithms supported with the wolfCrypt CSharp wrapper. Adding
+ support for RNG, ECC(ECIES and ECDHE), RSA, ED25519/Curve25519, AES-GCM, and
+ Hashing (PR 3166)
+* Expand MMCAU support for use with DES ECB (PR 7960)
+* Update AES SIV to handle multiple associated data inputs (PR 7911)
+* Remove HAVE_NULL_CIPHER from --enable-openssh (PR 7811)
+* Removed duplicate if(NULL) checks when calling XFREE (macro does) (PR 7839)
+* Set RSA_MIN_SIZE default to 2048 bits (PR 7923)
+* Added support for wolfSSL to be used as the default TLS in the zephyr kernel
+ (PR 7731)
+* Add enable provider build using --enable-wolfprovider with autotools (PR 7550)
+* Renesas RX TSIP ECDSA support (PR 7685)
+* Support DTLS1.3 downgrade when the server supports CID (PR 7841)
+* Server-side checks OCSP even if it uses v2 multi (PR 7828)
+* Add handling of absent hash params in PKCS7 bundle parsing and creation
+ (PR 7845)
+* Add the use of w64wrapper for Poly1305, enabling Poly1305 to be used in
+ environments that do not have a word64 type (PR 7759)
+* Update to the maxq10xx support (PR 7824)
+* Add support for parsing over optional PKCS8 attributes (PR 7944)
+* Add support for either side method with DTLS 1.3 (PR 8012)
+* Added PKCS7 PEM support for parsing PEM data with BEGIN/END PKCS7 (PR 7704)
+* Add CMake support for WOLFSSL_CUSTOM_CURVES (PR 7962)
+* Add left-most wildcard matching support to X509_check_host() (PR 7966)
+* Add option to set custom SKID with PKCS7 bundle creation (PR 7954)
+* Building wolfSSL as a library with Ada and corrections to Alire manifest
+ (PR 7303,7940)
+* Renesas RX72N support updated (PR 7849)
+* New option WOLFSSL_COPY_KEY added to always copy the key to the SSL object
+ (PR 8005)
+* Add the new option WOLFSSL_COPY_CERT to always copy the cert buffer for each
+ SSL object (PR 7867)
+* Add an option to use AES-CBC with HMAC for default session ticket enc/dec.
+ Defaults to AES-128-CBC with HMAC-SHA256 (PR 7703)
+* Memory usage improvements in wc_PRF, sha256 (for small code when many
+ registers are available) and sp_int objects (PR 7901)
+* Change in the configure script to work around ">>" with no command. In older
+ /bin/sh it can be ambiguous, as used in OS’s such as FreeBSD 9.2 (PR 7876)
+* Don't attempt to include system headers when not required (PR 7813)
+* Certificates: DER encoding of ECC signature algorithm parameter is now
+ allowed to be NULL with a define (PR 7903)
+* SP x86_64 asm: check for AVX2 support for VMs (PR 7979)
+* Update rx64n support on gr-rose (PR 7889)
+* Update FSP version to v5.4.0 for RA6M4 (PR 7994)
+* Update TSIP driver version to v1.21 for RX65N RSK (PR 7993)
+* Add a new crypto callback for RSA with padding (PR 7907)
+* Replaced the use of pqm4 with wolfSSL implementations of Kyber/MLDSA
+ (PR 7924)
+* Modernized memory fence support for C11 and clang (PR 7938)
+* Add a CRL error override callback (PR 7986)
+* Extend the X509 unknown extension callback for use with a user context
+ (PR 7730)
+* Additional debug error tracing added with TLS (PR 7917)
+* Added runtime support for library call stack traces with
+ –enable-debug-trace-errcodes=backtrace, using libbacktrace (PR 7846)
+* Expanded C89 conformance (PR 8077)
+* Expanded support for WOLFSSL_NO_MALLOC (PR 8065)
+* Added support for cross-compilation of Linux kernel module (PR 7746)
+* Updated Linux kernel module with support for kernel 6.11 and 6.12 (PR 7826)
+* Introduce WOLFSSL_ASN_ALLOW_0_SERIAL to allow parsing of certificates with a
+ serial number of 0 (PR 7893)
+* Add conditional repository_owner to all wolfSSL GitHub workflows (PR 7871)
+
+### Espressif / Arduino Updates
+* Update wolfcrypt settings.h for Espressif ESP-IDF, template update (PR 7953)
+* Update Espressif sha, util, mem, time helpers (PR 7955)
+* Espressif _thread_local_start and _thread_local_end fix (PR 8030)
+* Improve benchmark for Espressif devices (PR 8037)
+* Introduce Espressif common CONFIG_WOLFSSL_EXAMPLE_NAME, Kconfig (PR 7866)
+* Add wolfSSL esp-tls and Certificate Bundle Support for Espressif ESP-IDF
+ (PR 7936)
+* Update wolfssl Release for Arduino (PR 7775)
+
+### Post Quantum Crypto Updates
+* Dilithium: support fixed size arrays in dilithium_key (PR 7727)
+* Dilithium: add option to use precalc with small sign (PR 7744)
+* Allow Kyber to be built with FIPS (PR 7788)
+* Allow Kyber asm to be used in the Linux kernel module (PR 7872)
+* Dilithium, Kyber: Update to final specification (PR 7877)
+* Dilithium: Support FIPS 204 Draft and Final Draft (PR 7909,8016)
+
+### ARM Assembly Optimizations
+* ARM32 assembly optimizations added for ChaCha20 and Poly1305 (PR 8020)
+* Poly1305 assembly optimizations improvements for Aarch64 (PR 7859)
+* Poly1305 assembly optimizations added for Thumb-2 (PR 7939)
+* Adding ARM ASM build option to STM32CubePack (PR 7747)
+* Add ARM64 to Visual Studio Project (PR 8010)
+* Kyber assembly optimizations for ARM32 and Aarch64 (PR 8040,7998)
+* Kyber assembly optimizations for ARMv7E-M/ARMv7-M (PR 7706)
+
+
+## Fixes
+* ECC key load: fixes for certificates with parameters that are not default for
+ size (PR 7751)
+* Fixes for building x86 in Visual Studio for non-windows OS (PR 7884)
+* Fix for TLS v1.2 secret callback, incorrectly detecting bad master secret
+ (PR 7812)
+* Fixes for PowerPC assembly use with Darwin and SP math all (PR 7931)
+* Fix for detecting older versions of Mac OS when trying to link with
+ libdispatch (PR 7932)
+* Fix for DTLS1.3 downgrade to DTLS1.2 when the server sends multiple handshake
+ packets combined into a single transmission. (PR 7840)
+* Fix for OCSP to save the request if it was stored in ssl->ctx->certOcspRequest
+ (PR 7779)
+* Fix to OCSP for searching for CA by key hash instead of ext. key id (PR 7934)
+* Fix for staticmemory and singlethreaded build (PR 7737)
+* Fix to not allow Shake128/256 with Xilinx AFALG (PR 7708)
+* Fix to support PKCS11 without RSA key generation (PR 7738)
+* Fix not calling the signing callback when using PK callbacks + TLS 1.3
+ (PR 7761)
+* Cortex-M/Thumb2 ASM fix label for IAR compiler (PR 7753)
+* Fix with PKCS11 to iterate correctly over slotId (PR 7736)
+* Stop stripping out the sequence header on the AltSigAlg extension (PR 7710)
+* Fix ParseCRL_AuthKeyIdExt with ASN template to set extAuthKeyIdSet value
+ (PR 7742)
+* Use max key length for PSK encrypt buffer size (PR 7707)
+* DTLS 1.3 fix for size check to include headers and CID fixes (PR 7912,7951)
+* Fix STM32 Hash FIFO and add support for STM32U5A9xx (PR 7787)
+* Fix CMake build error for curl builds (PR 8021)
+* SP Maths: PowerPC ASM fix to use XOR instead of LI (PR 8038)
+* SSL loading of keys/certs: testing and fixes (PR 7789)
+* Misc. fixes for Dilithium and Kyber (PR 7721,7765,7803,8027,7904)
+* Fixes for building wolfBoot sources for PQ LMS/XMSS (PR 7868)
+* Fixes for building with Kyber enabled using CMake and zephyr port (PR 7773)
+* Fix for edge cases with session resumption with TLS 1.2 (PR 8097)
+* Fix issue with ARM ASM with AES CFB/OFB not initializing the "left" member
+ (PR 8099)
+
+
+# wolfSSL Release 5.7.2 (July 08, 2024)
+
+Release 5.7.2 has been developed according to wolfSSL's development and QA
+process (see link below) and successfully passed the quality criteria.
+https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance
+
+NOTE: * --enable-heapmath is being deprecated and will be removed by end of 2024
+
+## Vulnerabilities
+* [Medium] CVE-2024-1544
+Potential ECDSA nonce side channel attack in versions of wolfSSL before 5.6.6 with wc_ecc_sign_hash calls. Generating the ECDSA nonce k samples a random number r and then truncates this randomness with a modular reduction mod n where n is the order of the elliptic curve. Analyzing the division through a control-flow revealing side-channel reveals a bias in the most significant bits of k. Depending on the curve this is either a negligible bias or a significant bias large enough to reconstruct k with lattice reduction methods. Thanks to Luca Wilke, Florian Sieck and Thomas Eisenbarth (University of Lübeck) for reporting the vulnerability. Details will appear in the proceedings of CCS 24.
+Fixed https://github.com/wolfSSL/wolfssl/pull/7020
+
+
+* [Medium] CVE-2024-5288
+A private key blinding operation, enabled by defining the macro WOLFSSL_BLIND_PRIVATE_KEY, was added to mitigate a potential row hammer attack on ECC operations. If performing ECC private key operations in an environment where a malicious user could gain fine control over the device and perform row hammer style attacks it is recommended to update the version of wolfSSL used and to build with WOLFSSL_BLIND_PRIVATE_KEY defined. Thanks to Kemal Derya, M. Caner Tol, Berk Sunar for the report (Vernam Applied Cryptography and Cybersecurity Lab at Worcester Polytechnic Institute)
+Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7416
+
+
+* [Low] When parsing a provided maliciously crafted certificate directly using wolfSSL API, outside of a TLS connection, a certificate with an excessively large number of extensions could lead to a potential DoS. There are existing sanity checks during a TLS handshake with wolfSSL which mitigate this issue. Thanks to Bing Shi for the report.
+Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7597
+
+* [Low] CVE-2024-5991
+In the function MatchDomainName(), input param str is treated as a NULL terminated string despite being user provided and unchecked. Specifically, the Openssl compatibility function X509_check_host() takes in a pointer and length to check against, with no requirements that it be NULL terminated. While calling without a NULL terminated string is very uncommon, it is still technically allowed. If a caller was attempting to do a name check on a non*NULL terminated buffer, the code would read beyond the bounds of the input array until it found a NULL terminator.
+Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7604
+
+* [Medium] CVE-2024-5814
+A malicious TLS1.2 server can force a TLS1.3 client with downgrade capability to use a ciphersuite that it did not agree to and achieve a successful connection. This is because, aside from the extensions, the client was skipping fully parsing the server hello when downgrading from TLS 1.3.
+Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7619
+
+* [Medium] OCSP stapling version 2 response verification bypass issue when a crafted response of length 0 is received. Found with internal testing.
+Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7702
+
+* [Medium] OCSP stapling version 2 revocation bypass with a retry of a TLS connection attempt. A revoked CA certificate could incorrectly be loaded into the trusted signers list and used in a repeat connection attempt. Found with internal testing.
+Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7702
+
+
+## New Feature Additions
+* Added Dilithium/ML-DSA: Implementation of ML-DSA-44/65/87 (PR 7622)
+* AES RISC-V 64-bit ASM: ECB/CBC/CTR/GCM/CCM (PR 7569)
+* Added CUDA support for AES encryption (PR 7436)
+* Added support for gRPC (PR 7445)
+* Added function wc_RsaPrivateKeyDecodeRaw to import raw RSA private keys (PR 7608)
+* Added crypto callback for SHA-3 (PR 7670)
+* Support for Infineon Modus Toolbox with wolfSSL (PR 7369)
+* Allow user to send a user_canceled alert by calling wolfSSL_SendUserCanceled (PR 7590)
+* C# wrapper SNI support added (PR 7610)
+* Quantum-safe algorithm support added to the Linux kernel module (PR 7574)
+* Support for NIST 800-56C Option 1 KDF, using the macro WC_KDF_NIST_SP_800_56C added (PR 7589)
+* AES-XTS streaming mode added, along with hardware acceleration and kernel module use (PR 7522, 7560, 7424)
+* PlatformIO FreeRTOS with ESP build and addition of benchmark and test example applications (PR 7528, 7413, 7559, 7542)
+
+
+## Enhancements and Optimizations
+* Expanded STM32 AES hardware acceleration support for use with STM32H5 (PR 7578)
+* Adjusted wc_xmss and wc_lms settings to support use with wolfBoot (PR 7393)
+* Added the --enable-rpk option to autotools build for using raw public key support (PR 7379)
+* SHA-3 Thumb2, ARM32 assembly implementation added (PR 7667)
+* Improvements to RSA padding to expose Pad/Unpad APIs (PR 7612)
+* Updates and API additions for supporting socat version 1.8.0.0 (PR 7594)
+* cmake build improvements, expanding build options with SINGLE_THREADED and post-quantum algorithms, adjusting the generation of options.h file and using “yes;no” boolean instead of strings (PR 7611, 7546, 7479, 7480, 7380)
+* Improvements for Renesas RZ support (PR 7474)
+* Improvements to dual algorithm certificates for post-quantum keys (PR 7286)
+* Added wolfSSL_SessionIsSetup so the user can check if a session ticket has been sent by the server (PR 7430)
+* hostap updates: Implement PACs for EAP-FAST and filter cipher list on TLS version change (PR 7446)
+* Changed subject name comparison to match different upper and lower cases (PR 7420)
+* Support for DTLS 1.3 downgrade when using PSK (PR 7367)
+* Update to static memory build for more generic memory pools used (PR 7418)
+* Improved performance of Kyber C implementation (PR 7654)
+* Support for ECC_CACHE_CURVE with no malloc (PR 7490)
+* Added the configure option --enable-debug-trace-errcodes (macro WOLFSSL_DEBUG_TRACE_ERROR_CODES) which enables more debug tracking of error code values (PR 7634)
+* Enhanced wc_MakeRsaKey and wc_RsaKeyToDer to work with WOLFSSL_NO_MALLOC (PR 7362)
+* Improvements to assembly implementations of ChaCha20 and Poly1305 ASM for use with MSVC (PR 7319)
+* Cortex-M inline assembly labels with unique number appended (PR 7649)
+* Added secret logging callback to TLS <= 1.2, enabled with the macro HAVE_SECRET_CALLBACK (PR 7372)
+* Made wc_RNG_DRBG_Reseed() a public wolfCrypt API (PR 7386)
+* Enabled DES3 support without the DES3 ciphers. To re-enable DES3 cipher suites, use the configure flag --enable-des3-tls-suites (PR 7315)
+* Added stubs required for latest nginx (1.25.5) (PR 7449)
+* Added option for using a custom salt with the function wc_ecc_ctx_set_own_salt (PR 7552)
+* Added PQ files for Windows (PR 7419)
+* Enhancements to static memory feature, adding the option for a global heap hint (PR 7478) and build options for a lean or debug setting, enabled with --enable-staticmemory=small or --enable-staticmemory=debug (PR 7597)
+* Updated --enable-jni to define SESSION_CERTS for wolfJSSE (PR 7557)
+* Exposed DTLS in Ada wrapper and updated examples (PR 7397)
+* Added additional minimum TLS extension size sanity checks (PR 7602)
+* ESP improvements: updating the examples and libraries, updates for Apple HomeKit SHA/SRP, and fix for endianness with SHA512 software fallback (PR 7607, 7392, 7505, 7535)
+* Made the wc_CheckCertSigPubKey API publicly available with the define of the macro WOLFSSL_SMALL_CERT_VERIFY (PR 7599)
+* Added an alpha/preview of additional FIPS 140-3 full submission, bringing additional algorithms such as SRTP-KDF, AES-XTS, GCM streaming, AES-CFB, ED25519, and ED448 into the FIPS module boundary (PR 7295)
+* XCODE support for v5.2.3 of the FIPS module (PR 7140)
+* Expanded OpenSSL compatibility layer and added EC_POINT_hex2point (PR 7191)
+
+## Fixes
+* Fixed Kyber control-flow timing leak. Thanks to Antoon Purnal from PQShield for the report
+* Fixed the NXP MMCAU HW acceleration for SHA-256 (PR 7389)
+* Fixed AES-CFB1 encrypt/decrypt on size (8*x-1) bits (PR 7431)
+* Fixed use of %rip with SHA-256 x64 assembly (PR 7409)
+* Fixed OCSP response message build for DTLS (PR 7671)
+* Handled edge case in wc_ecc_mulmod() with zero (PR 7532)
+* Fixed RPK (Raw Public Key) to follow certificate use correctly (PR 7375)
+* Added sanity check on record header with QUIC use (PR 7638)
+* Added sanity check for empty directory strings in X.509 when parsing (PR 7669)
+* Added sanity check on non-conforming serial number of 0 in certificates being parsed (PR 7625)
+* Fixed wolfSSL_CTX_set1_sigalgs_list() to make the TLS connection conform to the selected sig hash algorithm (PR 7693)
+* Various fixes for dual algorithm certificates including small stack use and support for Certificate Signing Requests (PR 7577)
+* Added sanity check for critical policy extension when wolfSSL is built without policy extension support enabled (PR 7388)
+* Added sanity check that the ed25519 signature is smaller than the order (PR 7513)
+* Fixed Segger emNet to handle non-blocking want read/want write (PR 7581)
+
+
+# wolfSSL Release 5.7.0 (Mar 20, 2024)
+
+Release 5.7.0 has been developed according to wolfSSL's development and QA
+process (see link below) and successfully passed the quality criteria.
+https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance
+
+NOTE: * --enable-heapmath is being deprecated and will be removed by end of 2024
+
+NOTE: In future releases, --enable-des3 (which is disabled by default) will be insufficient in itself to enable DES3 in TLS cipher suites. A new option, --enable-des3-tls-suites, will need to be supplied in addition. This option should only be used in backward compatibility scenarios, as it is inherently insecure.
NOTE: This release switches the default ASN.1 parser to the new ASN template code. If the original ASN.1 code is preferred define `WOLFSSL_ASN_ORIGINAL` to use it. See PR #7199.
+
+## Vulnerabilities
+* [High] CVE-2024-0901 Potential denial of service and out of bounds read. Affects TLS 1.3 on the server side when accepting a connection from a malicious TLS 1.3 client. If using TLS 1.3 on the server side it is recommended to update the version of wolfSSL used. Fixed in this GitHub pull request https://github.com/wolfSSL/wolfssl/pull/7099
+
+
+* [Med] CVE-2024-1545 Fault Injection vulnerability in RsaPrivateDecryption function that potentially allows an attacker that has access to the same system with a victims process to perform a Rowhammer fault injection. Thanks to Junkai Liang, Zhi Zhang, Xin Zhang, Qingni Shen for the report (Peking University, The University of Western Australia)."
+Fixed in this GitHub pull request https://github.com/wolfSSL/wolfssl/pull/7167
+
+
+* [Med] Fault injection attack with EdDSA signature operations. This affects ed25519 sign operations where the system could be susceptible to Rowhammer attacks. Thanks to Junkai Liang, Zhi Zhang, Xin Zhang, Qingni Shen for the report (Peking University, The University of Western Australia).
+Fixed in this GitHub pull request https://github.com/wolfSSL/wolfssl/pull/7212
+
+
+## New Feature Additions
+
+* Added --enable-experimental configure flag to gate out features that are currently experimental. Now liboqs, kyber, lms, xmss, and dual-alg-certs require the --enable-experimental flag.
+
+### POST QUANTUM SUPPORT ADDITIONS
+* Experimental framework for using wolfSSL’s XMSS implementation (PR 7161)
+* Experimental framework for using wolfSSL’s LMS implementation (PR 7283)
+* Experimental wolfSSL Kyber implementation and assembly optimizations, enabled with --enable-experimental --enable-kyber (PR 7318)
+* Experimental support for post quantum dual key/signature certificates. A few known issues and sanitizer checks are in progress with this feature. Enabled with the configure flags --enable-experimental --enable-dual-alg-certs (PR 7112)
+* CryptoCb support for PQC algorithms (PR 7110)
+
+### OTHER FEATURE ADDITIONS
+* The Linux kernel module now supports registration of AES-GCM, AES-XTS, AES-CBC, and AES-CFB with the kernel cryptosystem through the new --enable-linuxkm-lkcapi-register option, enabling automatic use of wolfCrypt implementations by the dm-crypt/luks and ESP subsystems. In particular, wolfCrypt AES-XTS with –enable-aesni is faster than the native kernel implementation.
+* CryptoCb hook to one-shot CMAC functions (PR 7059)
+* BER content streaming support for PKCS7_VerifySignedData and sign/encrypt operations (PR 6961 & 7184)
+* IoT-Safe SHA-384 and SHA-512 support (PR 7176)
+* I/O callbacks for content and output with PKCS7 bundle sign/encrypt to reduce peak memory usage (PR 7272)
+* Microchip PIC24 support and example project (PR 7151)
+* AutoSAR shim layer for RNG, SHA256, and AES (PR 7296)
+* wolfSSL_CertManagerUnloadIntermediateCerts API to clear intermediate certs added to certificate store (PR 7245)
+* Implement SSL_get_peer_signature_nid and SSL_get_peer_signature_type_nid (PR 7236)
+
+
+## Enhancements and Optimizations
+
+* Remove obsolete user-crypto functionality and Intel IPP support (PR 7097)
+* Support for RSA-PSS signatures with CRL use (PR 7119)
+* Enhancement for AES-GCM use with Xilsecure on Microblaze (PR 7051)
+* Support for crypto cb only build with ECC and NXP CAAM (PR 7269)
+* Improve liboqs integration adding locking and init/cleanup functions (PR 7026)
+* Prevent memory access before clientSession->serverRow and clientSession->serverIdx are sanitized (PR 7096)
+* Enhancements to reproducible build (PR 7267)
+* Update Arduino example TLS Client/Server and improve support for ESP32 (PR 7304 & 7177)
+* XC32 compiler version 4.x compatibility (PR 7128)
+* Porting for build on PlayStation 3 and 4 (PR 7072)
+* Improvements for Espressif use; SHA HW/SW selection and use on ESP32-C2/ESP8684, wolfSSL_NewThread() type, component cmake fix, and update TLS client example for ESP8266 (PR 7081, 7173, 7077, 7148, 7240)
+* Allow crypto callbacks with SHA-1 HW (PR 7087)
+* Update OpenSSH port to version 9.6p1(PR 7203)
+* ARM Thumb2 enhancements, AES-GCM support for GCM_SMALL, alignment fix on key, fix for ASM clobber list (PR 7291,7301,7221)
+* Expand heap hint support for static memory build with more x509 functions (PR 7136)
+* Improving ARMv8 ChaCha20 ASM (alignment) (PR 7182)
+* Unknown extension callback wolfSSL_CertManagerSetUnknownExtCallback added to CertManager (PR 7194)
+* Implement wc_rng_new_ex for use with devID’s with crypto callback (PR 7271)
+* Allow reading 0-RTT data after writing 0.5-RTT data (PR 7102)
+* Send alert on bad PSK binder error (PR 7235)
+* Enhancements to CMake build files for use with cross compiling (PR 7188)
+
+
+## Fixes
+
+* Fix for checking result of MAC verify when no AAD is used with AES-GCM and Xilinx Xilsecure (PR 7051)
+* Fix for Aria sign use (PR 7082)
+* Fix for invalid `dh_ffdhe_test` test case using Intel QuickAssist (PR 7085)
+* Fixes for TI AES and SHA on TM4C with HW acceleration and add full AES GCM and CCM support with TLS (PR 7018)
+* Fixes for STM32 PKA use with ECC (PR 7098)
+* Fixes for TLS 1.3 with crypto callbacks to offload KDF / HMAC operation (PR 7070)
+* Fix include path for FSP 3.5 on Renesas RA6M4 (PR 7101)
+* Siphash x64 asm fix for use with older compilers (PR 7299)
+* Fix for SGX build with SP (PR 7308)
+* Fix to Make it mandatory that the cookie is sent back in new ClientHello when seen in a HelloRetryRequest with (PR 7190)
+* Fix for wrap around behavior with BIO pairs (PR 7169)
+* OCSP fixes for parsing of response correctly when there was a revocation reason and returning correct error value with date checks (PR 7241 & 7255)
+* Fix build with `NO_STDIO_FILESYSTEM` and improve checks for `XGETENV` (PR 7150)
+* Fix for DTLS sequence number and cookie when downgrading DTLS version (PR 7214)
+* Fix for write_dup use with chacha-poly cipher suites (PR 7206)
+* Fix for multiple handshake messages in one record failing with OUT_OF_ORDER_E when downgrading from TLS 1.3 to TLS 1.2 (PR 7141)
+* Fix for AES ECB build with Thumb and alignment (PR 7094)
+* Fix for negotiate handshake until the end in wolfSSL_read/wolfSSL_write if hitting an edge case with want read/write (PR 7237)
+
# wolfSSL Release 5.6.6 (Dec 19, 2023)
Release 5.6.6 has been developed according to wolfSSL's development and QA
@@ -22,7 +1024,7 @@ fixed this omission in several PRs for this release.
* [Low] CVE-2023-6936: A potential heap overflow read is possible in servers connecting over TLS 1.3 when the optional `WOLFSSL_CALLBACKS` has been defined. The out of bounds read can occur when a server receives a malicious malformed ClientHello. Users should either discontinue use of `WOLFSSL_CALLBACKS` on the server side or update versions of wolfSSL to 5.6.6. Thanks to the tlspuffin fuzzer team for the report which was designed and developed by; Lucca Hirschi (Inria, LORIA), Steve Kremer (Inria, LORIA), and Max Ammann (Trail of Bits). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/6949.
-* [Low] A side channel vulnerability with AES T-Tables is possible in a very controlled environment where precision sub-cache-line inspection can happen, such as inside an Intel SGX enclave. This can lead to recovery of the AES key. To prevent this type of attack, wolfSSL added an AES bitsliced implementation which can be enabled with the “`--enable-aes-bitsliced`” configure option. Thanks to Florian Sieck, Zhiyuan Zhang, Sebastian Berndt, Chitchanok Chuengsatiansup, Thomas Eisenbarth, and Yuval Yarom for the report (Universities of Lübeck, Melbourne, Adelaide and Bochum). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/6854.
+* [Low] CVE-2024-1543: A side channel vulnerability with AES T-Tables is possible in a very controlled environment where precision sub-cache-line inspection can happen, such as inside an Intel SGX enclave. This can lead to recovery of the AES key. To prevent this type of attack, wolfSSL added an AES bitsliced implementation which can be enabled with the “`--enable-aes-bitsliced`” configure option. Thanks to Florian Sieck, Zhiyuan Zhang, Sebastian Berndt, Chitchanok Chuengsatiansup, Thomas Eisenbarth, and Yuval Yarom for the report (Universities of Lübeck, Melbourne, Adelaide and Bochum). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/6854.
* [Low] CVE-2023-6937: wolfSSL prior to 5.6.6 did not check that messages in a single (D)TLS record do not span key boundaries. As a result, it was possible to combine (D)TLS messages using different keys into one (D)TLS record. The most extreme edge case is that, in (D)TLS 1.3, it was possible that an unencrypted (D)TLS 1.3 record from the server containing first a ServerHello message and then the rest of the first server flight would be accepted by a wolfSSL client. In (D)TLS 1.3 the handshake is encrypted after the ServerHello but a wolfSSL client would accept an unencrypted flight from the server. This does not compromise key negotiation and authentication so it is assigned a low severity rating. Thanks to Johannes Wilson for the report (Sectra Communications and Linköping University). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/7029.
@@ -676,9 +1678,9 @@ Release 5.5.1 of wolfSSL embedded TLS has bug fixes and new features including:
## Enhancements
* DTLSv1.3: Do HRR Cookie exchange by default
-* Add wolfSSL_EVP_PKEY_new_CMAC_key to OpenSSL compatible API
-* Update ide win10 build files to add missing sp source files
-* Improve Workbench docs
+* Add wolfSSL_EVP_PKEY_new_CMAC_key to OpenSSL compatible API
+* Update ide win10 build files to add missing sp source files
+* Improve Workbench docs
* Improve EVP support for CHACHA20_POLY1305
* Improve `wc_SetCustomExtension` documentation
* RSA-PSS with OCSP and add simple OCSP response DER verify test case
@@ -686,23 +1688,23 @@ Release 5.5.1 of wolfSSL embedded TLS has bug fixes and new features including:
* Don't over-allocate memory for DTLS fragments
* Add WOLFSSL_ATECC_TFLXTLS for Atmel port
* SHA-3 performance improvements with x86_64 assembly
-* Add code to fallback to S/W if TSIP cannot handle
+* Add code to fallback to S/W if TSIP cannot handle
* Improves entropy with VxWorks
* Make time in milliseconds 64-bits for longer session ticket lives
* Support for setting cipher list with bytes
* wolfSSL_set1_curves_list(), wolfSSL_CTX_set1_curves_list() improvements
* Add to RSAES-OAEP key parsing for pkcs7
* Add missing DN nid to work with PrintName()
-* SP int: default to 16 bit word size when NO_64BIT defined
+* SP int: default to 16 bit word size when NO_64BIT defined
* Limit the amount of fragments we store per a DTLS connection and error out when max limit is reached
* Detect when certificate's RSA public key size is too big and fail on loading of certificate
## Fixes
* Fix for async with OCSP non-blocking in `ProcessPeerCerts`
* Fixes for building with 32-bit and socket size sign/unsigned mismatch
-* Fix Windows CMakeList compiler options
-* TLS 1.3 Middle-Box compat: fix missing brace
-* Configuration consistency fixes for RSA keys and way to force disable of private keys
+* Fix Windows CMakeList compiler options
+* TLS 1.3 Middle-Box compat: fix missing brace
+* Configuration consistency fixes for RSA keys and way to force disable of private keys
* Fix for Aarch64 Mac M1 SP use
* Fix build errors and warnings for MSVC with DTLS 1.3
* Fix HMAC compat layer function for SHA-1
@@ -710,9 +1712,9 @@ Release 5.5.1 of wolfSSL embedded TLS has bug fixes and new features including:
* Check return from call to wc_Time
* SP math: fix build configuration with opensslall
* Fix for async session tickets
-* SP int mp_init_size fixes when SP_WORD_SIZE == 8
+* SP int mp_init_size fixes when SP_WORD_SIZE == 8
* Ed. function to make public key now checks for if the private key flag is set
-* Fix HashRaw WC_SHA256_DIGEST_SIZE for wc_Sha256GetHash
+* Fix HashRaw WC_SHA256_DIGEST_SIZE for wc_Sha256GetHash
* Fix for building with PSK only
* Set correct types in wolfSSL_sk_*_new functions
* Sanity check that size passed to mp_init_size() is no more than SP_INT_DIGITS
@@ -826,7 +1828,7 @@ CVE-2020-12966 https://www.amd.com/en/corporate/product-security/bulletin/amd-sb
* Update SP math all to not use sp_int_word when SQR_MUL_ASM is available
### SP Math Fixes
* Fixes for constant time with div function
-* Fix casting warnings for Windows builds and assembly changes to support XMM6-15 being non-volatile
+* Fix casting warnings for Windows builds and assembly changes to support XMM6-15 being non-volatile
* Fix for div_word when not using div function
* Fixes for user settings with SP ASM and ED/Curve25519 small
* Additional Wycheproof tests ran and fixes
@@ -1006,7 +2008,7 @@ Release 5.3.0 of wolfSSL embedded TLS has bug fixes and new features including:
### Math Library Fixes
* Sanity check with SP math that ECC points ordinates are not greater than modulus length
* Additional sanity checks that _sp_add_d does not error due to overflow
-* Wycheproof fixes, testing integration, and fixes for AVX / AArch64 ASM edge case tests
+* Wycheproof fixes, testing integration, and fixes for AVX / AArch64 ASM edge case tests
* TFM fp_div_2_ct rework to avoid potential overflow
### Misc.
@@ -1247,7 +2249,7 @@ Release 5.1.0 of wolfSSL embedded TLS has bug fixes and new features including:
###### PORT Fixes
* Building with Android wpa_supplicant and KeyStore
* Setting initial value of CA certificate with TSIP enabled
-* Cryptocell ECC build fix and fix with RSA disabled
+* Cryptocell ECC build fix and fix with RSA disabled
* IoT-SAFE improvement for Key/File slot ID size, fix for C++ compile, and fixes for retrieving the public key after key generation
###### Math Library Fixes
@@ -1386,7 +2388,7 @@ Release 5.0.0 of wolfSSL embedded TLS has bug fixes and new features including:
- SSL_SESSION_has_ticket()
- SSL_SESSION_get_ticket_lifetime_hint()
- DIST_POINT_new
- - DIST_POINT_free
+ - DIST_POINT_free
- DIST_POINTS_free
- CRL_DIST_POINTS_free
- sk_DIST_POINT_push
@@ -1549,7 +2551,7 @@ Release 4.8.0 of wolfSSL embedded TLS has bug fixes and new features including:
### Vulnerabilities
* [Low] CVE-2021-37155: OCSP request/response verification issue. In the case that the serial number in the OCSP request differs from the serial number in the OCSP response the error from the comparison was not resulting in a failed verification. We recommend users that have wolfSSL version 4.6.0 and 4.7.0 with OCSP enabled update their version of wolfSSL. Version 4.5.0 and earlier are not affected by this report. Thanks to Rainer Mueller-Amersdorffer, Roee Yankelevsky, Barak Gutman, Hila Cohen and Shoshi Berko (from CYMOTIVE Technologies and CARIAD) for the report.
-* [Low] CVE-2021-24116: Side-Channel cache look up vulnerability in base64 PEM decoding for versions of wolfSSL 4.5.0 and earlier. Versions 4.6.0 and up contain a fix and do not need to be updated for this report. If decoding a PEM format private key using version 4.5.0 and older of wolfSSL then we recommend updating the version of wolfSSL used. Thanks to Florian Sieck, Jan Wichelmann, Sebastian Berndt and Thomas Eisenbarth for the report.
+* [Low] CVE-2021-24116: Side-Channel cache look up vulnerability in base64 PEM decoding for versions of wolfSSL 4.5.0 and earlier. Versions 4.6.0 and up contain a fix and do not need to be updated for this report. If decoding a PEM format private key using version 4.5.0 and older of wolfSSL then we recommend updating the version of wolfSSL used. Thanks to Florian Sieck, Jan Wichelmann, Sebastian Berndt and Thomas Eisenbarth for the report.
### New Feature Additions
###### New Product
diff --git a/LICENSING b/LICENSING
index 24407d1..14b0801 100644
--- a/LICENSING
+++ b/LICENSING
@@ -1,9 +1,24 @@
+The wolfSSL, Inc. software (“wolfSSL Software”) to which this text is appended
+is made available under the GNU General Public License version 3 (“GPLv3”) with
+the following exception: When this wolfSSL Software is combined with the
+software listed below (“Exception Software”), licensee may elect to license
+this wolfSSL Software under the GNU General Public License version 2 (“GPLv2”)
+instead of GPLv3.
-wolfSSL (formerly known as CyaSSL) and wolfCrypt are either licensed for use
-under the GPLv2 (or at your option any later version) or a standard commercial
-license. For our users who cannot use wolfSSL under GPLv2
-(or any later version), a commercial license to wolfSSL and wolfCrypt is
-available.
+Exception Software:
+
+MariaDB Server
+
+MariaDB Client Libraries
+
+OpenVPN-NL
+
+Fetchmail
+
+OpenVPN
+
+For our users who cannot use wolfSSL under GPLv3, a commercial license to
+wolfSSL and wolfCrypt is available.
Please contact wolfSSL Inc. directly at:
diff --git a/README b/README
index c344bf8..6a0e29a 100644
--- a/README
+++ b/README
@@ -29,24 +29,29 @@ of the wolfSSL manual. (https://www.wolfssl.com/docs/wolfssl-manual/ch4/)
*** Notes, Please read ***
Note 1)
-wolfSSL as of 3.6.6 no longer enables SSLv3 by default. wolfSSL also no longer
-supports static key cipher suites with PSK, RSA, or ECDH. This means if you
-plan to use TLS cipher suites you must enable DH (DH is on by default), or
-enable ECC (ECC is on by default), or you must enable static key cipher suites
-with
-
- WOLFSSL_STATIC_DH
- WOLFSSL_STATIC_RSA
- or
- WOLFSSL_STATIC_PSK
-
-though static key cipher suites are deprecated and will be removed from future
-versions of TLS. They also lower your security by removing PFS.
-
-When compiling ssl.c, wolfSSL will now issue a compiler error if no cipher
+wolfSSL as of 3.6.6 no longer enables SSLv3 by default. By default, wolfSSL
+disables static key cipher suites that use PSK, RSA, or ECDH without ephemeral
+key exchange. Instead, wolfSSL enables cipher suites that provide perfect
+forward secrecy (PFS) using ephemeral Diffie-Hellman (DH) or Elliptic Curve
+(ECC) key exchange, both of which are enabled by default.
+
+If you need to support legacy systems that require static key cipher suites,
+you can enable them using one or more of these defines:
+
+WOLFSSL_STATIC_DH
+WOLFSSL_STATIC_RSA
+WOLFSSL_STATIC_PSK
+
+Important: Static key cipher suites reduce security by eliminating perfect
+forward secrecy. These cipher suites reuse the same long-term private key for
+all session key exchanges. In contrast, PFS-enabled cipher suites (the wolfSSL
+default) generate a new ephemeral key for each session, ensuring that
+compromising a long-term key cannot decrypt past sessions.
+
+When compiling `ssl.c`, wolfSSL will now issue a compiler error if no cipher
suites are available. You can remove this error by defining
-WOLFSSL_ALLOW_NO_SUITES in the event that you desire that, i.e., you're not
-using TLS cipher suites.
+`WOLFSSL_ALLOW_NO_SUITES` in the event that you desire that, i.e., you're
+not using TLS cipher suites.
Note 2)
wolfSSL takes a different approach to certificate verification than OpenSSL
@@ -70,93 +75,77 @@ should be used for the enum name.
*** end Notes ***
-# wolfSSL Release 5.6.6 (Dec 19, 2023)
+# wolfSSL Release 5.8.4 (Nov. 20, 2025)
-Release 5.6.6 has been developed according to wolfSSL's development and QA
+Release 5.8.4 has been developed according to wolfSSL's development and QA
process (see link below) and successfully passed the quality criteria.
https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance
-NOTE: * --enable-heapmath is being deprecated and will be removed by 2024
+NOTE: * --enable-heapmath is deprecated
+ * MD5 is now disabled by default
-REMINDER: When working with AES Block Cipher algorithms, wc_AesInit() should
-always be called first to initialize the `Aes` structure, before calling other
-Aes API functions. Recently we found several places in our documentation,
-comments, and codebase where this pattern was not observed. We have since
-fixed this omission in several PRs for this release.
+PR stands for Pull Request, and PR references a GitHub pull request number where the code change was added.
## Vulnerabilities
-
-* [Medium] CVE-2023-6935: After review of the previous RSA timing fix in wolfSSL 5.6.4, additional changes were found to be required. A complete resistant change is delivered in this release. This fix is for the Marvin attack, leading to being able to decrypt a saved TLS connection and potentially forge a signature after probing with a very large number of trial connections. This issue is around RSA decryption and affects the optional static RSA cipher suites on the server side, which are considered weak, not recommended to be used and are off by default in wolfSSL (even with --enable-all). Static RSA cipher suites were also removed from the TLS 1.3 protocol and are only present in TLS 1.2 and lower. All padding versions of RSA decrypt are affected since the code under review is outside of the padding processing. Information about the private keys is NOT compromised in affected code. It is recommended to disable static RSA cipher suites and update the version of wolfSSL used if using RSA private decryption alone outside of TLS. Thanks to Hubert Kario for the report. The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/6955.
-
-* [Low] CVE-2023-6936: A potential heap overflow read is possible in servers connecting over TLS 1.3 when the optional WOLFSSL_CALLBACKS has been defined. The out of bounds read can occur when a server receives a malicious malformed ClientHello. Users should either discontinue use of WOLFSSL_CALLBACKS on the server side or update versions of wolfSSL to 5.6.6. Thanks to the tlspuffin fuzzer team for the report which was designed and developed by; Lucca Hirschi (Inria, LORIA), Steve Kremer (Inria, LORIA), and Max Ammann (Trail of Bits). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/6949.
-
-* [Low] A side channel vulnerability with AES T-Tables is possible in a very controlled environment where precision sub-cache-line inspection can happen, such as inside an Intel SGX enclave. This can lead to recovery of the AES key. To prevent this type of attack, wolfSSL added an AES bitsliced implementation which can be enabled with the “--enable-aes-bitsliced” configure option. Thanks to Florian Sieck, Zhiyuan Zhang, Sebastian Berndt, Chitchanok Chuengsatiansup, Thomas Eisenbarth, and Yuval Yarom for the report (Universities of Lübeck, Melbourne, Adelaide and Bochum). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/6854.
-
-* [Low] CVE-2023-6937: wolfSSL prior to 5.6.6 did not check that messages in a single (D)TLS record do not span key boundaries. As a result, it was possible to combine (D)TLS messages using different keys into one (D)TLS record. The most extreme edge case is that, in (D)TLS 1.3, it was possible that an unencrypted (D)TLS 1.3 record from the server containing first a ServerHello message and then the rest of the first server flight would be accepted by a wolfSSL client. In (D)TLS 1.3 the handshake is encrypted after the ServerHello but a wolfSSL client would accept an unencrypted flight from the server. This does not compromise key negotiation and authentication so it is assigned a low severity rating. Thanks to Johannes Wilson for the report (Sectra Communications and Linköping University). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/7029.
-
-## New Feature Additions
-
-* Build option for disabling CRL date checks (WOLFSSL_NO_CRL_DATE_CHECK) (PR 6927)
-* Support for STM32WL55 and improvements to PKA ECC support (PR 6937)
-* Add option to skip cookie exchange on DTLS 1.3 session resumption (PR 6929)
-* Add implementation of SRTP KDF and SRTCP KDF (--enable-srtp-kdf) (PR 6888)
-* Add wolfSSL_EXTENDED_KEY_USAGE_free() (PR 6916)
-* Add AES bitsliced implementation that is cache attack safe (--enable-aes-bitsliced) (PR 6854)
-* Add memcached support and automated testing (PR 6430, 7022)
-* Add Hardware Encryption Acceleration for ESP32-C3, ESP32-C6, and ESP32-S2 (PR 6990)
-* Add (D)TLS 1.3 support for 0.5-RTT data (PR 7010)
-
-## Enhancements and Optimizations
-
-* Better built in testing of “--sys-ca-certs” configure option (PR 6910)
-* Updated CMakeLists.txt for Espressif wolfSSL component usage (PR 6877)
-* Disable TLS 1.1 by default (unless SSL 3.0 or TLS 1.0 is enabled) (PR 6946)
-* Add “--enable-quic” to “--enable-all” configure option (PR 6957)
-* Add support to SP C implementation for RSA exponent up to 64-bits (PR 6959)
-* Add result of “HAVE___UINT128_T” to options.h for CMake builds (PR 6965)
-* Add optimized assembly for AES-GCM on ARM64 using hardware crypto instructions (PR 6967)
-* Add built-in cipher suite tests for DTLS 1.3 PQC (PR 6952)
-* Add wolfCrypt test and unit test to ctest (PR 6977)
-* Move OpenSSL compatibility crypto APIs into ssl_crypto.c file (PR 6935)
-* Validate time generated from XGMTIME() (PR 6958)
-* Allow wolfCrypt benchmark to run with microsecond accuracy (PR 6868)
-* Add GitHub Actions testing with nginx 1.24.0 (PR 6982)
-* Allow encoding of CA:FALSE BasicConstraint during cert generation (PR 6953)
-* Add CMake option to enable DTLS-SRTP (PR 6991)
-* Add CMake options for enabling QUIC and cURL (PR 7049)
-* Improve RSA blinding to make code more constant time (PR 6955)
-* Refactor AES-NI implementation macros to allow dynamic fallback to C (PR 6981)
-* Default to native Windows threading API on MinGW (PR 7015)
-* Return better error codes from OCSP response check (PR 7028)
-* Updated Espressif ESP32 TLS client and server examples (PR 6844)
-* Add/clean up support for ESP-IDF v5.1 for a variety of ESP32 chips (PR 7035, 7037)
-* Add API to choose dynamic certs based on client ciphers/sigalgs (PR 6963)
-* Improve Arduino IDE 1.5 project file to match recursive style (PR 7007)
-* Simplify and improve apple-universal build script (PR 7025)
-
-## Fixes
-
-* Fix for async edge case with Intel QuickAssist/Cavium Nitrox (PR 6931)
-* Fix for building PKCS#7 with RSA disabled (PR 6902)
-* Fix for advancing output pointer in wolfSSL_i2d_X509() (PR 6891)
-* Fix for EVP_EncodeBlock() appending a newline (PR 6900)
-* Fix for wolfSSL_RSA_verify_PKCS1_PSS() with RSA_PSS_SALTLEN_AUTO (PR 6938)
-* Fixes for CODESonar reports around isalpha() and isalnum() calls (PR 6810)
-* Fix for SP ARM64 integer math to avoid compiler optimization issues (PR 6942)
-* Fix for SP Thumb2 inline assembly to add IAR build support (PR 6943, 6971)
-* Fix for SP Thumb2 to make functions not inlined (PR 6993)
-* Fix for SP Cortex-M assembly large build with IAR (PR 6954)
-* Fix for SP ARM64 assembly montgomery reduction by 4 (PR 6947)
-* Fix for SP ARM64 P-256 for not inlining functions for iOS compatibility (PR 6979)
-* Fix for WOLFSSL_CALLBACKS and potential memory error (PR 6949)
-* Fixes for wolfSSL’s Zephyr OS port (PR 6930)
-* Fix for build errors when building for NXP mmCAU (FREESCALE_MMCAU) (PR 6970)
-* Fix for TLS 1.3 SendBuffered() return code in non-blocking mode (PR 7001)
-* Fix for TLS Hmac_UpdateFinal() when padding byte is invalid (PR 6998)
-* Fix for ARMv8 AES-GCM streaming to check size of IV before storing (PR 6996)
-* Add missing calls to wc_AesInit() before wc_AesSetKey() (PR 7011)
-* Fix build errors with DTLS 1.3 enabled but TLS 1.2 disabled (PR 6976)
-* Fixes for building wolfSSL in Visual Studio (PR 7040)
+* [Low CVE-2025-12888] Vulnerability in X25519 constant-time cryptographic implementations due to timing side channels introduced by compiler optimizations and CPU architecture limitations, specifically with the Xtensa-based ESP32 chips. If targeting Xtensa it is recommended to use the low memory implementations of X25519, which is now turned on as the default for Xtensa. Thanks to Adrian Cinal for the report. Fixed in PR 9275.
+
+
+* [Med. CVE-2025-11936] Potential DoS vulnerability due to a memory leak through multiple KeyShareEntry with the same group in malicious TLS 1.3 ClientHello messages. This affects users who are running wolfSSL on the server side with TLS 1.3. Thanks to Jaehun Lee and Kyungmin Bae, Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9117.
+
+* [Low CVE-2025-11935] PSK with PFS (Perfect Forward Secrecy) downgrades to PSK without PFS during TLS 1.3 handshake. If the client sends a ClientHello that has a key share extension and the server responds with a ServerHello that does not have a key share extension the connection would previously continue on without using PFS. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9112.
+
+* [Low CVE-2025-11934] Signature Algorithm downgrade from ECDSA P521 to P256 during TLS 1.3 handshake. When a client sends ECDSA P521 as the supported signature algorithm the server previously could respond as ECDSA P256 being the accepted signature algorithm and the connection would continue with using ECDSA P256. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9113.
+
+
+* [Low CVE-2025-11933] DoS Vulnerability in wolfSSL TLS 1.3 CKS extension parsing. Previously duplicate CKS extensions were not rejected leading to a potential memory leak when processing a ClientHello. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9132.
+
+
+* [Low CVE-2025-11931] Integer Underflow Leads to Out-of-Bounds Access in XChaCha20-Poly1305 Decrypt. This issue is hit specifically with a call to the function wc_XChaCha20Poly1305_Decrypt() which is not used with TLS connections, only from direct calls from an application. Thanks to Luigino Camastra from Aisle Research for the report. Fixed in PR 9223.
+
+* [Low CVE-2025-11932] Timing Side-Channel in PSK Binder Verification. The server previously verified the TLS 1.3 PSK binder using a non-constant time method which could potentially leak information about the PSK binder. Thanks to Luigino Camastra from Aisle Research for the report. Fixed in PR 9223.
+
+* [Low CVE-2025-12889] With TLS 1.2 connections a client can use any digest, specifically a weaker digest, rather than those in the CertificateRequest. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9395
+
+## New Features
+* New ML-KEM / ML-DSA APIs and seed/import PKCS8 support; added _new/_delete APIs for ML-KEM/ML-DSA. (PR 9039, 9000, 9049)
+* Initial wolfCrypt FreeBSD kernel module support (PR 9392)
+* Expanded PKCS7/CMS capabilities: decode SymmetricKeyPackage / OneSymmetricKey, add wc_PKCS7_GetEnvelopedDataKariRid, and allow PKCS7 builds with AES keywrap unset. (PR 9018, 9029, 9032)
+* Add custom AES key wrap/unwrap callbacks and crypto callback copy/free operations. (PR 9002, 9309)
+* Add support for certificate_authorities extension in ClientHello and certificate manager CA-type selection/unloading. (PR 9209, 9046)
+* Large expansion of Rust wrapper modules: random, aes, rsa, ecc, dh, sha, hmac, cmac, ed25519/ed448, pbkdf2/PKCS#12, kdf/prf, SRTP KDFs, and conditional compilation options. (PR 9191, 9212, 9273, 9306, 9320, 9328, 9368, 9389, 9357, 9433)
+* Rust: support optional heap and dev_id parameters and enable conditional compilation based on C build options. (PR 9407, 9433)
+* STM32 fixes (benchmarking and platform fixes) and PSoC6 hardware acceleration additions. (PR 9228, 9256, 9185)
+* STM32U5 added support for SAES and DHUK. (PR 9087)
+* Add --enable-curl=tiny option for a smaller build when used with cURL. (PR 9174)
+
+## Improvements / Optimizations
+* Regression test fixes and expansion: TLS 1.3/1.2 tests, ARDUINO examples, libssh2 tests, hostap workflows, and nightly test improvements. (PR 9096, 9141, 9091, 9122, 9388)
+* Improved test ordering and CI test stability (random tests run order changes, FIPS test fixes). (PR 9204, 9257)
+* Docs and readme fixes, docstring updates, AsconAEAD comment placement, and example certificate renewals. (PR 9131, 9293, 9262, 9429)
+* Updated GPL exception lists (GPLv2 and GPLv3 exception updates: add Fetchmail and OpenVPN). (PR 9398, 9413)
+* Introduced WOLFSSL_DEBUG_CERTS and additional debug/logging refinements. (PR 8902, 9055)
+* Expanded crypto-callback support (SHA family, HKDF, SHA-224, sha512_family digest selection) and improved crypto-only build cases. (PR 9070, 9252, 9271, 9100, 9194)
+* AES & HW offload improvements including AES-CTR support in PKCS11 driver and AES ECB offload sizing fix. (PR 9277, 9364)
+* ESP32: PSRAM allocator support and SHA HW fixes for ESP-IDF v6/v5. (PR 8987, 9225, 9264)
+* Renesas FSP / RA examples updated and security-module TLS context improvements. (PR 9047, 9010, 9158, 9150)
+* Broad configure/CMake/Autotools workflow improvements (Apple options tracking, Watcom pinning, Debian packaging, ESP-IDF pinning). (PR 9037, 9167, 9161, 9264)
+* New assembly introspection / performance helpers for RISC-V and PPC32; benchmarking enhancements (cycle counts). (PR 9101, 9317)
+* Update to SGX build for using assembly optimizations. (PR 8463, 9138)
+* Testing with Fil-C compiler version to 0.674 (PR 9396)
+* Refactors and compressing of small stack code (PR 9153)
+
+## Bug Fixes
+* Removed the test feature using popen when defining the macro WOLFSSL_USE_POPEN_HOST and not having HAVE_GETADDRINFO defined, along with having the macro HAVE_HTTP_CLIENT set. There was the potential for vulnerable behavior with the use of popen when the API wolfSSL_BIO_new_connect() was called with this specific build. This exact build configuration is only intended for testing with QEMU and is not enabled with any autoconf/cmake flags. Thanks to linraymond2006 for the report. (PR 9038)
+* Fix for C# wrapper Ed25519 potential crash and heap overwrite with raw public key import when using the API Ed25519ImportPublic.This was a broken API with the C# wrapper that would crash on use. Thanks to Luigino Camastra from Aisle Research for the bug report. (PR 9291)
+* Coverity, cppcheck, MISRA, clang-tidy, ZeroPath and other static-analysis driven fixes across the codebase. (PR 9006, 9078, 9068, 9265, 9324)
+* TLS 1.2/DTLS improvements: client message order checks, DTLS cookie/exchange and replay protections, better DTLS early-data handling. (PR 9387, 9253, 9205, 9367)
+* Improved X.509 & cert handling: allow larger pathLen in Basic Constraints, restore inner server name for ECH, retrying cert candidate chains. (PR 8890, 9234, 8692)
+* Sniffer robustness: fix infinite recursion, better handling of OOO appData and partial overlaps, and improved retransmission detection. (PR 9051, 9106, 9140, 9094)
+* Numerous linuxkm (kernel-mode) fixes, relocation/PIE normalization, and FIPS-related build tweaks across many iterations. (PR 9025, 9035, 9067, 9111, 9121)
+* ML-KEM/Kyber and ML-DSA fixes for out-of-bounds and seed-import correctness; multiple ML-related safety fixes. (PR 9142, 9105, 9439)
+* Avoid uninitialized-variable and GCC warnings; several fixes for undefined-shift/overflow issues. (PR 9020, 9372, 9195)
+* Memory & leak fixes in X509 verification and various struct sizing fixes for WOLFSSL_NO_MALLOC usage. (PR 9258, 9036)
+* Fixed RSA / signing / verify-only warnings allowing WOLFSSL_NO_CT_OPS when WOLFSSL_RSA_VERIFY_ONLY is used and API cleanups for using const. (PR 9031, 9263)
For additional vulnerability information visit the vulnerability page at:
https://www.wolfssl.com/docs/security-vulnerabilities/
diff --git a/README.md b/README.md
index 358b387..905411a 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,52 @@
# Arduino wolfSSL Library
-This library is restructured from [wolfSSL](https://github.com/wolfSSL/wolfssl/) Release 5.6.6 for the Arduino platform.
+This library is restructured from [wolfSSL](https://github.com/wolfSSL/wolfssl/) Release 5.8.4 for the Arduino platform.
The Official wolfSSL Arduino Library is found in [The Library Manager index](http://downloads.arduino.cc/libraries/library_index.json).
-See the [Arduino-wolfSSL logs](https://downloads.arduino.cc/libraries/logs/github.com/wolfSSL/Arduino-wolfSSL/).
+See the [Arduino-wolfSSL logs](https://downloads.arduino.cc/libraries/logs/github.com/wolfSSL/Arduino-wolfSSL/) for publishing status.
+
+Instructions for installing and using libraries can be found in the [Arduino docs](https://docs.arduino.cc/software/ide-v1/tutorials/installing-libraries/).
+
+## wolfSSL Configuration
+
+As described in the [Getting Started with wolfSSL on Arduino](https://www.wolfssl.com/getting-started-with-wolfssl-on-arduino/), wolfSSL features are enabled and disabled in the `user_settings.h` file.
+
+The `user_settings.h` file is found in the `/libraries/wolfssl/src` directory.
+
+For Windows this is typically `C:\Users\%USERNAME%\Documents\Arduino\libraries\wolfssl\src`
+
+For Mac: `~/Documents/Arduino/libraries/wolfssl/src`
+
+For Linux: `~/Arduino/libraries/wolfssl/src`
+
+Tips for success:
+
+- The `WOLFSSL_USER_SETTINGS` macro must be defined project-wide. (see [wolfssl.h](https://github.com/wolfSSL/wolfssl/blob/master/IDE/ARDUINO/wolfssl.h))
+- Apply any customizations only to `user_settings.h`; Do not edit wolfSSL `settings.h` or `configh.h` files.
+- Do not explicitly include `user_settings.h` in any source file.
+- For every source file that uses wolfssl, include `wolfssl/wolfcrypt/settings.h` before any other wolfSSL include, typically via `#include "wolfssl.h"`.
+- See the [wolfSSL docs](https://www.wolfssl.com/documentation/manuals/wolfssl/chapter02.html) for details on build configuration macros.
+
+## wolfSSL Examples
+
+Additional wolfSSL examples can be found at:
+
+- https://github.com/wolfSSL/wolfssl/tree/master/IDE/ARDUINO
+
+- https://github.com/wolfSSL/wolfssl/tree/master/examples
+
+- https://github.com/wolfSSL/wolfssl-examples/
## Arduino Releases
-The first Official wolfSSL Arduino Library is `5.6.6-Arduino.1`: a slightly modified, post [release 5.6.6](https://github.com/wolfSSL/wolfssl/releases/tag/v5.6.6-stable) version update.
+See GitHub for [all Arduino wolfSSL releases](https://github.com/wolfSSL/Arduino-wolfSSL/releases).
+
+The `./wolfssl-arduino.sh INSTALL` [script](https://github.com/wolfSSL/wolfssl/tree/master/IDE/ARDUINO) can be used to install specific GitHub versions as needed.
-See other [wolfSSL releases versions](https://github.com/wolfSSL/wolfssl/releases). The `./wolfssl-arduino.sh INSTALL` [script](https://github.com/wolfSSL/wolfssl/tree/master/IDE/ARDUINO) can be used to install specific GitHub versions as needed.
# wolfSSL Embedded SSL/TLS Library
-The [wolfSSL embedded SSL library](https://www.wolfssl.com/products/wolfssl/)
+The [wolfSSL embedded SSL library](https://www.wolfssl.com/products/wolfssl/)
(formerly CyaSSL) is a lightweight SSL/TLS library written in ANSI C and
targeted for embedded, RTOS, and resource-constrained environments - primarily
because of its small size, speed, and feature set. It is commonly used in
@@ -27,7 +60,7 @@ OpenSSL.
wolfSSL is powered by the wolfCrypt cryptography library. Two versions of
wolfCrypt have been FIPS 140-2 validated (Certificate #2425 and
-certificate #3389). FIPS 140-3 validation is in progress. For additional
+certificate #3389). FIPS 140-3 validated (Certificate #4718). For additional
information, visit the [wolfCrypt FIPS FAQ](https://www.wolfssl.com/license/fips/)
or contact fips@wolfssl.com.
@@ -46,19 +79,24 @@ of the wolfSSL manual.
## Notes, Please Read
### Note 1
-wolfSSL as of 3.6.6 no longer enables SSLv3 by default. wolfSSL also no longer
-supports static key cipher suites with PSK, RSA, or ECDH. This means if you
-plan to use TLS cipher suites you must enable DH (DH is on by default), or
-enable ECC (ECC is on by default), or you must enable static key cipher suites
-with one or more of the following defines:
+wolfSSL as of 3.6.6 no longer enables SSLv3 by default. By default, wolfSSL
+disables static key cipher suites that use PSK, RSA, or ECDH without ephemeral
+key exchange. Instead, wolfSSL enables cipher suites that provide perfect
+forward secrecy (PFS) using ephemeral Diffie-Hellman (DH) or Elliptic Curve
+(ECC) key exchange, both of which are enabled by default.
-```
-WOLFSSL_STATIC_DH
-WOLFSSL_STATIC_RSA
-WOLFSSL_STATIC_PSK
-```
-Though static key cipher suites are deprecated and will be removed from future
-versions of TLS. They also lower your security by removing PFS.
+If you need to support legacy systems that require static key cipher suites,
+you can enable them using one or more of these defines:
+
+* `WOLFSSL_STATIC_DH`
+* `WOLFSSL_STATIC_RSA`
+* `WOLFSSL_STATIC_PSK`
+
+**Important:** Static key cipher suites reduce security by eliminating perfect
+forward secrecy. These cipher suites reuse the same long-term private key for
+all session key exchanges. In contrast, PFS-enabled cipher suites (the wolfSSL
+default) generate a new ephemeral key for each session, ensuring that
+compromising a long-term key cannot decrypt past sessions.
When compiling `ssl.c`, wolfSSL will now issue a compiler error if no cipher
suites are available. You can remove this error by defining
@@ -88,93 +126,77 @@ single call hash function. Instead the name `WC_SHA`, `WC_SHA256`, `WC_SHA384` a
`WC_SHA512` should be used for the enum name.
-# wolfSSL Release 5.6.6 (Dec 19, 2023)
+# wolfSSL Release 5.8.4 (Nov. 20, 2025)
-Release 5.6.6 has been developed according to wolfSSL's development and QA
+Release 5.8.4 has been developed according to wolfSSL's development and QA
process (see link below) and successfully passed the quality criteria.
https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance
-NOTE: * --enable-heapmath is being deprecated and will be removed by 2024
+NOTE: * --enable-heapmath is deprecated
+ * MD5 is now disabled by default
-REMINDER: When working with AES Block Cipher algorithms, `wc_AesInit()` should
-always be called first to initialize the `Aes` structure, before calling other
-Aes API functions. Recently we found several places in our documentation,
-comments, and codebase where this pattern was not observed. We have since
-fixed this omission in several PRs for this release.
+PR stands for Pull Request, and PR references a GitHub pull request number where the code change was added.
## Vulnerabilities
-
-* [Medium] CVE-2023-6935: After review of the previous RSA timing fix in wolfSSL 5.6.4, additional changes were found to be required. A complete resistant change is delivered in this release. This fix is for the Marvin attack, leading to being able to decrypt a saved TLS connection and potentially forge a signature after probing with a very large number of trial connections. This issue is around RSA decryption and affects the optional static RSA cipher suites on the server side, which are considered weak, not recommended to be used and are off by default in wolfSSL (even with `--enable-all`). Static RSA cipher suites were also removed from the TLS 1.3 protocol and are only present in TLS 1.2 and lower. All padding versions of RSA decrypt are affected since the code under review is outside of the padding processing. Information about the private keys is NOT compromised in affected code. It is recommended to disable static RSA cipher suites and update the version of wolfSSL used if using RSA private decryption alone outside of TLS. Thanks to Hubert Kario for the report. The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/6955.
-
-* [Low] CVE-2023-6936: A potential heap overflow read is possible in servers connecting over TLS 1.3 when the optional `WOLFSSL_CALLBACKS` has been defined. The out of bounds read can occur when a server receives a malicious malformed ClientHello. Users should either discontinue use of `WOLFSSL_CALLBACKS` on the server side or update versions of wolfSSL to 5.6.6. Thanks to the tlspuffin fuzzer team for the report which was designed and developed by; Lucca Hirschi (Inria, LORIA), Steve Kremer (Inria, LORIA), and Max Ammann (Trail of Bits). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/6949.
-
-* [Low] A side channel vulnerability with AES T-Tables is possible in a very controlled environment where precision sub-cache-line inspection can happen, such as inside an Intel SGX enclave. This can lead to recovery of the AES key. To prevent this type of attack, wolfSSL added an AES bitsliced implementation which can be enabled with the “`--enable-aes-bitsliced`” configure option. Thanks to Florian Sieck, Zhiyuan Zhang, Sebastian Berndt, Chitchanok Chuengsatiansup, Thomas Eisenbarth, and Yuval Yarom for the report (Universities of Lübeck, Melbourne, Adelaide and Bochum). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/6854.
-
-* [Low] CVE-2023-6937: wolfSSL prior to 5.6.6 did not check that messages in a single (D)TLS record do not span key boundaries. As a result, it was possible to combine (D)TLS messages using different keys into one (D)TLS record. The most extreme edge case is that, in (D)TLS 1.3, it was possible that an unencrypted (D)TLS 1.3 record from the server containing first a ServerHello message and then the rest of the first server flight would be accepted by a wolfSSL client. In (D)TLS 1.3 the handshake is encrypted after the ServerHello but a wolfSSL client would accept an unencrypted flight from the server. This does not compromise key negotiation and authentication so it is assigned a low severity rating. Thanks to Johannes Wilson for the report (Sectra Communications and Linköping University). The fix for this issue is located in the following GitHub Pull Request: https://github.com/wolfSSL/wolfssl/pull/7029.
-
-## New Feature Additions
-
-* Build option for disabling CRL date checks (`WOLFSSL_NO_CRL_DATE_CHECK`) (PR 6927)
-* Support for STM32WL55 and improvements to PKA ECC support (PR 6937)
-* Add option to skip cookie exchange on DTLS 1.3 session resumption (PR 6929)
-* Add implementation of SRTP KDF and SRTCP KDF (`--enable-srtp-kdf`) (PR 6888)
-* Add `wolfSSL_EXTENDED_KEY_USAGE_free()` (PR 6916)
-* Add AES bitsliced implementation that is cache attack safe (`--enable-aes-bitsliced`) (PR 6854)
-* Add memcached support and automated testing (PR 6430, 7022)
-* Add Hardware Encryption Acceleration for ESP32-C3, ESP32-C6, and ESP32-S2 (PR 6990)
-* Add (D)TLS 1.3 support for 0.5-RTT data (PR 7010)
-
-## Enhancements and Optimizations
-
-* Better built in testing of “`--sys-ca-certs`” configure option (PR 6910)
-* Updated CMakeLists.txt for Espressif wolfSSL component usage (PR 6877)
-* Disable TLS 1.1 by default (unless SSL 3.0 or TLS 1.0 is enabled) (PR 6946)
-* Add “`--enable-quic`” to “`--enable-all`” configure option (PR 6957)
-* Add support to SP C implementation for RSA exponent up to 64-bits (PR 6959)
-* Add result of “`HAVE___UINT128_T`” to options.h for CMake builds (PR 6965)
-* Add optimized assembly for AES-GCM on ARM64 using hardware crypto instructions (PR 6967)
-* Add built-in cipher suite tests for DTLS 1.3 PQC (PR 6952)
-* Add wolfCrypt test and unit test to ctest (PR 6977)
-* Move OpenSSL compatibility crypto APIs into `ssl_crypto.c` file (PR 6935)
-* Validate time generated from XGMTIME() (PR 6958)
-* Allow wolfCrypt benchmark to run with microsecond accuracy (PR 6868)
-* Add GitHub Actions testing with nginx 1.24.0 (PR 6982)
-* Allow encoding of CA:FALSE BasicConstraint during cert generation (PR 6953)
-* Add CMake option to enable DTLS-SRTP (PR 6991)
-* Add CMake options for enabling QUIC and cURL (PR 7049)
-* Improve RSA blinding to make code more constant time (PR 6955)
-* Refactor AES-NI implementation macros to allow dynamic fallback to C (PR 6981)
-* Default to native Windows threading API on MinGW (PR 7015)
-* Return better error codes from OCSP response check (PR 7028)
-* Updated Espressif ESP32 TLS client and server examples (PR 6844)
-* Add/clean up support for ESP-IDF v5.1 for a variety of ESP32 chips (PR 7035, 7037)
-* Add API to choose dynamic certs based on client ciphers/sigalgs (PR 6963)
-* Improve Arduino IDE 1.5 project file to match recursive style (PR 7007)
-* Simplify and improve apple-universal build script (PR 7025)
-
-## Fixes
-
-* Fix for async edge case with Intel QuickAssist/Cavium Nitrox (PR 6931)
-* Fix for building PKCS#7 with RSA disabled (PR 6902)
-* Fix for advancing output pointer in `wolfSSL_i2d_X509()` (PR 6891)
-* Fix for `EVP_EncodeBlock()` appending a newline (PR 6900)
-* Fix for `wolfSSL_RSA_verify_PKCS1_PSS()` with `RSA_PSS_SALTLEN_AUTO` (PR 6938)
-* Fixes for CODESonar reports around `isalpha()` and `isalnum()` calls (PR 6810)
-* Fix for SP ARM64 integer math to avoid compiler optimization issues (PR 6942)
-* Fix for SP Thumb2 inline assembly to add IAR build support (PR 6943, 6971)
-* Fix for SP Thumb2 to make functions not inlined (PR 6993)
-* Fix for SP Cortex-M assembly large build with IAR (PR 6954)
-* Fix for SP ARM64 assembly montgomery reduction by 4 (PR 6947)
-* Fix for SP ARM64 P-256 for not inlining functions for iOS compatibility (PR 6979)
-* Fix for `WOLFSSL_CALLBACKS` and potential memory error (PR 6949)
-* Fixes for wolfSSL’s Zephyr OS port (PR 6930)
-* Fix for build errors when building for NXP mmCAU (`FREESCALE_MMCAU`) (PR 6970)
-* Fix for TLS 1.3 `SendBuffered()` return code in non-blocking mode (PR 7001)
-* Fix for TLS `Hmac_UpdateFinal()` when padding byte is invalid (PR 6998)
-* Fix for ARMv8 AES-GCM streaming to check size of IV before storing (PR 6996)
-* Add missing calls to `wc_AesInit()` before `wc_AesSetKey()` (PR 7011)
-* Fix build errors with DTLS 1.3 enabled but TLS 1.2 disabled (PR 6976)
-* Fixes for building wolfSSL in Visual Studio (PR 7040)
+* [Low CVE-2025-12888] Vulnerability in X25519 constant-time cryptographic implementations due to timing side channels introduced by compiler optimizations and CPU architecture limitations, specifically with the Xtensa-based ESP32 chips. If targeting Xtensa it is recommended to use the low memory implementations of X25519, which is now turned on as the default for Xtensa. Thanks to Adrian Cinal for the report. Fixed in PR 9275.
+
+
+* [Med. CVE-2025-11936] Potential DoS vulnerability due to a memory leak through multiple KeyShareEntry with the same group in malicious TLS 1.3 ClientHello messages. This affects users who are running wolfSSL on the server side with TLS 1.3. Thanks to Jaehun Lee and Kyungmin Bae, Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9117.
+
+* [Low CVE-2025-11935] PSK with PFS (Perfect Forward Secrecy) downgrades to PSK without PFS during TLS 1.3 handshake. If the client sends a ClientHello that has a key share extension and the server responds with a ServerHello that does not have a key share extension the connection would previously continue on without using PFS. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9112.
+
+* [Low CVE-2025-11934] Signature Algorithm downgrade from ECDSA P521 to P256 during TLS 1.3 handshake. When a client sends ECDSA P521 as the supported signature algorithm the server previously could respond as ECDSA P256 being the accepted signature algorithm and the connection would continue with using ECDSA P256. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9113.
+
+
+* [Low CVE-2025-11933] DoS Vulnerability in wolfSSL TLS 1.3 CKS extension parsing. Previously duplicate CKS extensions were not rejected leading to a potential memory leak when processing a ClientHello. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9132.
+
+
+* [Low CVE-2025-11931] Integer Underflow Leads to Out-of-Bounds Access in XChaCha20-Poly1305 Decrypt. This issue is hit specifically with a call to the function wc_XChaCha20Poly1305_Decrypt() which is not used with TLS connections, only from direct calls from an application. Thanks to Luigino Camastra from Aisle Research for the report. Fixed in PR 9223.
+
+* [Low CVE-2025-11932] Timing Side-Channel in PSK Binder Verification. The server previously verified the TLS 1.3 PSK binder using a non-constant time method which could potentially leak information about the PSK binder. Thanks to Luigino Camastra from Aisle Research for the report. Fixed in PR 9223.
+
+* [Low CVE-2025-12889] With TLS 1.2 connections a client can use any digest, specifically a weaker digest, rather than those in the CertificateRequest. Thanks to Jaehun Lee from Pohang University of Science and Technology (POSTECH) for the report. Fixed in PR 9395
+
+## New Features
+* New ML-KEM / ML-DSA APIs and seed/import PKCS8 support; added _new/_delete APIs for ML-KEM/ML-DSA. (PR 9039, 9000, 9049)
+* Initial wolfCrypt FreeBSD kernel module support (PR 9392)
+* Expanded PKCS7/CMS capabilities: decode SymmetricKeyPackage / OneSymmetricKey, add wc_PKCS7_GetEnvelopedDataKariRid, and allow PKCS7 builds with AES keywrap unset. (PR 9018, 9029, 9032)
+* Add custom AES key wrap/unwrap callbacks and crypto callback copy/free operations. (PR 9002, 9309)
+* Add support for certificate_authorities extension in ClientHello and certificate manager CA-type selection/unloading. (PR 9209, 9046)
+* Large expansion of Rust wrapper modules: random, aes, rsa, ecc, dh, sha, hmac, cmac, ed25519/ed448, pbkdf2/PKCS#12, kdf/prf, SRTP KDFs, and conditional compilation options. (PR 9191, 9212, 9273, 9306, 9320, 9328, 9368, 9389, 9357, 9433)
+* Rust: support optional heap and dev_id parameters and enable conditional compilation based on C build options. (PR 9407, 9433)
+* STM32 fixes (benchmarking and platform fixes) and PSoC6 hardware acceleration additions. (PR 9228, 9256, 9185)
+* STM32U5 added support for SAES and DHUK. (PR 9087)
+* Add --enable-curl=tiny option for a smaller build when used with cURL. (PR 9174)
+
+## Improvements / Optimizations
+* Regression test fixes and expansion: TLS 1.3/1.2 tests, ARDUINO examples, libssh2 tests, hostap workflows, and nightly test improvements. (PR 9096, 9141, 9091, 9122, 9388)
+* Improved test ordering and CI test stability (random tests run order changes, FIPS test fixes). (PR 9204, 9257)
+* Docs and readme fixes, docstring updates, AsconAEAD comment placement, and example certificate renewals. (PR 9131, 9293, 9262, 9429)
+* Updated GPL exception lists (GPLv2 and GPLv3 exception updates: add Fetchmail and OpenVPN). (PR 9398, 9413)
+* Introduced WOLFSSL_DEBUG_CERTS and additional debug/logging refinements. (PR 8902, 9055)
+* Expanded crypto-callback support (SHA family, HKDF, SHA-224, sha512_family digest selection) and improved crypto-only build cases. (PR 9070, 9252, 9271, 9100, 9194)
+* AES & HW offload improvements including AES-CTR support in PKCS11 driver and AES ECB offload sizing fix. (PR 9277, 9364)
+* ESP32: PSRAM allocator support and SHA HW fixes for ESP-IDF v6/v5. (PR 8987, 9225, 9264)
+* Renesas FSP / RA examples updated and security-module TLS context improvements. (PR 9047, 9010, 9158, 9150)
+* Broad configure/CMake/Autotools workflow improvements (Apple options tracking, Watcom pinning, Debian packaging, ESP-IDF pinning). (PR 9037, 9167, 9161, 9264)
+* New assembly introspection / performance helpers for RISC-V and PPC32; benchmarking enhancements (cycle counts). (PR 9101, 9317)
+* Update to SGX build for using assembly optimizations. (PR 8463, 9138)
+* Testing with Fil-C compiler version to 0.674 (PR 9396)
+* Refactors and compressing of small stack code (PR 9153)
+
+## Bug Fixes
+* Removed the test feature using popen when defining the macro WOLFSSL_USE_POPEN_HOST and not having HAVE_GETADDRINFO defined, along with having the macro HAVE_HTTP_CLIENT set. There was the potential for vulnerable behavior with the use of popen when the API wolfSSL_BIO_new_connect() was called with this specific build. This exact build configuration is only intended for testing with QEMU and is not enabled with any autoconf/cmake flags. Thanks to linraymond2006 for the report. (PR 9038)
+* Fix for C# wrapper Ed25519 potential crash and heap overwrite with raw public key import when using the API Ed25519ImportPublic.This was a broken API with the C# wrapper that would crash on use. Thanks to Luigino Camastra from Aisle Research for the bug report. (PR 9291)
+* Coverity, cppcheck, MISRA, clang-tidy, ZeroPath and other static-analysis driven fixes across the codebase. (PR 9006, 9078, 9068, 9265, 9324)
+* TLS 1.2/DTLS improvements: client message order checks, DTLS cookie/exchange and replay protections, better DTLS early-data handling. (PR 9387, 9253, 9205, 9367)
+* Improved X.509 & cert handling: allow larger pathLen in Basic Constraints, restore inner server name for ECH, retrying cert candidate chains. (PR 8890, 9234, 8692)
+* Sniffer robustness: fix infinite recursion, better handling of OOO appData and partial overlaps, and improved retransmission detection. (PR 9051, 9106, 9140, 9094)
+* Numerous linuxkm (kernel-mode) fixes, relocation/PIE normalization, and FIPS-related build tweaks across many iterations. (PR 9025, 9035, 9067, 9111, 9121)
+* ML-KEM/Kyber and ML-DSA fixes for out-of-bounds and seed-import correctness; multiple ML-related safety fixes. (PR 9142, 9105, 9439)
+* Avoid uninitialized-variable and GCC warnings; several fixes for undefined-shift/overflow issues. (PR 9020, 9372, 9195)
+* Memory & leak fixes in X509 verification and various struct sizing fixes for WOLFSSL_NO_MALLOC usage. (PR 9258, 9036)
+* Fixed RSA / signing / verify-only warnings allowing WOLFSSL_NO_CT_OPS when WOLFSSL_RSA_VERIFY_ONLY is used and API cleanups for using const. (PR 9031, 9263)
For additional vulnerability information visit the vulnerability page at:
https://www.wolfssl.com/docs/security-vulnerabilities/
@@ -203,3 +225,51 @@ More info can be found on-line at: https://wolfssl.com/wolfSSL/Docs.html
[wolfSSL Vulnerabilities](https://www.wolfssl.com/docs/security-vulnerabilities/)
[Additional wolfSSL Examples](https://github.com/wolfssl/wolfssl-examples)
+
+# Directory structure
+
+```
+
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ certs [Certificates used in tests and examples]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ cmake [Cmake build utilities]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ debian [Debian packaging files]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ doc [Documentation for wolfSSL (Doxygen)]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ Docker [Prebuilt Docker environments]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ examples [wolfSSL examples]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ asn1 [ASN.1 printing example]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ async [Asynchronous Cryptography example]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ benchmark [TLS benchmark example]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ client [Client example]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ configs [Example build configurations]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ echoclient [Echoclient example]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ echoserver [Echoserver example]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ pem [Example for convert between PEM and DER]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ sctp [Servers and clients that demonstrate wolfSSL's DTLS-SCTP support]
+ââ€â€šÃ‚ Â ââ€â€Ã¢â€â‚¬Ã¢â€â‚¬ server [Server example]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ IDE [Contains example projects for various development environments]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ linuxkm [Linux Kernel Module implementation]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ m4 [Autotools utilities]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ mcapi [wolfSSL MPLAB X Project Files]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ mplabx [wolfSSL MPLAB X Project Files]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ mqx [wolfSSL Freescale CodeWarrior Project Files]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ rpm [RPM packaging metadata]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ RTOS
+ââ€â€šÃ‚ Â ââ€â€Ã¢â€â‚¬Ã¢â€â‚¬ nuttx [Port of wolfSSL for NuttX]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ scripts [Testing scripts]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ src [wolfSSL source code]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ sslSniffer [wolfSSL sniffer can be used to passively sniff SSL traffic]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ support [Contains the pkg-config file]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ tests [Unit and configuration testing]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ testsuite [Test application that orchestrates tests]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ tirtos [Port of wolfSSL for TI RTOS]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ wolfcrypt [The wolfCrypt component]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ benchmark [Cryptography benchmarking application]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ src [wolfCrypt source code]
+ââ€â€šÃ‚ Â ââ€â€šÃ‚ Â ââ€â€Ã¢â€â‚¬Ã¢â€â‚¬ port [Supported hardware acceleration ports]
+ââ€â€šÃ‚ Â ââ€â€Ã¢â€â‚¬Ã¢â€â‚¬ test [Cryptography testing application]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ wolfssl [Header files]
+ââ€â€šÃ‚ Â ââ€Å“ââ€â‚¬Ã¢â€â‚¬ openssl [Compatibility layer headers]
+ââ€â€šÃ‚ Â ââ€â€Ã¢â€â‚¬Ã¢â€â‚¬ wolfcrypt [Header files]
+ââ€Å“ââ€â‚¬Ã¢â€â‚¬ wrapper [wolfSSL language wrappers]
+ââ€â€Ã¢â€â‚¬Ã¢â€â‚¬ zephyr [Port of wolfSSL for Zephyr RTOS]
+```
diff --git a/examples/template/README.md b/examples/template/README.md
new file mode 100644
index 0000000..5ce0cbf
--- /dev/null
+++ b/examples/template/README.md
@@ -0,0 +1,34 @@
+# Template Example
+
+Open the [template.ino](./template.ino) file in the Arduino IDE.
+
+Other IDE products are also supported, such as:
+
+- [PlatformIO in VS Code](https://docs.platformio.org/en/latest/frameworks/arduino.html)
+- [VisualGDB](https://visualgdb.com/tutorials/arduino/)
+- [VisualMicro](https://www.visualmicro.com/)
+
+For examples on other platforms, see the [IDE directory](https://github.com/wolfssl/wolfssl/tree/master/IDE).
+Additional examples can be found on [wolfSSL/wolfssl-examples](https://github.com/wolfSSL/wolfssl-examples/).
+
+
+### Troubleshooting
+
+When encountering odd errors such as `undefined reference to ``_impure_ptr'`, such as this:
+
+```text
+c:/users/gojimmypi/appdata/local/arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/esp-2021r2-patch5-8.4.0/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: C:\Users\gojimmypi\AppData\Local\Temp\arduino\sketches\EAB8D79A02D1ECF107884802D893914E\libraries\wolfSSL\wolfcrypt\src\logging.c.o:(.literal.wolfssl_log+0x8): undefined reference to `_impure_ptr'
+collect2.exe: error: ld returned 1 exit status
+
+exit status 1
+
+Compilation error: exit status 1
+```
+
+Try cleaning the Arduino cache directories. For Windows, that's typically in:
+
+```text
+C:\Users\%USERNAME%\AppData\Local\Temp\arduino\sketches
+```
+
+Remove all other boards from other serial ports, leaving one the one being programmed.
diff --git a/examples/template/template.ino b/examples/template/template.ino
new file mode 100644
index 0000000..0d0f8d8
--- /dev/null
+++ b/examples/template/template.ino
@@ -0,0 +1,150 @@
+/* template.ino
+ *
+ * Copyright (C) 2006-2025 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 3 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
+ */
+
+#include
+
+#if defined(ARDUINO_PORTENTA_X8)
+ /* The Portenta is a Linux device. See wolfSSL examples:
+ * https://github.com/wolfSSL/wolfssl/tree/master/examples
+ * By default Serial is disabled and mapped to ErrorSerial */
+ #include
+#endif
+
+/* wolfSSL user_settings.h must be included from settings.h
+ * Make all configurations changes in user_settings.h
+ * Do not edit wolfSSL `settings.h` or `config.h` files.
+ * Do not explicitly include user_settings.h in any source code.
+ * Each Arduino sketch that uses wolfSSL must have: #include "wolfssl.h"
+ * C/C++ source files can use: #include
+ * The wolfSSL "settings.h" must be included in each source file using wolfSSL.
+ * The wolfSSL "settings.h" must appear before any other wolfSSL include.
+ */
+
+/* This is Arduino reference sketch example 2 of 2: multiple file .ino */
+/* See also template.ino project example using a single file project. */
+
+/* Do not insert attempts at appending wolfssl user_settings.h here.
+ * All wolfssl settings needed by wolfSSL must be in the user_settings.h */
+#include
+
+/* settings.h is included from Arduino `wolfssl.h`, but a good practice to
+ * include before any other wolfssl headers. As a reminder here: */
+#include
+
+/* Include a simple wolfSSL header to this example: */
+#include
+
+/* There's a wolfSSL_Arduino_Serial_Print() for logging messages in wolfssl. */
+#include
+
+/* Include files (.c, .cpp, .h) typically in the same directory as the sketch;
+ * The wolfssl_helper is an example of this: */
+#include "wolfssl_helper.h"
+
+/* Arduino library header files are typically not in an `include` directory;
+ * The wolfssl_library is an example of a library directory: */
+#include "wolfssl_library/wolfssl_library.h"
+#include "wolfssl_library/src/wolfssl_library.cpp" /* Force compilation */
+
+/* Choose a monitor serial baud rate: 9600, 14400, 19200, 57600, 74880, etc. */
+#define SERIAL_BAUD 115200
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino setup() */
+/*****************************************************************************/
+/*****************************************************************************/
+void setup() {
+ Serial.begin(SERIAL_BAUD);
+ while (!Serial) {
+ /* wait for serial port to connect. Needed for native USB port only */
+ delay(10);
+ }
+ /* See https://github.com/wolfSSL/wolfssl/blob/master/examples/configs/user_settings_arduino.h */
+ /* Various historical versions have differing features enabled. */
+#ifdef WOLFSSL_USER_SETTINGS_ID
+ /* Print the release version at runtime for reference. */
+ Serial.println(WOLFSSL_USER_SETTINGS_ID);
+#else
+ /* Introduced after v5.7.6, or otherwise missing from user_settings.h */
+ Serial.println("A WOLFSSL_USER_SETTINGS_ID not found.");
+#endif
+
+ Serial.println(F("wolfSSL setup complete!!"));
+ Serial.println(F(""));
+ Serial.println(F(""));
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino loop() */
+/*****************************************************************************/
+/*****************************************************************************/
+void loop() {
+ int ret;
+ Serial.println("\nLOOP!\n\n");
+
+ Serial.print("wolfSSL Version: ");
+ Serial.println(LIBWOLFSSL_VERSION_STRING);
+
+ /* A project-level include.
+ * These files typically WILL be visible automatically in the Arduino IDE */
+ ret = wolfssl_helper_sample();
+ Serial.print("- wolfssl_helper_sample ret = ");
+ Serial.println(ret);
+
+ /* A local library directory.
+ * These files typically WILL NOT be visible in the Arduino IDE */
+ ret = wolfssl_library_sample();
+ Serial.print("- wolfssl_library_sample ret = ");
+ Serial.println(ret);
+
+ /* This next section demonstrates wolfSSL logging. Logging is toggled
+ * on or off for each Arduino loop() iteration. WOLFSSL_MSG() only
+ * prints messages when debugging is turned on. */
+
+ /* Internal wolfssl_log() uses wolfSSL_Arduino_Serial_Print() */
+ Serial.println("");
+ Serial.println("Example wolfSSL_Arduino_Serial_Print():");
+ wolfSSL_Arduino_Serial_Print("Hello from wolfSSL_Arduino_Serial_Print");
+
+ /* WOLFSSL_MSG uses wolfssl_log() for conditional messages. */
+ Serial.println("The next line is conditional depending on debug state:");
+ WOLFSSL_MSG("Hello from wolfssl_log");
+ Serial.println("");
+
+ ret = WOLFSSL_IS_DEBUG_ON();
+ if (ret == 0) {
+ Serial.println(""); /* nothing would have printed in WOLFSSL_MSG */
+ Serial.println("WOLFSSL_IS_DEBUG_ON is not set (debugging off)");
+
+ Serial.println("Calling wolfSSL_Debugging_ON()");
+ wolfSSL_Debugging_ON();
+ }
+ else {
+ Serial.println("WOLFSSL_IS_DEBUG_ON is set (debugging on)");
+
+ Serial.println("Calling wolfSSL_Debugging_OFF()");
+ wolfSSL_Debugging_OFF();
+ }
+
+ delay(60000);
+}
diff --git a/examples/template/wolfssl_helper.c b/examples/template/wolfssl_helper.c
new file mode 100644
index 0000000..c6dcd39
--- /dev/null
+++ b/examples/template/wolfssl_helper.c
@@ -0,0 +1,78 @@
+/* my_library.cpp
+ *
+ * Copyright (C) 2006-2025 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 3 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
+ */
+
+/* This is a sample include directory library using wolfSSL.
+ *
+ * Do not explicitly include wolfSSL user_settings.h here.
+ *
+ * Be sure to include these files in all libraries that reference
+ * wolfssl in this order: */
+
+#if defined(ARDUINO_PORTENTA_X8)
+ /* This file is purposely a c and not .cpp file for testing.
+ * On Portenta X8 the core headers assume C++, and things like A6,
+ * PIN_SPI_MOSI, etc. - rely on C++-only constructs.
+ * So don't include Arduino.h here for Portenta. */
+
+ #include
+ #include /* The ssl.h usually included by wolfssl.h */
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ /* Sample source code is C, but Arduino is compiling with C++
+ * Declare a helper function to be used in wolfssl/wolfcrypt/logging.c */
+ int wolfSSL_Arduino_Serial_Print(const char* const s);
+
+ #ifdef __cplusplus
+ }
+ #endif
+#else
+ /* Assume all other target boards would want to include Arduino.h in a
+ * helper such as this one. Not needed in this wolfssl_helper.c example. */
+ #include
+
+ /* settings.h is typically included in wolfssl.h, but here as a reminder: */
+ #include
+ #include /* The wolfssl core Arduino library file */
+#endif
+
+
+#include "wolfssl_helper.h"
+
+int wolfssl_helper_sample()
+{
+ /* We cannot use Serial.print in a "c" file */
+ /* Serial.print("Hello world!"); */
+ int ret;
+ printf("Hello wolfssl_helper_sample!\r\n");
+
+ printf("- Calling wolfSSL_Init()\r\n");
+ ret = wolfSSL_Init();
+ if (ret == WOLFSSL_SUCCESS) {
+ printf("- Success wolfssl_helper!\r\n");
+ }
+ else {
+ printf("- Error initializing wolfSSL!\r\n");
+ }
+ return ret;
+}
diff --git a/examples/template/wolfssl_helper.h b/examples/template/wolfssl_helper.h
new file mode 100644
index 0000000..1291dbe
--- /dev/null
+++ b/examples/template/wolfssl_helper.h
@@ -0,0 +1,37 @@
+/* wolfssl_helper.h
+ *
+ * Copyright (C) 2006-2025 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 3 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_HELPER_H_
+#define _WOLFSSL_HELPER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Sample source code is C, but Arduino is compiling with C++ */
+int wolfssl_helper_sample();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/examples/template/wolfssl_library/src/wolfssl_library.cpp b/examples/template/wolfssl_library/src/wolfssl_library.cpp
new file mode 100644
index 0000000..e4d9685
--- /dev/null
+++ b/examples/template/wolfssl_library/src/wolfssl_library.cpp
@@ -0,0 +1,42 @@
+/* wolfssl_library.cpp
+ *
+ * Copyright (C) 2006-2025 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
+ */
+#include
+#include
+#include
+
+/* Arduino source is typically in a `src` directory, with header in parent: */
+#include "../wolfssl_library.h"
+
+int wolfssl_library_sample()
+{
+ int ret = 0;
+ Serial.println("\nHello wolfssl_library!");
+
+ printf("- Calling wolfSSL_Init()\r\n");
+ ret = wolfSSL_Init();
+ if (ret == WOLFSSL_SUCCESS) {
+ printf("- Success wolfssl_library!\r\n");
+ }
+ else {
+ printf("- Error initializing wolfSSL!\r\n");
+ }
+ return ret;
+}
diff --git a/examples/template/wolfssl_library/wolfssl_library.h b/examples/template/wolfssl_library/wolfssl_library.h
new file mode 100644
index 0000000..98f5dfd
--- /dev/null
+++ b/examples/template/wolfssl_library/wolfssl_library.h
@@ -0,0 +1,46 @@
+/* wolfssl_library.h
+ *
+ * Copyright (C) 2006-2025 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
+ */
+
+
+/* This is a sample include directory library using wolfSSL.
+ *
+ * Do not explicitly include wolfSSL user_settings.h here.
+ *
+ * Be sure to include these files in all libraries that reference
+ * wolfssl in this order: */
+
+#include
+#include "wolfssl.h"
+
+ #ifndef _WOLFSSL_LIBRARY_H_
+ #define _WOLFSSL_LIBRARY_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int wolfssl_library_sample();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WOLFSSL_LIBRARY_H_ */
diff --git a/examples/wolfssl_AES_CTR/README.md b/examples/wolfssl_AES_CTR/README.md
new file mode 100644
index 0000000..c9b26d6
--- /dev/null
+++ b/examples/wolfssl_AES_CTR/README.md
@@ -0,0 +1,34 @@
+# Arduino AES CTR Example
+
+Open the [wolfssl_AES_CTR.ino](./wolfssl_AES_CTR.ino) file in the Arduino IDE.
+
+Other IDE products are also supported, such as:
+
+- [PlatformIO in VS Code](https://docs.platformio.org/en/latest/frameworks/arduino.html)
+- [VisualGDB](https://visualgdb.com/tutorials/arduino/)
+- [VisualMicro](https://www.visualmicro.com/)
+
+For examples on other platforms, see the [IDE directory](https://github.com/wolfssl/wolfssl/tree/master/IDE).
+Additional examples can be found on [wolfSSL/wolfssl-examples](https://github.com/wolfSSL/wolfssl-examples/).
+
+
+### Troubleshooting
+
+When encountering odd errors such as `undefined reference to ``_impure_ptr'`, such as this:
+
+```text
+c:/users/gojimmypi/appdata/local/arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/esp-2021r2-patch5-8.4.0/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: C:\Users\gojimmypi\AppData\Local\Temp\arduino\sketches\EAB8D79A02D1ECF107884802D893914E\libraries\wolfSSL\wolfcrypt\src\logging.c.o:(.literal.wolfssl_log+0x8): undefined reference to `_impure_ptr'
+collect2.exe: error: ld returned 1 exit status
+
+exit status 1
+
+Compilation error: exit status 1
+```
+
+Try cleaning the Arduino cache directories. For Windows, that's typically in:
+
+```text
+C:\Users\%USERNAME%\AppData\Local\Temp\arduino\sketches
+```
+
+Remove all other boards from other serial ports, leaving one the one being programmed.
diff --git a/examples/wolfssl_AES_CTR/wolfssl_AES_CTR.ino b/examples/wolfssl_AES_CTR/wolfssl_AES_CTR.ino
new file mode 100644
index 0000000..a47d096
--- /dev/null
+++ b/examples/wolfssl_AES_CTR/wolfssl_AES_CTR.ino
@@ -0,0 +1,291 @@
+/* wolfssl_AES_CTR.ino
+ *
+ * Copyright (C) 2006-2025 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 3 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
+ */
+
+#include
+
+#if defined(ARDUINO_PORTENTA_X8)
+ /* The Portenta is a Linux device. See wolfSSL examples:
+ * https://github.com/wolfSSL/wolfssl/tree/master/examples
+ * By default Serial is disabled and mapped to ErrorSerial */
+ #include
+#endif
+
+/*
+The Advanced Encryption Standard (AES) is a specification for the encryption of electronic
+data established by the U.S. National Institute of Standards and Technology (NIST) in 2001.
+
+AES Counter mode (AES-CTR) is a "Block Cipher Mode of Operation" that
+turns a block cipher into a stream cipher, as explained here:
+https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)
+
+The wolfSSL AES algorithms in this sketch (e.g wc_AesCtrEncrypt) are just some of
+many algorithms in the wolfSSL library. All are documented in the wolfSSL Manual at
+https://www.wolfssl.com/documentation/manuals/wolfssl/group__AES.html
+
+This sketch example demonstrates AES-CTR usage by first encrypting the input
+data producing the cipher, then decrypt the cipher to reveal the original data.
+
+Required user inputs
+--------------------
+1) Encryption Key
+2) Initialization Vector ("iv")
+3) The input data to be encrypted
+
+Tested on
+---------
+Arduino UNO R4 WiFi (Renesas ARM Cortex M4)
+Sparkfun MicroMod WiFi Function Board (ESP32-WROOM-32E)
+Wemos D1 R32 Development Board (ESP32-WROOM-32)
+Teensy 4.1 (ARM Cortex M7)
+
+*/
+
+#define WOLFSSL_AES_CTR_EXAMPLE
+/* wolfSSL user_settings.h must be included from settings.h
+ * Make all configurations changes in user_settings.h
+ * Do not edit wolfSSL `settings.h` or `config.h` files.
+ * Do not explicitly include user_settings.h in any source code.
+ * Each Arduino sketch that uses wolfSSL must have: #include "wolfssl.h"
+ * C/C++ source files can use: #include
+ * The wolfSSL "settings.h" must be included in each source file using wolfSSL.
+ * The wolfSSL "settings.h" must appear before any other wolfSSL include.
+ */
+#include
+
+ /* settings.h is included from Arduino `wolfssl.h`, but a good practice to
+ * include before any other wolfssl headers. As a reminder here: */
+#include
+
+#include
+
+#if defined(NO_AES) or !defined(WOLFSSL_AES_COUNTER) or !defined(WOLFSSL_AES_128)
+ /* edit user_settings.h in ~\Arduino\libraries\wolfssl\src
+ * e.g. for Windows:
+ * C:\Users\%USERNAME%\Documents\Arduino\libraries\wolfssl\src
+ */
+ #error "Missing AES, WOLFSSL_AES_COUNTER or WOLFSSL_AES_128"
+#endif
+
+/* macro to check for expected results */
+#define ExpectIntEQ(p1, p2) if (p1 == p2) { \
+ Serial.println(F("OK")); \
+ } \
+ else { \
+ Serial.println(F("FAIL")); \
+ }
+
+
+/* USER INPUTS:
+ * The Encryption Key (encKey) is confidential and must only be shared with
+ * the intended recipient of the data. Length must be 16, 24, 32 or larger
+ * multiples of AES_BLOCK_SIZE
+ *
+ * The initialization Vector (iv) is a nonce/counter (or 'salt') that is
+ * incremented between each encryption to ensures no two ciphers are identical,
+ * even if the input data is unchanged. Can be any length.
+ *
+ * The input data ("input") provides the bytes to be encrypted.
+ * Must be 16, 24, 32 bytes, or larger multiples of AES_BLOCK_SIZE
+ */
+
+/* Choose one of these data sets, or provide your own. */
+/* Example data set 1 */
+byte encKey[] = {0x33,0x9a,0x28,0x9d,0x08,0x61,0xe8,0x34,
+ 0x16,0xe5,0x8d,0xb7,0x58,0x33,0xdc,0x0a}; /* 16 bytes */
+byte iv[] = {0x43,0x05, 0, 0, 0, 0, 0, 0, /* Padded to */
+ 0, 0, 0, 0, 0, 0, 0, 0}; /* 16 bytes */
+byte input[] = {0x05,0x00,0x8c,0x0a,0x21,0x00,0x6a,0x00,
+ 0x5c,0x00,0xff,0xff,0xc1,0xfc,0x25,0xc4}; /* 16 bytes */
+
+/*
+ * Example data set 2
+byte encKey[] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+ 0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x66,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+ 0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x66}; // 32 bytes
+
+byte iv[] = "1234567890abcdef";
+
+byte input[] = { // Now is the time for all w/o trailing 0
+ 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
+ 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20}; // 24 bytes
+*/
+
+/* create aes objects for encryption & decryption */
+Aes aesEnc;
+Aes aesDec;
+
+/* Print out the data as HEX bytes with breaks every 8 bytes */
+void reportData(byte * data, int sz) {
+ int i;
+ for (i = 0; i < sz; i++) {
+ if (data[i] < 0x10) {
+ Serial.print(F("0"));
+ }
+ Serial.print(data[i], HEX);
+ if (i < sz - 1) {
+ if (((i + 1) % 8) == 0) {
+ Serial.print(F(" | "));
+ }
+ else {
+ Serial.print(F(" "));
+ }
+ }
+ }
+ Serial.println();
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino setup() */
+/*****************************************************************************/
+/*****************************************************************************/
+void setup() {
+ Serial.begin(115200);
+ while (!Serial && millis() < 1000) ; /* wait for serial, up to 1 sec */
+
+ Serial.println();
+ Serial.println();
+ Serial.println(F("===== wolfSSL example: AES Counter mode ====="));
+ Serial.print(F("wolfSSL library version: "));
+ Serial.println(LIBWOLFSSL_VERSION_STRING);
+ Serial.println();
+}
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino loop() */
+/*****************************************************************************/
+/*****************************************************************************/
+void loop() {
+ memset(&aesEnc, 0, sizeof(Aes)); /* fill aesEnc with zeros */
+ memset(&aesDec, 0, sizeof(Aes)); /* ditto aesDec */
+
+ /* --------------------------------------------------------------------- */
+ /* Choose blkSize of be 16, 24, 32 or larger multiples of 8, based */
+ /* on sizeof(input) data. Uncomment the relevant lines from following: */
+
+ Serial.print(F("data set 1 ["));
+ uint32_t blkSize = AES_BLOCK_SIZE * 1; /* 16 bytes (for data set 1) */
+
+ /* Serial.print(F("data set 2 - ")); */
+ /* uint32_t blkSize = AES_BLOCK_SIZE * 1.5; // 24 bytes (for data set 2) */
+
+ /* Serial.print(F("my data set - ")); */
+ /* uint32_t blkSize = AES_BLOCK_SIZE * n; // choose an appropriate n */
+
+ Serial.print(F("blkSize: "));
+ Serial.print(blkSize);
+ Serial.println(F(" bytes]"));
+ Serial.println();
+ /* ----------------------------------------------------------------------*/
+
+ byte cipher[blkSize]; /* for the encrypted data (or "cipher") */
+ byte output[blkSize]; /* for the deciphered data */
+ memset(cipher, 0, blkSize); /* fill with zeros */
+ memset(output, 0, blkSize); /* fill with zeros */
+
+ /* initialize structures for encryption and decryption. */
+ Serial.println(F("--- Encryption ..."));
+ Serial.print(F("init aes (enc) : "));
+
+ /* init aesEnc structure, with NULL heap hint, dev id not used. */
+ ExpectIntEQ(wc_AesInit(&aesEnc, NULL, INVALID_DEVID), 0);
+
+ /* set up the key + salt in the AES encryption structure. */
+ Serial.print(F("load key (enc) : "));
+ ExpectIntEQ(wc_AesSetKey(&aesEnc, encKey, blkSize, iv, AES_ENCRYPTION), 0);
+
+ /* encrypt */
+ Serial.print(F("encryption done: "));
+ ExpectIntEQ(wc_AesCtrEncrypt(&aesEnc, cipher,
+ input, sizeof(input) / sizeof(byte) ), 0);
+
+ Serial.println();
+ Serial.println(F("--- Decryption ..."));
+ /* set up the key + salt in the AES decryption structure. */
+ Serial.print(F("init aes (dec) : "));
+
+ /* init aesDec structure, with NULL heap hint, dev id not used. */
+ ExpectIntEQ(wc_AesInit(&aesDec, NULL, INVALID_DEVID), 0);
+
+ /* set up the key + salt in an AES decryption structure. */
+ Serial.print(F("load key (dec) : "));
+ ExpectIntEQ(wc_AesSetKey(&aesDec, encKey, blkSize, iv, AES_ENCRYPTION), 0);
+
+ /* decrypt */
+ Serial.print(F("decryption done: "));
+ ExpectIntEQ(wc_AesCtrEncrypt(&aesDec, output,
+ cipher, sizeof(cipher) / sizeof(byte)), 0);
+ Serial.println();
+
+ /* Test for bad args */
+ Serial.println(F("--- Check for bad arguments ..."));
+ Serial.print(F("Bad arguments 1: "));
+ ExpectIntEQ(wc_AesCtrEncrypt(NULL, output,
+ cipher, sizeof(cipher) / sizeof(byte)),
+ WC_NO_ERR_TRACE(BAD_FUNC_ARG));
+
+ Serial.print(F("Bad arguments 2: "));
+ ExpectIntEQ(wc_AesCtrEncrypt(&aesDec, NULL,
+ cipher, sizeof(cipher) / sizeof(byte)),
+ WC_NO_ERR_TRACE(BAD_FUNC_ARG));
+
+ Serial.print(F("Bad arguments 3: "));
+ ExpectIntEQ(wc_AesCtrEncrypt(&aesDec, output,
+ NULL, sizeof(cipher) / sizeof(byte)),
+ WC_NO_ERR_TRACE(BAD_FUNC_ARG));
+
+ /* Display data and results. */
+ Serial.println();
+ Serial.println(F("--- Inputs ..."));
+ Serial.print(F("key : ")); reportData(encKey, sizeof(encKey));
+ Serial.print(F("salt/iv : ")); reportData(iv, sizeof(iv));
+ Serial.print(F("data in : ")); reportData(input, sizeof(input));
+
+ Serial.println();
+ Serial.println(F("--- Outputs ..."));
+ Serial.print(F("cipher : "));
+ reportData(cipher, sizeof(cipher));
+ Serial.print(F("decipher: "));
+ reportData(output, sizeof(output));
+ Serial.println();
+
+ if (memcmp(input, output, sizeof(input)) == 0) {
+ Serial.println(F("** SUCCESS ** deciphered data matches input data."));
+ }
+ else {
+ Serial.print(F("*** FAILED *** deciphered & input data DO NOT MATCH."));
+ }
+ Serial.println();
+
+ /* Free up resources associated with the aes structures. */
+ wc_AesFree(&aesEnc);
+ wc_AesFree(&aesDec);
+
+ Serial.println(F("===== end ====="));
+
+ while (1) {
+ /* nothing */
+ }
+}
diff --git a/examples/wolfssl_client/README.md b/examples/wolfssl_client/README.md
index caf83c5..3068931 100644
--- a/examples/wolfssl_client/README.md
+++ b/examples/wolfssl_client/README.md
@@ -2,6 +2,12 @@
Open the [wolfssl_client.ino](./wolfssl_client.ino) file in the Arduino IDE.
+If using WiFi, be sure to set `ssid` and `password` values.
+
+May need "Ethernet by Various" library to be installed. Tested with v2.0.2 and v2.8.1.
+
+See the `#define WOLFSSL_TLS_SERVER_HOST` to set your own server address.
+
Other IDE products are also supported, such as:
- [PlatformIO in VS Code](https://docs.platformio.org/en/latest/frameworks/arduino.html)
diff --git a/examples/wolfssl_client/wolfssl_client.ino b/examples/wolfssl_client/wolfssl_client.ino
index 514c7dc..c56de7f 100644
--- a/examples/wolfssl_client/wolfssl_client.ino
+++ b/examples/wolfssl_client/wolfssl_client.ino
@@ -1,12 +1,12 @@
/* wolfssl_client.ino
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -37,13 +37,25 @@ Tested with:
*/
/* If you have a private include, define it here, otherwise edit WiFi params */
-#define MY_PRIVATE_CONFIG "/workspace/my_private_config.h"
+/* #define MY_PRIVATE_CONFIG "/workspace/my_private_config.h" */
+
+#if defined(ARDUINO) && defined(ESP8266)
+ #warning "This example is not yet supported on Arduino ESP8266"
+#endif
+
+#if defined(DEBUG_WOLFSSL)
+ /* Optionally enabled verbose wolfSSL debugging */
+ #define DEBUG_WOLFSSL_MESSAGES_ON
+#else
+ /* DEBUG_WOLFSSL needs to be enabled */
+ #undef DEBUG_WOLFSSL_MESSAGES_ON
+#endif
/* set REPEAT_CONNECTION to a non-zero value to continually run the example. */
#define REPEAT_CONNECTION 0
/* Edit this with your other TLS host server address to connect to: */
-#define WOLFSSL_TLS_SERVER_HOST "192.168.1.34"
+#define WOLFSSL_TLS_SERVER_HOST "192.168.1.39"
/* wolfssl TLS examples communicate on port 11111 */
#define WOLFSSL_PORT 11111
@@ -58,7 +70,7 @@ Tested with:
#define RECONNECT_ATTEMPTS 20
/* Optional stress test. Define to consume memory until exhausted: */
-#define MEMORY_STRESS_TEST
+/* #define MEMORY_STRESS_TEST */
/* Choose client or server example, not both. */
#define WOLFSSL_CLIENT_EXAMPLE
@@ -68,12 +80,12 @@ Tested with:
/* the /workspace directory may contain a private config
* excluded from GitHub with items such as WiFi passwords */
#include MY_PRIVATE_CONFIG
- const char* ssid PROGMEM = CONFIG_ESP_WIFI_SSID;
- const char* password PROGMEM = CONFIG_ESP_WIFI_PASSWORD;
+ static const char ssid[] PROGMEM = MY_ARDUINO_WIFI_SSID;
+ static const char password[] PROGMEM = MY_ARDUINO_WIFI_PASSWORD;
#else
/* when using WiFi capable boards: */
- const char* ssid PROGMEM = "your_SSID";
- const char* password PROGMEM = "your_PASSWORD";
+ static const char ssid[] PROGMEM = "your_SSID";
+ static const char password[] PROGMEM = "your_PASSWORD";
#endif
#define BROADCAST_ADDRESS "255.255.255.255"
@@ -85,6 +97,15 @@ Tested with:
#include
#endif
+/* wolfSSL user_settings.h must be included from settings.h
+ * Make all configurations changes in user_settings.h
+ * Do not edit wolfSSL `settings.h` or `config.h` files.
+ * Do not explicitly include user_settings.h in any source code.
+ * Each Arduino sketch that uses wolfSSL must have: #include "wolfssl.h"
+ * C/C++ source files can use: #include
+ * The wolfSSL "settings.h" must be included in each source file using wolfSSL.
+ * The wolfSSL "settings.h" must appear before any other wolfSSL include.
+ */
#include
/* Important: make sure settings.h appears before any other wolfSSL headers */
#include
@@ -123,6 +144,10 @@ Tested with:
#elif defined(ESP8266)
#define USING_WIFI
#include
+ /* Ensure the F() flash macro is defined */
+ #ifndef F
+ #define F
+ #endif
WiFiClient client;
#elif defined(ARDUINO_SAM_DUE)
@@ -131,11 +156,14 @@ Tested with:
/* Needs "Ethernet by Various" library to be installed. Tested with V2.0.2 */
#include
EthernetClient client;
-
+#elif defined(ARDUINO_AVR_ETHERNET) || defined(ARDUINO_AVR_LEONARDO_ETH)
+ /* Boards such as arduino:avr:ethernet and arduino:avr:leonardoeth */
+ #include
+ EthernetClient client;
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
#define USING_WIFI
#include
- #include
+ #include /* Needs Arduino WiFiNINA library installed manually */
WiFiClient client;
#elif defined(ARDUINO_ARCH_RP2040)
@@ -144,6 +172,36 @@ Tested with:
#include
WiFiClient client;
+#elif defined(ARDUINO_SAMD_TIAN)
+ #include
+ #include
+ HttpClient client;
+ /* Arduino Tian does not support network shields like the standard Ethernet or Wi-Fi shields. */
+ #error "HttpClient cannot be used for this example"
+#elif defined(ARDUINO_PORTENTA_X8)
+ /* The Portenta is a Linux device. See wolfSSL examples:
+ * https://github.com/wolfSSL/wolfssl/tree/master/examples
+ * By default Serial is disabled and mapped to ErrorSerial */
+ #include
+
+ /* ----No - network placeholders(compile - only) ---- */
+ #include
+ struct X8NoNetClient {
+ int write(const uint8_t*, size_t) { return -1; }
+ int available() { return 0; }
+ int read() { return -1; }
+ void stop() {}
+ bool connected() { return false; }
+ IPAddress remoteIP() { return IPAddress(0, 0, 0, 0); }
+ };
+ struct X8NoNetServer {
+ explicit X8NoNetServer(uint16_t) {}
+ void begin() {}
+ X8NoNetClient available() { return X8NoNetClient(); }
+ };
+
+ X8NoNetClient client;
+ X8NoNetServer server(WOLFSSL_PORT);
#elif defined(USING_WIFI)
#define USING_WIFI
#include
@@ -157,9 +215,10 @@ Tested with:
#elif defined(OTHER_BOARD)
*/
#else
+ /* assume all other boards using WiFi library. Edit as needed: */
+ #include
#define USING_WIFI
WiFiClient client;
-
#endif
/* Only for syntax highlighters to show interesting options enabled: */
@@ -176,34 +235,36 @@ Tested with:
|| defined(HAVE_SERVER_RENEGOTIATION_INFO)
#endif
-const char host[] PROGMEM = WOLFSSL_TLS_SERVER_HOST; /* server to connect to */
-const int port PROGMEM = WOLFSSL_PORT; /* port on server to connect to */
-const int serial_baud PROGMEM = SERIAL_BAUD; /* local serial port to monitor */
+static const char host[] PROGMEM = WOLFSSL_TLS_SERVER_HOST; /* server to connect to */
+static const int port PROGMEM = WOLFSSL_PORT; /* port on server to connect to */
-WOLFSSL_CTX* ctx = NULL;
-WOLFSSL* ssl = NULL;
-char* wc_error_message = (char*)malloc(80 + 1);
-char errBuf[80];
+static WOLFSSL_CTX* ctx = NULL;
+static WOLFSSL* ssl = NULL;
+static char* wc_error_message = (char*)malloc(80 + 1);
+static char errBuf[80];
#if defined(MEMORY_STRESS_TEST)
#define MEMORY_STRESS_ITERATIONS 100
#define MEMORY_STRESS_BLOCK_SIZE 1024
#define MEMORY_STRESS_INITIAL (4*1024)
- char* memory_stress[MEMORY_STRESS_ITERATIONS]; /* typically 1K per item */
- int mem_ctr = 0;
+ static char* memory_stress[MEMORY_STRESS_ITERATIONS]; /* typically 1K per item */
+ static int mem_ctr = 0;
#endif
static int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx);
static int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx);
static int reconnect = RECONNECT_ATTEMPTS;
+#if 0
+/* optional showPeerEx, currently disabled */
static int lng_index PROGMEM = 0; /* 0 = English */
+#endif
#if defined(__arm__)
#include
extern char _end;
extern "C" char *sbrk(int i);
- char *ramstart=(char *)0x20070000;
- char *ramend=(char *)0x20088000;
+ static char *ramstart=(char *)0x20070000;
+ static char *ramend=(char *)0x20088000;
#endif
/*****************************************************************************/
@@ -372,28 +433,31 @@ int setup_network(void) {
#if defined(USING_WIFI)
int status = WL_IDLE_STATUS;
- if (WiFi.status() == WL_NO_MODULE) {
- Serial.println("Communication with WiFi module failed!");
- /* don't continue if no network */
- while (true) ;
- }
-
- String fv = WiFi.firmwareVersion();
- if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
- Serial.println("Please upgrade the firmware");
- }
-
/* The ESP8266 & ESP32 support both AP and STA. We'll use STA: */
#if defined(ESP8266) || defined(ESP32)
WiFi.mode(WIFI_STA);
+ #else
+ String fv;
+ if (WiFi.status() == WL_NO_MODULE) {
+ Serial.println("Communication with WiFi module failed!");
+ /* don't continue if no network */
+ while (true) ;
+ }
+
+ fv = WiFi.firmwareVersion();
+ if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
+ Serial.println("Please upgrade the firmware");
+ }
#endif
Serial.print(F("Connecting to WiFi "));
Serial.print(ssid);
+ status = WiFi.begin(ssid, password);
while (status != WL_CONNECTED) {
- status = WiFi.begin(ssid, password);
- delay(5000);
+ delay(1000);
Serial.print(F("."));
+ Serial.print(status);
+ status = WiFi.status();
}
Serial.println(F(" Connected!"));
@@ -450,7 +514,8 @@ int setup_network(void) {
/*****************************************************************************/
/* Arduino setup_wolfssl() */
/*****************************************************************************/
-int setup_wolfssl(void) {
+int setup_wolfssl(void)
+{
int ret = 0;
WOLFSSL_METHOD* method;
@@ -470,8 +535,14 @@ int setup_wolfssl(void) {
#endif
#if defined(DEBUG_WOLFSSL)
- wolfSSL_Debugging_ON();
- Serial.println(F("wolfSSL Debugging is On!"));
+ Serial.println(F("wolfSSL Debugging is available! (DEBUG_WOLFSSL)"));
+ #if defined(DEBUG_WOLFSSL_MESSAGES_ON)
+ Serial.println(F("Enabling verbose messages wolfSSL_Debugging_ON"));
+ wolfSSL_Debugging_ON();
+ #else
+ Serial.println(F("Enable verbose messages with wolfSSL_Debugging_ON"));
+ Serial.println(F("or define DEBUG_WOLFSSL_MESSAGES_ON"));
+ #endif
#else
Serial.println(F("wolfSSL Debugging is Off! (enable with DEBUG_WOLFSSL)"));
#endif
@@ -497,6 +568,7 @@ int setup_wolfssl(void) {
* It is best on embedded devices to choose a TLS session cache size. */
#endif
+ /* Initialize wolfSSL before assigning ctx */
ret = wolfSSL_Init();
if (ret == WOLFSSL_SUCCESS) {
Serial.println("Successfully called wolfSSL_Init");
@@ -531,7 +603,8 @@ int setup_wolfssl(void) {
/*****************************************************************************/
/* Arduino setup_certificates() */
/*****************************************************************************/
-int setup_certificates(void) {
+int setup_certificates(void)
+{
int ret = 0;
Serial.println(F("Initializing certificates..."));
@@ -597,10 +670,14 @@ int setup_certificates(void) {
/* Arduino setup() */
/*****************************************************************************/
/*****************************************************************************/
-void setup(void) {
- Serial.begin(serial_baud);
- while (!Serial) {
+void setup(void)
+{
+ int i = 0;
+ Serial.begin(SERIAL_BAUD);
+ while (!Serial && (i < 10)) {
/* wait for serial port to connect. Needed for native USB port only */
+ delay(1000);
+ i++;
}
Serial.println(F(""));
Serial.println(F(""));
@@ -623,10 +700,10 @@ void setup(void) {
setup_hardware();
- setup_datetime();
-
setup_network();
+ setup_datetime();
+
setup_wolfssl();
setup_certificates();
@@ -635,13 +712,17 @@ void setup(void) {
wolfSSL_SetIOSend(ctx, EthernetSend);
wolfSSL_SetIORecv(ctx, EthernetReceive);
+#if defined THIS_USER_SETTINGS_VERSION
+ Serial.print(F("This user_settings.h version:"))
+ Serial.println(THIS_USER_SETTINGS_VERSION)
+#endif
+
Serial.println(F("Completed Arduino setup!"));
/* See companion wolfssl_server.ino code; server begins listening here
* https://github.com/wolfSSL/wolfssl/tree/master/IDE/ARDUINO/sketches/wolfssl_server
* Any other server will work. See also:
* https://github.com/wolfSSL/wolfssl/tree/master/examples/client
*/
- /* See companion wolfssl_server.ino code */
return;
} /* Arduino setup */
@@ -716,7 +797,7 @@ int error_check_ssl(WOLFSSL* ssl, int this_ret, bool halt_on_error,
}
return err;
-}
+} /* error_check_ssl */
/*****************************************************************************/
/*****************************************************************************/
diff --git a/examples/wolfssl_client_dtls/README.md b/examples/wolfssl_client_dtls/README.md
new file mode 100644
index 0000000..924225b
--- /dev/null
+++ b/examples/wolfssl_client_dtls/README.md
@@ -0,0 +1,28 @@
+# Arduino Basic DTLS Listening Client
+
+Open the [wolfssl_client_dtls.ino](./wolfssl_client_dtls.ino) file in the Arduino IDE.
+
+If using WiFi, be sure to set `ssid` and `password` values.
+
+May need "Ethernet by Various" library to be installed. Tested with v2.0.2 and v2.8.1.
+
+See the `#define WOLFSSL_TLS_SERVER_HOST` to set your own server address.
+
+Other IDE products are also supported, such as:
+
+- [PlatformIO in VS Code](https://docs.platformio.org/en/latest/frameworks/arduino.html)
+- [VisualGDB](https://visualgdb.com/tutorials/arduino/)
+- [VisualMicro](https://www.visualmicro.com/)
+
+For examples on other platforms, see the [IDE directory](https://github.com/wolfssl/wolfssl/tree/master/IDE).
+Additional examples can be found on [wolfSSL/wolfssl-examples](https://github.com/wolfSSL/wolfssl-examples/).
+
+
+### Troubleshooting
+
+When encountering odd errors such as `undefined reference to ``_impure_ptr'`, try cleaning the Arduino
+cache directories. For Windows, that's typically in:
+
+```text
+C:\Users\%USERNAME%\AppData\Local\Temp\arduino\sketches
+```
diff --git a/examples/wolfssl_client_dtls/wolfssl_client_dtls.ino b/examples/wolfssl_client_dtls/wolfssl_client_dtls.ino
new file mode 100644
index 0000000..e4e8fec
--- /dev/null
+++ b/examples/wolfssl_client_dtls/wolfssl_client_dtls.ino
@@ -0,0 +1,950 @@
+/*
+ * client-dtls13.c
+ *
+ * Copyright (C) 2006-2025 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 3 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
+ *
+ *=============================================================================
+ *
+ * Bare-bones example of a DTLS 1.3 client for instructional/learning purposes.
+ * This example uses blocking sockets for simplicity.
+ *
+ * Define USE_DTLS12 to use DTLS 1.2 instead of DTLS 1.3
+/*
+Tested with:
+
+1) Intel Galileo acting as the Client, with a laptop acting as a server using
+ the server example provided in examples/server.
+ Legacy Arduino v1.86 was used to compile and program the Galileo
+
+2) Espressif ESP32 WiFi
+
+3) Arduino Due, Nano33 IoT, Nano RP-2040
+*/
+
+/*
+ * Note to code editors: the Arduino client and server examples are edited in
+ * parallel for side-by-side comparison between examples.
+ */
+
+/* If you have a private include, define it here, otherwise edit WiFi params */
+/* #define MY_PRIVATE_CONFIG "/workspace/my_private_config.h" */
+
+#if defined(ARDUINO) && defined(ESP8266)
+ #warning "This example is not yet supported on Arduino ESP8266"
+#endif
+
+#if defined(DEBUG_WOLFSSL)
+ /* Optionally enabled verbose wolfSSL debugging */
+ #define DEBUG_WOLFSSL_MESSAGES_ON
+#else
+ /* DEBUG_WOLFSSL needs to be enabled */
+ #undef DEBUG_WOLFSSL_MESSAGES_ON
+#endif
+
+/* set REPEAT_CONNECTION to a non-zero value to continually run the example. */
+#define REPEAT_CONNECTION 0
+
+/* Edit this with your other DTLS host server address to connect to: */
+#define WOLFSSL_DTLS_SERVER_HOST "192.168.1.107"
+
+/* wolfssl TLS examples communicate on port 11111 */
+#define WOLFSSL_PORT 11111
+
+/* Choose a monitor serial baud rate: 9600, 14400, 19200, 57600, 74880, etc. */
+#define SERIAL_BAUD 115200
+
+/* We'll wait up to 2000 milliseconds to properly shut down connection */
+#define SHUTDOWN_DELAY_MS 2000
+
+/* Number of times to retry connection. */
+#define RECONNECT_ATTEMPTS 20
+
+/* Number of DTLS messages to send. Use -1 for continual messages. */
+#define DTLS_MESSAGE_CT 42
+
+/* Assume bad socket until proven otherwise */
+#define INVALID_SOCKET -1
+
+/* Maximum size in bytes of buffer to send and receive */
+#define MAXLINE 128
+
+/* Optional stress test. Define to consume memory until exhausted: */
+/* #define MEMORY_STRESS_TEST */
+
+/* Choose client or server example, not both. */
+#define WOLFSSL_CLIENT_EXAMPLE
+/* #define WOLFSSL_SERVER_EXAMPLE */
+
+#if defined(MY_PRIVATE_CONFIG)
+ /* the /workspace directory may contain a private config
+ * excluded from GitHub with items such as WiFi passwords */
+ #include MY_PRIVATE_CONFIG
+ static const char ssid[] PROGMEM = MY_ARDUINO_WIFI_SSID;
+ static const char password[] PROGMEM = MY_ARDUINO_WIFI_PASSWORD;
+#else
+ /* when using WiFi capable boards: */
+ static const char ssid[] PROGMEM = "your_SSID";
+ static const char password[] PROGMEM = "your_PASSWORD";
+#endif
+
+#define BROADCAST_ADDRESS "255.255.255.255"
+
+/* There's an optional 3rd party NTPClient library by Fabrice Weinberg.
+ * If it is installed, uncomment define USE_NTP_LIB here: */
+/* #define USE_NTP_LIB */
+#ifdef USE_NTP_LIB
+ #include
+#endif
+
+/* wolfSSL user_settings.h must be included from settings.h
+ * Make all configurations changes in user_settings.h
+ * Do not edit wolfSSL `settings.h` or `config.h` files.
+ * Do not explicitly include user_settings.h in any source code.
+ * Each Arduino sketch that uses wolfSSL must have: #include "wolfssl.h"
+ * C/C++ source files can use: #include
+ * The wolfSSL "settings.h" must be included in each source file using wolfSSL.
+ * The wolfSSL "settings.h" must appear before any other wolfSSL include.
+ */
+#include
+/* Important: make sure settings.h appears before any other wolfSSL headers */
+#include
+/* Reminder: settings.h includes user_settings.h
+ * For ALL project wolfSSL settings, see:
+ * [your path]/Arduino\libraries\wolfSSL\src\user_settings.h */
+#include
+#include
+#include
+
+#ifndef WOLFSSL_DTLS
+ /* Support for DTLS by default was added after wolfSSL v5.8.2 release */
+ #error "This example requires WOLFSSL_DTLS. See user_settings.h in the Arduino wolfssl library"
+#endif
+
+/* Define DEBUG_WOLFSSL in user_settings.h for more verbose logging. */
+#if defined(DEBUG_WOLFSSL)
+ #define PROGRESS_DOT F("")
+#else
+ #define PROGRESS_DOT F(".")
+#endif
+
+/* Convert a macro to a string */
+#define xstr(x) str(x)
+#define str(x) #x
+
+/* optional board-specific networking includes */
+#if defined(ESP32)
+ #define USING_WIFI
+ #include
+ #include
+ #ifdef USE_NTP_LIB
+ WiFiUDP ntpUDP;
+ #endif
+ /* Ensure the F() flash macro is defined */
+ #ifndef F
+ #define F
+ #endif
+ WiFiClient client;
+
+#elif defined(ESP8266)
+ #define USING_WIFI
+ #include
+ WiFiClient client;
+
+#elif defined(ARDUINO_SAM_DUE)
+ #include
+ /* There's no WiFi/Ethernet on the Due. Requires Ethernet Shield.
+ /* Needs "Ethernet by Various" library to be installed. Tested with V2.0.2 */
+ #include
+ EthernetClient client;
+#elif defined(ARDUINO_AVR_ETHERNET) || defined(ARDUINO_AVR_LEONARDO_ETH)
+ /* Boards such as arduino:avr:ethernet and arduino:avr:leonardoeth */
+ #include
+ EthernetClient client;
+
+#elif defined(ARDUINO_SAMD_NANO_33_IOT)
+ #define USING_WIFI
+ #include
+ #include /* Needs Arduino WiFiNINA library installed manually */
+ WiFiClient client;
+
+#elif defined(ARDUINO_ARCH_RP2040)
+ #define USING_WIFI
+ #include
+ #include
+ WiFiClient client;
+
+#elif defined(ARDUINO_SAMD_TIAN)
+ #include
+ #include
+ HttpClient client;
+ /* Arduino Tian does not support network shields like the standard Ethernet or Wi-Fi shields. */
+ #error "HttpClient cannot be used for this example"
+#elif defined(ARDUINO_PORTENTA_X8)
+ /* The Portenta is a Linux device. See wolfSSL examples:
+ * https://github.com/wolfSSL/wolfssl/tree/master/examples
+ * By default Serial is disabled and mapped to ErrorSerial */
+ #include
+
+ /* ----No - network placeholders(compile - only) ---- */
+ #include
+ struct X8NoNetClient {
+ int write(const uint8_t*, size_t) { return -1; }
+ int available() { return 0; }
+ int read() { return -1; }
+ void stop() {}
+ bool connected() { return false; }
+ IPAddress remoteIP() { return IPAddress(0, 0, 0, 0); }
+ };
+ struct X8NoNetServer {
+ explicit X8NoNetServer(uint16_t) {}
+ void begin() {}
+ X8NoNetClient available() { return X8NoNetClient(); }
+ };
+
+ X8NoNetClient client;
+ X8NoNetServer server(WOLFSSL_PORT);
+#elif defined(USING_WIFI)
+ #define USING_WIFI
+ #include
+ #include
+ #ifdef USE_NTP_LIB
+ WiFiUDP ntpUDP;
+ #endif
+ WiFiClient client;
+
+/* TODO
+#elif defined(OTHER_BOARD)
+*/
+#else
+ /* assume all other boards using WiFi library. Edit as needed: */
+ #include
+ #define USING_WIFI
+ WiFiClient client;
+#endif
+
+/* Only for syntax highlighters to show interesting options enabled: */
+#if defined(HAVE_SNI) \
+ || defined(HAVE_MAX_FRAGMENT) \
+ || defined(HAVE_TRUSTED_CA) \
+ || defined(HAVE_TRUNCATED_HMAC) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \
+ || defined(HAVE_SUPPORTED_CURVES) \
+ || defined(HAVE_ALPN) \
+ || defined(HAVE_SESSION_TICKET) \
+ || defined(HAVE_SECURE_RENEGOTIATION) \
+ || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+#endif
+
+static const char host[] PROGMEM = WOLFSSL_DTLS_SERVER_HOST; /* server to connect to */
+static const int port PROGMEM = WOLFSSL_PORT; /* port on server to connect to */
+
+static WOLFSSL_CTX* ctx = NULL;
+static WOLFSSL* ssl = NULL;
+static char* wc_error_message = (char*)malloc(80 + 1);
+static char errBuf[80];
+
+#if defined(MEMORY_STRESS_TEST)
+ #define MEMORY_STRESS_ITERATIONS 100
+ #define MEMORY_STRESS_BLOCK_SIZE 1024
+ #define MEMORY_STRESS_INITIAL (4*1024)
+ static char* memory_stress[MEMORY_STRESS_ITERATIONS]; /* typically 1K per item */
+ static int mem_ctr = 0;
+#endif
+
+static int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx);
+static int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx);
+static int reconnect = RECONNECT_ATTEMPTS;
+#if 0
+/* optional showPeerEx, currently disabled */
+static int lng_index PROGMEM = 0; /* 0 = English */
+#endif
+
+#if defined(__arm__)
+ #include
+ extern char _end;
+ extern "C" char *sbrk(int i);
+ static char *ramstart=(char *)0x20070000;
+ static char *ramend=(char *)0x20088000;
+#endif
+
+/*****************************************************************************/
+/* fail_wait - in case of unrecoverable error */
+/*****************************************************************************/
+int fail_wait(void) {
+ show_memory();
+
+ Serial.println(F("Failed. Halt."));
+ while (1) {
+ delay(1000);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* show_memory() to optionally view during debugging. */
+/*****************************************************************************/
+int show_memory(void)
+{
+#if defined(__arm__)
+ struct mallinfo mi = mallinfo();
+
+ char *heapend=sbrk(0);
+ register char * stack_ptr asm("sp");
+ #if defined(DEBUG_WOLFSSL_VERBOSE)
+ Serial.print(" arena=");
+ Serial.println(mi.arena);
+ Serial.print(" ordblks=");
+ Serial.println(mi.ordblks);
+ Serial.print(" uordblks=");
+ Serial.println(mi.uordblks);
+ Serial.print(" fordblks=");
+ Serial.println(mi.fordblks);
+ Serial.print(" keepcost=");
+ Serial.println(mi.keepcost);
+ #endif
+
+ #if defined(DEBUG_WOLFSSL) || defined(MEMORY_STRESS_TEST)
+ Serial.print("Estimated free memory: ");
+ Serial.print(stack_ptr - heapend + mi.fordblks);
+ Serial.println(F(" bytes"));
+ #endif
+
+ #if (0)
+ /* Experimental: not supported on all devices: */
+ Serial.print("RAM Start %lx\n", (unsigned long)ramstart);
+ Serial.print("Data/Bss end %lx\n", (unsigned long)&_end);
+ Serial.print("Heap End %lx\n", (unsigned long)heapend);
+ Serial.print("Stack Ptr %lx\n",(unsigned long)stack_ptr);
+ Serial.print("RAM End %lx\n", (unsigned long)ramend);
+
+ Serial.print("Heap RAM Used: ",mi.uordblks);
+ Serial.print("Program RAM Used ",&_end - ramstart);
+ Serial.print("Stack RAM Used ",ramend - stack_ptr);
+
+ Serial.print("Estimated Free RAM: %d\n\n",stack_ptr - heapend + mi.fordblks);
+ #endif
+#else
+ Serial.println(F("show_memory() not implemented for this platform"));
+#endif
+ return 0;
+}
+
+/*****************************************************************************/
+/* Arduino setup_hardware() */
+/*****************************************************************************/
+int setup_hardware(void) {
+ int ret = 0;
+
+#if defined(ARDUINO_SAMD_NANO_33_IOT)
+ Serial.println(F("Detected known tested and working Arduino Nano 33 IoT"));
+#elif defined(ARDUINO_ARCH_RP2040)
+ Serial.println(F("Detected known tested and working Arduino RP-2040"));
+#elif defined(__arm__) && defined(ID_TRNG) && defined(TRNG)
+ /* need to manually turn on random number generator on Arduino Due, etc. */
+ pmc_enable_periph_clk(ID_TRNG);
+ trng_enable(TRNG);
+ Serial.println(F("Enabled ARM TRNG"));
+#endif
+
+ show_memory();
+ randomSeed(analogRead(0));
+ return ret;
+}
+
+/*****************************************************************************/
+/* Arduino setup_datetime() */
+/* The device needs to have a valid date within the valid range of certs. */
+/*****************************************************************************/
+int setup_datetime(void) {
+ int ret = 0;
+ int ntp_tries = 20;
+
+ /* we need a date in the range of cert expiration */
+#ifdef USE_NTP_LIB
+ #if defined(ESP32)
+ NTPClient timeClient(ntpUDP, "pool.ntp.org");
+
+ timeClient.begin();
+ timeClient.update();
+ delay(1000);
+ while (!timeClient.isTimeSet() && (ntp_tries > 0)) {
+ timeClient.forceUpdate();
+ Serial.println(F("Waiting for NTP update"));
+ delay(2000);
+ ntp_tries--;
+ }
+ if (ntp_tries <= 0) {
+ Serial.println(F("Warning: gave up waiting on NTP"));
+ }
+ Serial.println(timeClient.getFormattedTime());
+ Serial.println(timeClient.getEpochTime());
+ #endif
+#endif
+
+#if defined(ESP32)
+ /* see esp32-hal-time.c */
+ ntp_tries = 5;
+ /* Replace "pool.ntp.org" with your preferred NTP server */
+ configTime(0, 0, "pool.ntp.org");
+
+ /* Wait for time to be set */
+ while ((time(nullptr) <= 100000) && ntp_tries > 0) {
+ Serial.println(F("Waiting for time to be set..."));
+ delay(2000);
+ ntp_tries--;
+ }
+#endif
+
+ return ret;
+} /* setup_datetime */
+
+/*****************************************************************************/
+/* Arduino setup_network() */
+/*****************************************************************************/
+int setup_network(void) {
+ int ret = 0;
+
+#if defined(USING_WIFI)
+ int status = WL_IDLE_STATUS;
+
+ /* The ESP8266 & ESP32 support both AP and STA. We'll use STA: */
+ #if defined(ESP8266) || defined(ESP32)
+ WiFi.mode(WIFI_STA);
+ #else
+ String fv;
+ if (WiFi.status() == WL_NO_MODULE) {
+ Serial.println("Communication with WiFi module failed!");
+ /* don't continue if no network */
+ while (true) ;
+ }
+
+ fv = WiFi.firmwareVersion();
+ if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
+ Serial.println("Please upgrade the firmware");
+ }
+ #endif
+
+ Serial.print(F("Connecting to WiFi "));
+ Serial.print(ssid);
+ status = WiFi.begin(ssid, password);
+ while (status != WL_CONNECTED) {
+ delay(1000);
+ Serial.print(F("."));
+ Serial.print(status);
+ status = WiFi.status();
+ }
+
+ Serial.println(F(" Connected!"));
+#else
+ /* Newer Ethernet shields have a
+ * MAC address printed on a sticker on the shield */
+ byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
+ IPAddress ip(192, 168, 1, 42);
+ IPAddress myDns(192, 168, 1, 1);
+ Ethernet.init(10); /* Most Arduino shields */
+ /* Ethernet.init(5); * MKR ETH Shield */
+ /* Ethernet.init(0); * Teensy 2.0 */
+ /* Ethernet.init(20); * Teensy++ 2.0 */
+ /* Ethernet.init(15); * ESP8266 with Adafruit FeatherWing Ethernet */
+ /* Ethernet.init(33); * ESP32 with Adafruit FeatherWing Ethernet */
+ Serial.println(F("Initialize Ethernet with DHCP:"));
+ if (Ethernet.begin(mac) == 0) {
+ Serial.println(F("Failed to configure Ethernet using DHCP"));
+ /* Check for Ethernet hardware present */
+ if (Ethernet.hardwareStatus() == EthernetNoHardware) {
+ Serial.println(F("Ethernet shield was not found."));
+ while (true) {
+ delay(1); /* do nothing */
+ }
+ }
+ if (Ethernet.linkStatus() == LinkOFF) {
+ Serial.println(F("Ethernet cable is not connected."));
+ }
+ /* try to configure using IP address instead of DHCP : */
+ Ethernet.begin(mac, ip, myDns);
+ }
+ else {
+ Serial.print(F(" DHCP assigned IP "));
+ Serial.println(Ethernet.localIP());
+ }
+ /* We'll assume the Ethernet connection is ready to go. */
+#endif
+
+ Serial.println(F("********************************************************"));
+ Serial.print(F(" wolfSSL Example Client IP = "));
+#if defined(USING_WIFI)
+ Serial.println(WiFi.localIP());
+#else
+ Serial.println(Ethernet.localIP());
+#endif
+ Serial.print(F(" Configured Server Host to connect to: "));
+ Serial.println(host);
+ Serial.println(F("********************************************************"));
+ Serial.println(F("Setup network complete."));
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* Arduino setup_wolfssl() */
+/*****************************************************************************/
+int setup_wolfssl(void)
+{
+ int ret = 0;
+ WOLFSSL_METHOD* method;
+
+ /* Show a revision of wolfssl user_settings.h file in use when available: */
+#if defined(WOLFSSL_USER_SETTINGS_ID)
+ Serial.print(F("WOLFSSL_USER_SETTINGS_ID: "));
+ Serial.println(F(WOLFSSL_USER_SETTINGS_ID));
+#else
+ Serial.println(F("No WOLFSSL_USER_SETTINGS_ID found."));
+#endif
+
+#if defined(NO_WOLFSSL_SERVER)
+ Serial.println(F("wolfSSL server code disabled to save space."));
+#endif
+#if defined(NO_WOLFSSL_CLIENT)
+ Serial.println(F("wolfSSL client code disabled to save space."));
+#endif
+
+#if defined(DEBUG_WOLFSSL)
+ Serial.println(F("wolfSSL Debugging is available! (DEBUG_WOLFSSL)"));
+ #if defined(DEBUG_WOLFSSL_MESSAGES_ON)
+ Serial.println(F("Enabling verbose messages wolfSSL_Debugging_ON"));
+ wolfSSL_Debugging_ON();
+ #else
+ Serial.println(F("Enable verbose messages with wolfSSL_Debugging_ON"));
+ Serial.println(F("or define DEBUG_WOLFSSL_MESSAGES_ON"));
+ #endif
+#else
+ Serial.println(F("wolfSSL Debugging is Off! (enable with DEBUG_WOLFSSL)"));
+#endif
+
+ /* See ssl.c for TLS cache settings. Larger cache = use more RAM. */
+#if defined(NO_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS NO_SESSION_CACHE"));
+#elif defined(MICRO_SESSION_CACHEx)
+ Serial.println(F("wolfSSL TLS MICRO_SESSION_CACHE"));
+#elif defined(SMALL_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS SMALL_SESSION_CACHE"));
+#elif defined(MEDIUM_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS MEDIUM_SESSION_CACHE"));
+#elif defined(BIG_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS BIG_SESSION_CACHE"));
+#elif defined(HUGE_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS HUGE_SESSION_CACHE"));
+#elif defined(HUGE_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS HUGE_SESSION_CACHE"));
+#else
+ Serial.println(F("WARNING: Unknown or no TLS session cache setting."));
+ /* See wolfssl/src/ssl.c for amount of memory used.
+ * It is best on embedded devices to choose a TLS session cache size. */
+#endif
+
+ /* Initialize wolfSSL before assigning ctx */
+ ret = wolfSSL_Init();
+ if (ret == WOLFSSL_SUCCESS) {
+ Serial.println("Successfully called wolfSSL_Init");
+ }
+ else {
+ Serial.println("ERROR: wolfSSL_Init failed");
+ }
+
+ /* See companion server example with wolfSSLv23_server_method here.
+ * method = wolfSSLv23_client_method()); SSL 3.0 - TLS 1.3.
+ * method = wolfTLSv1_2_client_method(); only TLS 1.2
+ * method = wolfTLSv1_3_client_method(); only TLS 1.3
+ *
+ * see Arduino\libraries\wolfssl\src\user_settings.h */
+
+ Serial.println("Here we go!");
+
+#ifdef WOLFSSL_DTLS13
+ Serial.println(F("Setting wolfDTLSv1_3_client_method"));
+ method = wolfDTLSv1_3_client_method();
+#else
+ Serial.println(F("Setting wolfDTLSv1_2_client_method"));
+ method = wolfDTLSv1_2_client_method();
+#endif
+ ctx = wolfSSL_CTX_new(method);
+ if (ctx == NULL) {
+ fail_wait();
+ }
+
+ if (method == NULL) {
+ Serial.println(F("Unable to get wolfssl client method"));
+ fail_wait();
+ }
+
+ ctx = wolfSSL_CTX_new(method);
+ if (ctx == NULL) {
+ Serial.println(F("unable to get ctx"));
+ fail_wait();
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* Arduino setup_certificates() */
+/*****************************************************************************/
+int setup_certificates(void)
+{
+ int ret = 0;
+
+ /* See user_settings.h that should have included wolfssl/certs_test.h */
+
+ Serial.println(F("Initializing certificates..."));
+ show_memory();
+
+ /* Use built-in validation, No verification callback function: */
+ wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0);
+
+ /* Certificate */
+ Serial.println("Initializing certificates...");
+ ret = wolfSSL_CTX_use_certificate_buffer(ctx,
+ CTX_CLIENT_CERT,
+ CTX_CLIENT_CERT_SIZE,
+ CTX_CLIENT_CERT_TYPE);
+ if (ret == WOLFSSL_SUCCESS) {
+ Serial.print("Success: use certificate: ");
+ Serial.println(xstr(CTX_SERVER_CERT));
+ }
+ else {
+ Serial.println(F("Error: wolfSSL_CTX_use_certificate_buffer failed: "));
+ wc_ErrorString(ret, wc_error_message);
+ Serial.println(wc_error_message);
+ fail_wait();
+ }
+
+ /* Setup private client key */
+ ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx,
+ CTX_CLIENT_KEY,
+ CTX_CLIENT_KEY_SIZE,
+ CTX_CLIENT_KEY_TYPE);
+ if (ret == WOLFSSL_SUCCESS) {
+ Serial.print("Success: use private key buffer: ");
+ Serial.println(xstr(CTX_SERVER_KEY));
+ }
+ else {
+ Serial.println(F("Error: wolfSSL_CTX_use_PrivateKey_buffer failed: "));
+ wc_ErrorString(ret, wc_error_message);
+ Serial.println(wc_error_message);
+ fail_wait();
+ }
+
+ ret = wolfSSL_CTX_load_verify_buffer(ctx,
+ CTX_CA_CERT,
+ CTX_CA_CERT_SIZE,
+ CTX_CA_CERT_TYPE);
+ if (ret == WOLFSSL_SUCCESS) {
+ Serial.println(F("Success: load_verify CTX_CA_CERT"));
+ }
+ else {
+ Serial.println(F("Error: wolfSSL_CTX_load_verify_buffer failed: "));
+ wc_ErrorString(ret, wc_error_message);
+ Serial.println(wc_error_message);
+ fail_wait();
+ }
+
+ return ret;
+} /* Arduino setup */
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino setup() */
+/*****************************************************************************/
+/*****************************************************************************/
+void setup(void) {
+ int i = 0;
+ Serial.begin(SERIAL_BAUD);
+ while (!Serial && (i < 10)) {
+ /* wait for serial port to connect. Needed for native USB port only */
+ delay(1000);
+ i++;
+ }
+ Serial.println(F(""));
+ Serial.println(F(""));
+ Serial.println(F("wolfSSL DTLS Client Example Startup."));
+
+ /* Optionally pre-allocate a large block of memory for testing */
+#if defined(MEMORY_STRESS_TEST)
+ Serial.println(F("WARNING: Memory Stress Test Active!"));
+ Serial.print(F("Allocating extra memory: "));
+ Serial.print(MEMORY_STRESS_INITIAL);
+ Serial.println(F(" bytes..."));
+ memory_stress[mem_ctr] = (char*)malloc(MEMORY_STRESS_INITIAL);
+ show_memory();
+#endif
+
+ setup_hardware();
+
+ setup_network();
+
+ setup_datetime();
+
+ setup_wolfssl();
+
+ setup_certificates();
+
+#if defined THIS_USER_SETTINGS_VERSION
+ Serial.print(F("This user_settings.h version:"))
+ Serial.println(THIS_USER_SETTINGS_VERSION)
+#endif
+
+ Serial.println(F("Completed Arduino setup!"));
+ /* See companion wolfssl_server_dtls.ino code; server begins listening here
+ * https://github.com/wolfSSL/wolfssl-examples/tree/master/Arduino/sketches/wolfssl_server_dtls
+ * Any other DTLS server will work. See also:
+ * https://github.com/wolfSSL/wolfssl/tree/master/examples/client
+ */
+ return;
+} /* Arduino setup */
+
+/*****************************************************************************/
+/* wolfSSL error_check() */
+/*****************************************************************************/
+int error_check(int this_ret, bool halt_on_error,
+ const __FlashStringHelper* message) {
+ int ret = 0;
+ if (this_ret == WOLFSSL_SUCCESS) {
+ Serial.print(F("Success: "));
+ Serial.println(message);
+ }
+ else {
+ Serial.print(F("ERROR: return = "));
+ Serial.print(this_ret);
+ Serial.print(F(": "));
+ Serial.println(message);
+ Serial.println(wc_GetErrorString(this_ret));
+ if (halt_on_error) {
+ fail_wait();
+ }
+ }
+ show_memory();
+
+ return ret;
+} /* error_check */
+
+/*****************************************************************************/
+/* wolfSSL error_check_ssl */
+/* Parameters: */
+/* ssl is the current WOLFSSL object pointer */
+/* halt_on_error set to true to suspend operations for critical error */
+/* message is expected to be a memory-efficient F("") macro string */
+/*****************************************************************************/
+int error_check_ssl(WOLFSSL* ssl, int this_ret, bool halt_on_error,
+ const __FlashStringHelper* message) {
+ int err = 0;
+
+ if (ssl == NULL) {
+ Serial.println(F("ssl is Null; Unable to allocate SSL object?"));
+#ifndef DEBUG_WOLFSSL
+ Serial.println(F("Define DEBUG_WOLFSSL in user_settings.h for more."));
+#else
+ Serial.println(F("See wolfssl/wolfcrypt/error-crypt.h for codes."));
+#endif
+ Serial.print(F("ERROR: "));
+ Serial.println(message);
+ show_memory();
+ if (halt_on_error) {
+ fail_wait();
+ }
+ }
+ else {
+ err = wolfSSL_get_error(ssl, this_ret);
+ if (err == WOLFSSL_SUCCESS) {
+ Serial.print(F("Success m: "));
+ Serial.println(message);
+ }
+ else {
+ if (err < 0) {
+ wolfSSL_ERR_error_string(err, errBuf);
+ Serial.print(F("WOLFSSL Error: "));
+ Serial.print(err);
+ Serial.print(F("; "));
+ Serial.println(errBuf);
+ }
+ else {
+ Serial.println(F("Success: ssl object."));
+ }
+ }
+ }
+
+ return err;
+} /* error_check_ssl */
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino loop() */
+/*****************************************************************************/
+/*****************************************************************************/
+void loop()
+{
+ /* standard variables used in a dtls client */
+ char sendLine[MAXLINE] = "Hello DTLS wolfSSL!";
+ char recvLine[MAXLINE - 1];
+ struct sockaddr_in servAddr;
+ const char* cipherName;
+ int msg_ct = 0;
+ int n = 0;
+ int sockfd = INVALID_SOCKET;
+ int err;
+ int ret;
+ int exitVal = 1;
+
+ /* Assign ssl variable */
+ ssl = wolfSSL_new(ctx);
+ if (ssl == NULL) {
+ Serial.println(F("unable to get ssl object\n"));
+ goto cleanup;
+ }
+
+ /* servAddr setup */
+ memset(&servAddr, 0, sizeof(servAddr));
+ servAddr.sin_family = AF_INET;
+ servAddr.sin_port = htons(WOLFSSL_PORT);
+ if (inet_pton(AF_INET, WOLFSSL_DTLS_SERVER_HOST, &servAddr.sin_addr) < 1) {
+ perror("inet_pton()");
+ goto cleanup;
+ }
+
+ if (wolfSSL_dtls_set_peer(ssl, &servAddr, sizeof(servAddr))
+ != WOLFSSL_SUCCESS) {
+ Serial.println(F("wolfSSL_dtls_set_peer failed\n"));
+ goto cleanup;
+ }
+
+ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ perror("socket()");
+ goto cleanup;
+ }
+
+ /* Set the file descriptor for ssl */
+ if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) {
+ Serial.println(F("cannot set socket file descriptor\n"));
+ goto cleanup;
+ }
+
+ Serial.print(F("Connecting to wolfSSL DTLS Secure Server..."));
+ do {
+ reconnect--;
+ err = 0; /* reset error */
+ Serial.println(F("wolfSSL_connect ..."));
+ ret = wolfSSL_connect(ssl);
+ if ((ret != WOLFSSL_SUCCESS) && (ret != WC_PENDING_E)) {
+ Serial.println(F("Failed connection, checking error."));
+ err = error_check_ssl(ssl, ret, true,
+ F("Create WOLFSSL object from ctx"));
+ Serial.print("err =");
+ Serial.println(err);
+ }
+ else {
+ Serial.print(PROGRESS_DOT);
+ }
+ } while ((err == WC_PENDING_E) && (reconnect > 0));
+
+ Serial.println();
+ Serial.println(F("Connected!"));
+ Serial.print(F("SSL version is "));
+ Serial.println(wolfSSL_get_version(ssl));
+
+ cipherName = wolfSSL_get_cipher(ssl);
+ Serial.print(F("SSL cipher suite is "));
+ Serial.println(cipherName);
+
+/*****************************************************************************/
+/* Code for sending datagram to server */
+/*****************************************************************************/
+ Serial.println(F("Begin DTLS Loop..."));
+ msg_ct = 0;
+ while (msg_ct < DTLS_MESSAGE_CT || (DTLS_MESSAGE_CT == -1)) {
+ msg_ct++;
+
+ /* Send sendLine to the server */
+ Serial.print(F("Sending Message #"));
+ Serial.print(msg_ct);
+ Serial.print(F(": \""));
+ Serial.print(F(sendLine));
+ Serial.println(F("\" ... "));
+ if (wolfSSL_write(ssl, sendLine, strlen(sendLine)) != strlen(sendLine)) {
+ err = error_check_ssl(ssl, ret, true,
+ F("Create WOLFSSL object from ctx"));
+ Serial.print("err =");
+ Serial.println(err);
+ goto cleanup;
+ }
+
+ /* n is the # of bytes received */
+ Serial.println(F("Reading Message..."));
+ n = wolfSSL_read(ssl, recvLine, sizeof(recvLine)-1);
+
+ if (n > 0) {
+ /* Add a terminating character to the generic server message */
+ recvLine[n] = '\0';
+ Serial.println(F("Got Message..."));
+ printf("%s\n", recvLine);
+ }
+ else {
+ err = error_check_ssl(ssl, ret, true,
+ F("Create WOLFSSL object from ctx"));
+ Serial.print("err =");
+ Serial.println(err);
+ goto cleanup;
+ }
+
+ } /* (msg_ct > DTLS_MESSAGE_CT || (DTLS_MESSAGE_CT == -1)) */
+
+ exitVal = 0;
+cleanup:
+ if (ssl != NULL) {
+ /* Attempt a full shutdown */
+ ret = wolfSSL_shutdown(ssl);
+ if (ret == WOLFSSL_SHUTDOWN_NOT_DONE) {
+ Serial.println("Not done... Try again wolfSSL_shutdown");
+ ret = wolfSSL_shutdown(ssl);
+ }
+
+ if (ret != WOLFSSL_SUCCESS) {
+ err = error_check_ssl(ssl, ret, true,
+ F("Create WOLFSSL object from ctx"));
+ Serial.print("err =");
+ Serial.println(err);
+ Serial.println(F("wolfSSL_shutdown failed\n"));
+ }
+ wolfSSL_free(ssl);
+ }
+ if (sockfd != INVALID_SOCKET) {
+ close(sockfd);
+ }
+ if (ctx != NULL) {
+ wolfSSL_CTX_free(ctx);
+ }
+ wolfSSL_Cleanup();
+
+ Serial.print(F("Reset to start over."));
+ Serial.print(F("Done!"));
+
+ while (1) {
+ delay(1000);
+ }
+} /* Arduino loop */
+
diff --git a/examples/wolfssl_server/README.md b/examples/wolfssl_server/README.md
index 523eb08..e961d71 100644
--- a/examples/wolfssl_server/README.md
+++ b/examples/wolfssl_server/README.md
@@ -2,6 +2,12 @@
Open the [wolfssl_server.ino](./wolfssl_server.ino) file in the Arduino IDE.
+If using WiFi, be sure to set `ssid` and `password` values.
+
+May need "Ethernet by Various" library to be installed. Tested with v2.0.2 and v2.8.1.
+
+See the `#define WOLFSSL_TLS_SERVER_HOST` to set your own server address.
+
Other IDE products are also supported, such as:
- [PlatformIO in VS Code](https://docs.platformio.org/en/latest/frameworks/arduino.html)
@@ -13,7 +19,7 @@ Additional examples can be found on [wolfSSL/wolfssl-examples](https://github.co
## Connect with an Arduino Sketch
-See the companion [Arduino Sketch Client](../wolfssl_client/wolfssl_client.ino).
+See the companion [Arduino Sketch Client](../wolfssl_client/wolfssl_client.ino).
## Connect with Linux Client
@@ -35,7 +41,7 @@ press the reset button or power cycle the Arduino before making a connection.
Here's one possible script to test the server from a command-line client:
```bash
-#!/bin/bash
+#!/usr/bin/env bash
echo "client log " > client_log.txt
counter=1
THIS_ERR=0
diff --git a/examples/wolfssl_server/wolfssl_server.ino b/examples/wolfssl_server/wolfssl_server.ino
index 7471362..7f75bcc 100644
--- a/examples/wolfssl_server/wolfssl_server.ino
+++ b/examples/wolfssl_server/wolfssl_server.ino
@@ -1,12 +1,12 @@
/* wolfssl_server.ino
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -37,7 +37,19 @@ Tested with:
*/
/* If you have a private include, define it here, otherwise edit WiFi params */
-#define MY_PRIVATE_CONFIG "/workspace/my_private_config.h"
+/* #define MY_PRIVATE_CONFIG "/workspace/my_private_config.h" */
+
+#if defined(ARDUINO) && defined(ESP8266)
+ #warning "This example is not yet supported on Arduino ESP8266"
+#endif
+
+#if defined(DEBUG_WOLFSSL)
+ /* Optionally enabled verbose wolfSSL debugging */
+ #define DEBUG_WOLFSSL_MESSAGES_ON
+#else
+ /* DEBUG_WOLFSSL needs to be enabled */
+ #undef DEBUG_WOLFSSL_MESSAGES_ON
+#endif
/* set REPEAT_CONNECTION to a non-zero value to continually run the example. */
#define REPEAT_CONNECTION 1
@@ -68,12 +80,12 @@ Tested with:
/* the /workspace directory may contain a private config
* excluded from GitHub with items such as WiFi passwords */
#include MY_PRIVATE_CONFIG
- const char* ssid PROGMEM = CONFIG_ESP_WIFI_SSID;
- const char* password PROGMEM = CONFIG_ESP_WIFI_PASSWORD;
+ static const char ssid[] PROGMEM = MY_ARDUINO_WIFI_SSID;
+ static const char password[] PROGMEM = MY_ARDUINO_WIFI_PASSWORD;
#else
/* when using WiFi capable boards: */
- const char* ssid PROGMEM = "your_SSID";
- const char* password PROGMEM = "your_PASSWORD";
+ static const char ssid[] PROGMEM = "your_SSID";
+ static const char password[] PROGMEM = "your_PASSWORD";
#endif
#define BROADCAST_ADDRESS "255.255.255.255"
@@ -85,6 +97,15 @@ Tested with:
#include
#endif
+/* wolfSSL user_settings.h must be included from settings.h
+ * Make all configurations changes in user_settings.h
+ * Do not edit wolfSSL `settings.h` or `config.h` files.
+ * Do not explicitly include user_settings.h in any source code.
+ * Each Arduino sketch that uses wolfSSL must have: #include "wolfssl.h"
+ * C/C++ source files can use: #include
+ * The wolfSSL "settings.h" must be included in each source file using wolfSSL.
+ * The wolfSSL "settings.h" must appear before any other wolfSSL include.
+ */
#include
/* Important: make sure settings.h appears before any other wolfSSL headers */
#include
@@ -123,6 +144,10 @@ Tested with:
#elif defined(ESP8266)
#define USING_WIFI
#include
+ /* Ensure the F() flash macro is defined */
+ #ifndef F
+ #define F
+ #endif
WiFiClient client;
WiFiServer server(WOLFSSL_PORT);
#elif defined(ARDUINO_SAM_DUE)
@@ -131,11 +156,16 @@ Tested with:
/* Needs "Ethernet by Various" library to be installed. Tested with V2.0.2 */
#include
EthernetClient client;
- EthernetClient server(WOLFSSL_PORT);
+ EthernetServer server(WOLFSSL_PORT);
+#elif defined(ARDUINO_AVR_ETHERNET) || defined(ARDUINO_AVR_LEONARDO_ETH)
+ /* Boards such as arduino:avr:ethernet and arduino:avr:leonardoeth */
+ #include
+ EthernetClient client;
+ EthernetServer server(WOLFSSL_PORT);
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
#define USING_WIFI
#include
- #include
+ #include /* Needs Arduino WiFiNINA library installed manually */
WiFiClient client;
WiFiServer server(WOLFSSL_PORT);
#elif defined(ARDUINO_ARCH_RP2040)
@@ -144,6 +174,36 @@ Tested with:
#include
WiFiClient client;
WiFiServer server(WOLFSSL_PORT);
+#elif defined(ARDUINO_SAMD_TIAN)
+ #include
+ #include
+ HttpClient client;
+ /* Arduino Tian does not support network shields like the standard Ethernet or Wi-Fi shields. */
+ #error "HttpClient cannot be used for this example"
+#elif defined(ARDUINO_PORTENTA_X8)
+ /* The Portenta is a Linux device. See wolfSSL examples:
+ * https://github.com/wolfSSL/wolfssl/tree/master/examples
+ * By default Serial is disabled and mapped to ErrorSerial */
+ #include
+
+ /* ----No - network placeholders(compile - only) ---- */
+ #include
+ struct X8NoNetClient {
+ int write(const uint8_t*, size_t) { return -1; }
+ int available() { return 0; }
+ int read() { return -1; }
+ void stop() {}
+ bool connected() { return false; }
+ IPAddress remoteIP() { return IPAddress(0, 0, 0, 0); }
+ };
+ struct X8NoNetServer {
+ explicit X8NoNetServer(uint16_t) {}
+ void begin() {}
+ X8NoNetClient available() { return X8NoNetClient(); }
+ };
+
+ X8NoNetClient client;
+ X8NoNetServer server(WOLFSSL_PORT);
#elif defined(USING_WIFI)
#define USING_WIFI
#include
@@ -157,6 +217,8 @@ Tested with:
#elif defined(OTHER_BOARD)
*/
#else
+ /* assume all other boards using WiFi library. Edit as needed: */
+ #include
#define USING_WIFI
WiFiClient client;
WiFiServer server(WOLFSSL_PORT);
@@ -178,32 +240,34 @@ Tested with:
/* we expect our IP address from DHCP */
-const int serial_baud = SERIAL_BAUD; /* local serial port to monitor */
-WOLFSSL_CTX* ctx = NULL;
-WOLFSSL* ssl = NULL;
-char* wc_error_message = (char*)malloc(80 + 1);
-char errBuf[80];
+static WOLFSSL_CTX* ctx = NULL;
+static WOLFSSL* ssl = NULL;
+static char* wc_error_message = (char*)malloc(80 + 1);
+static char errBuf[80];
#if defined(MEMORY_STRESS_TEST)
#define MEMORY_STRESS_ITERATIONS 100
#define MEMORY_STRESS_BLOCK_SIZE 1024
#define MEMORY_STRESS_INITIAL (4*1024)
- char* memory_stress[MEMORY_STRESS_ITERATIONS]; /* typically 1K per item */
- int mem_ctr = 0;
+ static char* memory_stress[MEMORY_STRESS_ITERATIONS]; /* typically 1K per item */
+ static int mem_ctr = 0;
#endif
static int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx);
static int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx);
static int reconnect = RECONNECT_ATTEMPTS;
+#if 0
+/* optional showPeerEx, currently disabled */
static int lng_index PROGMEM = 0; /* 0 = English */
+#endif
#if defined(__arm__)
#include
extern char _end;
extern "C" char *sbrk(int i);
- char *ramstart=(char *)0x20070000;
- char *ramend=(char *)0x20088000;
+ static char *ramstart=(char *)0x20070000;
+ static char *ramend=(char *)0x20088000;
#endif
/*****************************************************************************/
@@ -372,28 +436,31 @@ int setup_network(void) {
#if defined(USING_WIFI)
int status = WL_IDLE_STATUS;
- if (WiFi.status() == WL_NO_MODULE) {
- Serial.println("Communication with WiFi module failed!");
- /* don't continue if no network */
- while (true) ;
- }
-
- String fv = WiFi.firmwareVersion();
- if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
- Serial.println("Please upgrade the firmware");
- }
-
/* The ESP8266 & ESP32 support both AP and STA. We'll use STA: */
#if defined(ESP8266) || defined(ESP32)
WiFi.mode(WIFI_STA);
+ #else
+ String fv;
+ if (WiFi.status() == WL_NO_MODULE) {
+ Serial.println("Communication with WiFi module failed!");
+ /* don't continue if no network */
+ while (true) ;
+ }
+
+ fv = WiFi.firmwareVersion();
+ if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
+ Serial.println("Please upgrade the firmware");
+ }
#endif
Serial.print(F("Connecting to WiFi "));
Serial.print(ssid);
+ status = WiFi.begin(ssid, password);
while (status != WL_CONNECTED) {
- status = WiFi.begin(ssid, password);
- delay(5000);
+ delay(1000);
Serial.print(F("."));
+ Serial.print(status);
+ status = WiFi.status();
}
Serial.println(F(" Connected!"));
@@ -450,7 +517,8 @@ int setup_network(void) {
/*****************************************************************************/
/* Arduino setup_wolfssl() */
/*****************************************************************************/
-int setup_wolfssl(void) {
+int setup_wolfssl(void)
+{
int ret = 0;
WOLFSSL_METHOD* method;
@@ -470,8 +538,14 @@ int setup_wolfssl(void) {
#endif
#if defined(DEBUG_WOLFSSL)
- wolfSSL_Debugging_ON();
- Serial.println(F("wolfSSL Debugging is On!"));
+ Serial.println(F("wolfSSL Debugging is available! (DEBUG_WOLFSSL)"));
+ #if defined(DEBUG_WOLFSSL_MESSAGES_ON)
+ Serial.println(F("Enabling verbose messages wolfSSL_Debugging_ON"));
+ wolfSSL_Debugging_ON();
+ #else
+ Serial.println(F("Enable verbose messages with wolfSSL_Debugging_ON"));
+ Serial.println(F("or define DEBUG_WOLFSSL_MESSAGES_ON"));
+ #endif
#else
Serial.println(F("wolfSSL Debugging is Off! (enable with DEBUG_WOLFSSL)"));
#endif
@@ -497,6 +571,7 @@ int setup_wolfssl(void) {
* It is best on embedded devices to choose a TLS session cache size. */
#endif
+ /* Initialize wolfSSL before assigning ctx */
ret = wolfSSL_Init();
if (ret == WOLFSSL_SUCCESS) {
Serial.println("Successfully called wolfSSL_Init");
@@ -531,7 +606,8 @@ int setup_wolfssl(void) {
/*****************************************************************************/
/* Arduino setup_certificates() */
/*****************************************************************************/
-int setup_certificates(void) {
+int setup_certificates(void)
+{
int ret = 0;
Serial.println(F("Initializing certificates..."));
@@ -581,10 +657,14 @@ int setup_certificates(void) {
/* Arduino setup() */
/*****************************************************************************/
/*****************************************************************************/
-void setup(void) {
+void setup(void)
+{
+ int i = 0;
Serial.begin(SERIAL_BAUD);
- while (!Serial) {
+ while (!Serial && (i < 10)) {
/* wait for serial port to connect. Needed for native USB port only */
+ delay(1000);
+ i++;
}
Serial.println(F(""));
@@ -608,10 +688,10 @@ void setup(void) {
setup_hardware();
- setup_datetime();
-
setup_network();
+ setup_datetime();
+
setup_wolfssl();
setup_certificates();
@@ -709,7 +789,7 @@ int error_check_ssl(WOLFSSL* ssl, int this_ret, bool halt_on_error,
}
return err;
-}
+} /* error_check_ssl */
/*****************************************************************************/
/*****************************************************************************/
diff --git a/examples/wolfssl_server_dtls/README.md b/examples/wolfssl_server_dtls/README.md
new file mode 100644
index 0000000..43deb7e
--- /dev/null
+++ b/examples/wolfssl_server_dtls/README.md
@@ -0,0 +1,140 @@
+# Arduino Basic TLS Server
+
+Open the [wolfssl_server_dtls.ino](./wolfssl_server_dtls.ino) file in the Arduino IDE.
+
+If using WiFi, be sure to set `ssid` and `password` values.
+
+May need "Ethernet by Various" library to be installed. Tested with v2.0.2 and v2.8.1.
+
+See the `#define WOLFSSL_TLS_SERVER_HOST` to set your own server address.
+
+Other IDE products are also supported, such as:
+
+- [PlatformIO in VS Code](https://docs.platformio.org/en/latest/frameworks/arduino.html)
+- [VisualGDB](https://visualgdb.com/tutorials/arduino/)
+- [VisualMicro](https://www.visualmicro.com/)
+
+For examples on other platforms, see the [IDE directory](https://github.com/wolfssl/wolfssl/tree/master/IDE).
+Additional examples can be found on [wolfSSL/wolfssl-examples](https://github.com/wolfSSL/wolfssl-examples/).
+
+## Connect with an Arduino Sketch
+
+See the companion [Arduino Sketch Client](../wolfssl_client/wolfssl_client_dtls.ino).
+
+## Connect with Linux Client
+
+See also the [wolfSSL Example TLS Client](https://github.com/wolfSSL/wolfssl/tree/master/examples/client)
+and [wolfSSL Example TLS Server](https://github.com/wolfSSL/wolfssl/tree/master/examples/server).
+
+Assuming a listening [Arduino Sketch Server](./wolfssl_server.ino) at `192.168.1.38` on port `11111`,
+connect with the `client` executable:
+
+```
+./examples/client/client -h 192.168.1.38 -p 11111 -v 3
+```
+
+## wolfSSL Error -308 wolfSSL_connect error state on socket
+
+When using a wired Ethernet connection, and this error is encountered, simply
+press the reset button or power cycle the Arduino before making a connection.
+
+Here's one possible script to test the server from a command-line client:
+
+```bash
+#!/usr/bin/env bash
+echo "client log " > client_log.txt
+counter=1
+THIS_ERR=0
+while [ $THIS_ERR -eq 0 ]; do
+ ./examples/client/client -h 192.168.1.38 -p 11111 -v 3 >> client_log.txt
+
+ THIS_ERR=$?
+ if [ $? -ne 0 ]; then
+ echo "Failed!"
+ exit 1
+ fi
+ echo "Iteration $counter"
+ echo "Iteration $counter" >> client_log.txt
+ ((counter++))
+done
+```
+
+Output expected from the `client` command:
+
+```
+$ ./examples/client/client -h 192.168.1.38 -p 11111 -v 3
+Alternate cert chain used
+ issuer : /C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com
+ subject: /C=US/ST=Montana/L=Bozeman/O=wolfSSL/OU=Support/CN=www.wolfssl.com/emailAddress=info@wolfssl.com
+ altname = example.com
+ altname = 127.0.0.1
+ serial number:01
+SSL version is TLSv1.2
+SSL cipher suite is ECDHE-RSA-AES128-GCM-SHA256
+SSL curve name is SECP256R1
+---
+Server certificate
+-----BEGIN CERTIFICATE-----
+MIIE6DCCA9CgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh
+d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz
+bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjMxMjEz
+MjIxOTI4WhcNMjYwOTA4MjIxOTI4WjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM
+B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxEDAO
+BgNVBAsMB1N1cHBvcnQxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG
+SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAMCVCOFXQfJxbbfSRUEnAWXGRa7yvCQwuJXOL07W9hyIvHyf+6hn
+f/5cnFF194rKB+c1L4/hvXvAL3yrZKgX/Mpde7rgIeVyLm8uhtiVc9qsG1O5Xz/X
+GQ0lT+FjY1GLC2Q/rUO4pRxcNLOuAKBjxfZ/C1loeHOmjBipAm2vwxkBLrgQ48bM
+QLRpo0YzaYduxLsXpvPo3a1zvHsvIbX9ZlEMvVSz4W1fHLwjc9EJA4kU0hC5ZMMq
+0KGWSrzh1Bpbx6DAwWN4D0Q3MDKWgDIjlaF3uhPSl3PiXSXJag3DOWCktLBpQkIJ
+6dgIvDMgs1gip6rrxOHmYYPF0pbf2dBPrdcCAwEAAaOCAUUwggFBMB0GA1UdDgQW
+BBSzETLJkpiE4sn40DtuA0LKHw6OPDCB1AYDVR0jBIHMMIHJgBQnjmcRdMMmHT/t
+M2OzpNgdMOXo1aGBmqSBlzCBlDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRh
+bmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQL
+DApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG
+9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CFDNEGqhsAez2YPJwUQpM0RT6vOlEMAwG
+A1UdEwQFMAMBAf8wHAYDVR0RBBUwE4ILZXhhbXBsZS5jb22HBH8AAAEwHQYDVR0l
+BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBK/7nl
+hZvaU2Z/ByK/thnqQuukEQdi/zlfMzc6hyZxPROyyrhkOHuKmUgOpaRrsZlu4EZR
+vRlSrbymfip6fCOnzNteQ31rBMi33ZWt8JGAWcUZkSYnkbhIHOtVtqp9pDjxA7xs
+i6qU1jwFepbFBvEmFC51+93lNbMBLLOtYlohmgi+Vvz5okKHhuWpxZnPrhS+4LkI
+JA0dXNYU4UyfQLOp6S1Si0y/rEQxZ8GNBoXsD+SZ10t7IQZm1OT1nf+O8IY5WB2k
+W+Jj73zJGIeoAiUQPoco+fXvR56lgAgRkGj+0aOoUbk3/9XKfId/a7wsEsjFhYv8
+DMa5hrjJBMNRN9JP
+-----END CERTIFICATE-----
+Session timeout set to 500 seconds
+Client Random : 56A0BB9647B064D3F20947032B74B31FDB4C93DBAC9460BA8AEA213A2B2DD4A8
+SSL-Session:
+ Protocol : TLSv1.2
+ Cipher : TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ Session-ID: 3255404E997FA9C27ECB4F1A20A70E722E4AA504B63A945FC175434D1907EC31
+ Session-ID-ctx:
+ Master-Key: 67F22168BBADD678643BBA76B398277270C29788AC18FD05B57F6B715F49A7BCEEF75BEAF7FE266B0CC058534AF76C1F
+ TLS session ticket: NONE
+ Start Time: 1705533296
+ Timeout : 500 (sec)
+ Extended master secret: no
+I hear you fa shizzle!
+```
+
+### Troubleshooting
+
+When encountering odd errors such as `undefined reference to ``_impure_ptr'`, such as this:
+
+```text
+c:/users/gojimmypi/appdata/local/arduino15/packages/esp32/tools/xtensa-esp32-elf-gcc/esp-2021r2-patch5-8.4.0/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: C:\Users\gojimmypi\AppData\Local\Temp\arduino\sketches\EAB8D79A02D1ECF107884802D893914E\libraries\wolfSSL\wolfcrypt\src\logging.c.o:(.literal.wolfssl_log+0x8): undefined reference to `_impure_ptr'
+collect2.exe: error: ld returned 1 exit status
+
+exit status 1
+
+Compilation error: exit status 1
+```
+
+Try cleaning the Arduino cache directories. For Windows, that's typically in:
+
+```text
+C:\Users\%USERNAME%\AppData\Local\Temp\arduino\sketches
+```
+
+Remove all other boards from other serial ports, leaving one the one being programmed.
diff --git a/examples/wolfssl_server_dtls/wolfssl_server_dtls.ino b/examples/wolfssl_server_dtls/wolfssl_server_dtls.ino
new file mode 100644
index 0000000..38e9148
--- /dev/null
+++ b/examples/wolfssl_server_dtls/wolfssl_server_dtls.ino
@@ -0,0 +1,984 @@
+/* server-dtls13.c
+ *
+ * Copyright (C) 2006-2025 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 3 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
+ *
+ *=============================================================================
+ *
+ * Bare-bones example of a DTLS 1.3 server for instructional/learning purposes.
+ * This example can only accept one connection at a time.
+ *
+ * Define USE_DTLS12 to use DTLS 1.2 instead of DTLS 1.3
+/*
+Tested with:
+
+1) Intel Galileo acting as the Client, with a laptop acting as a server using
+ the server example provided in examples/server.
+ Legacy Arduino v1.86 was used to compile and program the Galileo
+
+2) Espressif ESP32 WiFi
+
+3) Arduino Due, Nano33 IoT, Nano RP-2040
+*/
+
+/*
+ * Note to code editors: the Arduino client and server examples are edited in
+ * parallel for side-by-side comparison between examples.
+ */
+
+/* If you have a private include, define it here, otherwise edit WiFi params */
+/* #define MY_PRIVATE_CONFIG "/workspace/my_private_config.h" */
+
+#if defined(ARDUINO) && defined(ESP8266)
+ #warning "This example is not yet supported on Arduino ESP8266"
+#endif
+
+#if defined(DEBUG_WOLFSSL)
+ /* Optionally enabled verbose wolfSSL debugging */
+ #define DEBUG_WOLFSSL_MESSAGES_ON
+#else
+ /* DEBUG_WOLFSSL needs to be enabled */
+ #undef DEBUG_WOLFSSL_MESSAGES_ON
+#endif
+
+/* set REPEAT_CONNECTION to a non-zero value to continually run the example. */
+#define REPEAT_CONNECTION 0
+
+/* Edit this with your other TLS host server address to connect to: */
+/* #define WOLFSSL_TLS_SERVER_HOST "192.168.1.39" */
+
+/* wolfssl TLS examples communicate on port 11111 */
+#define WOLFSSL_PORT 11111
+
+/* Choose a monitor serial baud rate: 9600, 14400, 19200, 57600, 74880, etc. */
+#define SERIAL_BAUD 115200
+
+/* We'll wait up to 2000 milliseconds to properly shut down connection */
+#define SHUTDOWN_DELAY_MS 2000
+
+/* Number of times to retry connection. */
+#define RECONNECT_ATTEMPTS 20
+
+/* Assume bad socket until proven otherwise */
+#define INVALID_SOCKET -1
+
+/* Maximum size in bytes of buffer to send and receive */
+#define MAXLINE 128
+
+/* Optional stress test. Define to consume memory until exhausted: */
+/* #define MEMORY_STRESS_TEST */
+
+/* Choose client or server example, not both. */
+/* #define WOLFSSL_CLIENT_EXAMPLE */
+#define WOLFSSL_SERVER_EXAMPLE
+
+#if defined(MY_PRIVATE_CONFIG)
+ /* the /workspace directory may contain a private config
+ * excluded from GitHub with items such as WiFi passwords */
+ #include MY_PRIVATE_CONFIG
+ static const char ssid[] PROGMEM = MY_ARDUINO_WIFI_SSID;
+ static const char password[] PROGMEM = MY_ARDUINO_WIFI_PASSWORD;
+#else
+ /* when using WiFi capable boards: */
+ static const char ssid[] PROGMEM = "your_SSID";
+ static const char password[] PROGMEM = "your_PASSWORD";
+#endif
+
+#define BROADCAST_ADDRESS "255.255.255.255"
+
+/* There's an optional 3rd party NTPClient library by Fabrice Weinberg.
+ * If it is installed, uncomment define USE_NTP_LIB here: */
+/* #define USE_NTP_LIB */
+#ifdef USE_NTP_LIB
+ #include
+#endif
+
+/* wolfSSL user_settings.h must be included from settings.h
+ * Make all configurations changes in user_settings.h
+ * Do not edit wolfSSL `settings.h` or `config.h` files.
+ * Do not explicitly include user_settings.h in any source code.
+ * Each Arduino sketch that uses wolfSSL must have: #include "wolfssl.h"
+ * C/C++ source files can use: #include
+ * The wolfSSL "settings.h" must be included in each source file using wolfSSL.
+ * The wolfSSL "settings.h" must appear before any other wolfSSL include.
+ */
+#include
+/* Important: make sure settings.h appears before any other wolfSSL headers */
+#include
+/* Reminder: settings.h includes user_settings.h
+ * For ALL project wolfSSL settings, see:
+ * [your path]/Arduino\libraries\wolfSSL\src\user_settings.h */
+#include
+#include
+#include
+
+#ifndef WOLFSSL_DTLS
+ /* Support for DTLS by default was added after wolfSSL v5.8.2 release */
+ #error "This example requires WOLFSSL_DTLS. See user_settings.h in the Arduino wolfssl library"
+#endif
+
+/* Define DEBUG_WOLFSSL in user_settings.h for more verbose logging. */
+#if defined(DEBUG_WOLFSSL)
+ #define PROGRESS_DOT F("")
+#else
+ #define PROGRESS_DOT F(".")
+#endif
+
+/* Convert a macro to a string */
+#define xstr(x) str(x)
+#define str(x) #x
+
+/* optional board-specific networking includes */
+#if defined(ESP32)
+ #define USING_WIFI
+ #include
+ #include
+ #ifdef USE_NTP_LIB
+ WiFiUDP ntpUDP;
+ #endif
+ /* Ensure the F() flash macro is defined */
+ #ifndef F
+ #define F
+ #endif
+ WiFiClient client;
+ WiFiServer server(WOLFSSL_PORT);
+#elif defined(ESP8266)
+ #define USING_WIFI
+ #include
+ /* Ensure the F() flash macro is defined */
+ #ifndef F
+ #define F
+ #endif
+ WiFiClient client;
+ WiFiServer server(WOLFSSL_PORT);
+#elif defined(ARDUINO_SAM_DUE)
+ #include
+ /* There's no WiFi/Ethernet on the Due. Requires Ethernet Shield.
+ /* Needs "Ethernet by Various" library to be installed. Tested with V2.0.2 */
+ #include
+ EthernetClient client;
+ EthernetClient server(WOLFSSL_PORT);
+#elif defined(ARDUINO_AVR_ETHERNET) || defined(ARDUINO_AVR_LEONARDO_ETH)
+ /* Boards such as arduino:avr:ethernet and arduino:avr:leonardoeth */
+ #include
+ EthernetClient client;
+
+ EthernetClient server(WOLFSSL_PORT);
+#elif defined(ARDUINO_SAMD_NANO_33_IOT)
+ #define USING_WIFI
+ #include
+ #include /* Needs Arduino WiFiNINA library installed manually */
+ WiFiClient client;
+ WiFiServer server(WOLFSSL_PORT);
+#elif defined(ARDUINO_ARCH_RP2040)
+ #define USING_WIFI
+ #include
+ #include
+ WiFiClient client;
+ WiFiServer server(WOLFSSL_PORT);
+#elif defined(ARDUINO_SAMD_TIAN)
+ #include
+ #include
+ HttpClient client;
+ /* Arduino Tian does not support network shields like the standard Ethernet or Wi-Fi shields. */
+ #error "HttpClient cannot be used for this example"
+#elif defined(ARDUINO_PORTENTA_X8)
+ /* The Portenta is a Linux device. See wolfSSL examples:
+ * https://github.com/wolfSSL/wolfssl/tree/master/examples
+ * By default Serial is disabled and mapped to ErrorSerial */
+ #include
+
+ /* ----No - network placeholders(compile - only) ---- */
+ #include
+ struct X8NoNetClient {
+ int write(const uint8_t*, size_t) { return -1; }
+ int available() { return 0; }
+ int read() { return -1; }
+ void stop() {}
+ bool connected() { return false; }
+ IPAddress remoteIP() { return IPAddress(0, 0, 0, 0); }
+ };
+ struct X8NoNetServer {
+ explicit X8NoNetServer(uint16_t) {}
+ void begin() {}
+ X8NoNetClient available() { return X8NoNetClient(); }
+ };
+
+ X8NoNetClient client;
+ X8NoNetServer server(WOLFSSL_PORT);
+#elif defined(USING_WIFI)
+ #define USING_WIFI
+ #include
+ #include
+ #ifdef USE_NTP_LIB
+ WiFiUDP ntpUDP;
+ #endif
+ WiFiClient client;
+ WiFiServer server(WOLFSSL_PORT);
+/* TODO
+#elif defined(OTHER_BOARD)
+*/
+#else
+ /* assume all other boards using WiFi library. Edit as needed: */
+ #include
+ #define USING_WIFI
+ WiFiClient client;
+ WiFiServer server(WOLFSSL_PORT);
+#endif
+
+/* Only for syntax highlighters to show interesting options enabled: */
+#if defined(HAVE_SNI) \
+ || defined(HAVE_MAX_FRAGMENT) \
+ || defined(HAVE_TRUSTED_CA) \
+ || defined(HAVE_TRUNCATED_HMAC) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \
+ || defined(HAVE_SUPPORTED_CURVES) \
+ || defined(HAVE_ALPN) \
+ || defined(HAVE_SESSION_TICKET) \
+ || defined(HAVE_SECURE_RENEGOTIATION) \
+ || defined(HAVE_SERVER_RENEGOTIATION_INFO)
+#endif
+
+static const int port PROGMEM = WOLFSSL_PORT; /* port on server to connect to */
+
+static WOLFSSL_CTX* ctx = NULL;
+static WOLFSSL* ssl = NULL;
+static char* wc_error_message = (char*)malloc(80 + 1);
+static char errBuf[80];
+
+#if defined(MEMORY_STRESS_TEST)
+ #define MEMORY_STRESS_ITERATIONS 100
+ #define MEMORY_STRESS_BLOCK_SIZE 1024
+ #define MEMORY_STRESS_INITIAL (4*1024)
+ static char* memory_stress[MEMORY_STRESS_ITERATIONS]; /* typically 1K per item */
+ static int mem_ctr = 0;
+#endif
+
+static int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx);
+static int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx);
+static int reconnect = RECONNECT_ATTEMPTS;
+#if 0
+/* optional showPeerEx, currently disabled */
+static int lng_index PROGMEM = 0; /* 0 = English */
+#endif
+static int listenfd = INVALID_SOCKET; /* Initialize our socket */
+
+#if defined(__arm__)
+ #include
+ extern char _end;
+ extern "C" char *sbrk(int i);
+ static char *ramstart=(char *)0x20070000;
+ static char *ramend=(char *)0x20088000;
+#endif
+
+/*****************************************************************************/
+/* fail_wait - in case of unrecoverable error */
+/*****************************************************************************/
+int fail_wait(void) {
+ show_memory();
+
+ Serial.println(F("Failed. Halt."));
+ while (1) {
+ delay(1000);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* show_memory() to optionally view during debugging. */
+/*****************************************************************************/
+int show_memory(void)
+{
+#if defined(__arm__)
+ struct mallinfo mi = mallinfo();
+
+ char *heapend=sbrk(0);
+ register char * stack_ptr asm("sp");
+ #if defined(DEBUG_WOLFSSL_VERBOSE)
+ Serial.print(" arena=");
+ Serial.println(mi.arena);
+ Serial.print(" ordblks=");
+ Serial.println(mi.ordblks);
+ Serial.print(" uordblks=");
+ Serial.println(mi.uordblks);
+ Serial.print(" fordblks=");
+ Serial.println(mi.fordblks);
+ Serial.print(" keepcost=");
+ Serial.println(mi.keepcost);
+ #endif
+
+ #if defined(DEBUG_WOLFSSL) || defined(MEMORY_STRESS_TEST)
+ Serial.print("Estimated free memory: ");
+ Serial.print(stack_ptr - heapend + mi.fordblks);
+ Serial.println(F(" bytes"));
+ #endif
+
+ #if (0)
+ /* Experimental: not supported on all devices: */
+ Serial.print("RAM Start %lx\n", (unsigned long)ramstart);
+ Serial.print("Data/Bss end %lx\n", (unsigned long)&_end);
+ Serial.print("Heap End %lx\n", (unsigned long)heapend);
+ Serial.print("Stack Ptr %lx\n",(unsigned long)stack_ptr);
+ Serial.print("RAM End %lx\n", (unsigned long)ramend);
+
+ Serial.print("Heap RAM Used: ",mi.uordblks);
+ Serial.print("Program RAM Used ",&_end - ramstart);
+ Serial.print("Stack RAM Used ",ramend - stack_ptr);
+
+ Serial.print("Estimated Free RAM: %d\n\n",stack_ptr - heapend + mi.fordblks);
+ #endif
+#else
+ Serial.println(F("show_memory() not implemented for this platform"));
+#endif
+ return 0;
+}
+
+/*****************************************************************************/
+/* Arduino setup_hardware() */
+/*****************************************************************************/
+int setup_hardware(void) {
+ int ret = 0;
+
+#if defined(ARDUINO_SAMD_NANO_33_IOT)
+ Serial.println(F("Detected known tested and working Arduino Nano 33 IoT"));
+#elif defined(ARDUINO_ARCH_RP2040)
+ Serial.println(F("Detected known tested and working Arduino RP-2040"));
+#elif defined(__arm__) && defined(ID_TRNG) && defined(TRNG)
+ /* need to manually turn on random number generator on Arduino Due, etc. */
+ pmc_enable_periph_clk(ID_TRNG);
+ trng_enable(TRNG);
+ Serial.println(F("Enabled ARM TRNG"));
+#endif
+
+ show_memory();
+ randomSeed(analogRead(0));
+ return ret;
+}
+
+/*****************************************************************************/
+/* Arduino setup_datetime() */
+/* The device needs to have a valid date within the valid range of certs. */
+/*****************************************************************************/
+int setup_datetime(void) {
+ int ret = 0;
+ int ntp_tries = 20;
+
+ /* we need a date in the range of cert expiration */
+#ifdef USE_NTP_LIB
+ #if defined(ESP32)
+ NTPClient timeClient(ntpUDP, "pool.ntp.org");
+
+ timeClient.begin();
+ timeClient.update();
+ delay(1000);
+ while (!timeClient.isTimeSet() && (ntp_tries > 0)) {
+ timeClient.forceUpdate();
+ Serial.println(F("Waiting for NTP update"));
+ delay(2000);
+ ntp_tries--;
+ }
+ if (ntp_tries <= 0) {
+ Serial.println(F("Warning: gave up waiting on NTP"));
+ }
+ Serial.println(timeClient.getFormattedTime());
+ Serial.println(timeClient.getEpochTime());
+ #endif
+#endif
+
+#if defined(ESP32)
+ /* see esp32-hal-time.c */
+ ntp_tries = 5;
+ /* Replace "pool.ntp.org" with your preferred NTP server */
+ configTime(0, 0, "pool.ntp.org");
+
+ /* Wait for time to be set */
+ while ((time(nullptr) <= 100000) && ntp_tries > 0) {
+ Serial.println(F("Waiting for time to be set..."));
+ delay(2000);
+ ntp_tries--;
+ }
+#endif
+
+ return ret;
+} /* setup_datetime */
+
+/*****************************************************************************/
+/* Arduino setup_network() */
+/*****************************************************************************/
+int setup_network(void) {
+ int ret = 0;
+
+#if defined(USING_WIFI)
+ int status = WL_IDLE_STATUS;
+
+ /* The ESP8266 & ESP32 support both AP and STA. We'll use STA: */
+ #if defined(ESP8266) || defined(ESP32)
+ WiFi.mode(WIFI_STA);
+ #else
+ String fv;
+ if (WiFi.status() == WL_NO_MODULE) {
+ Serial.println("Communication with WiFi module failed!");
+ /* don't continue if no network */
+ while (true) ;
+ }
+
+ fv = WiFi.firmwareVersion();
+ if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
+ Serial.println("Please upgrade the firmware");
+ }
+ #endif
+
+ Serial.print(F("Connecting to WiFi "));
+ Serial.print(ssid);
+ status = WiFi.begin(ssid, password);
+ while (status != WL_CONNECTED) {
+ delay(1000);
+ Serial.print(F("."));
+ Serial.print(status);
+ status = WiFi.status();
+ }
+
+ Serial.println(F(" Connected!"));
+#else
+ /* Newer Ethernet shields have a
+ * MAC address printed on a sticker on the shield */
+ byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
+ IPAddress ip(192, 168, 1, 42);
+ IPAddress myDns(192, 168, 1, 1);
+ Ethernet.init(10); /* Most Arduino shields */
+ /* Ethernet.init(5); * MKR ETH Shield */
+ /* Ethernet.init(0); * Teensy 2.0 */
+ /* Ethernet.init(20); * Teensy++ 2.0 */
+ /* Ethernet.init(15); * ESP8266 with Adafruit FeatherWing Ethernet */
+ /* Ethernet.init(33); * ESP32 with Adafruit FeatherWing Ethernet */
+ Serial.println(F("Initialize Ethernet with DHCP:"));
+ if (Ethernet.begin(mac) == 0) {
+ Serial.println(F("Failed to configure Ethernet using DHCP"));
+ /* Check for Ethernet hardware present */
+ if (Ethernet.hardwareStatus() == EthernetNoHardware) {
+ Serial.println(F("Ethernet shield was not found."));
+ while (true) {
+ delay(1); /* do nothing */
+ }
+ }
+ if (Ethernet.linkStatus() == LinkOFF) {
+ Serial.println(F("Ethernet cable is not connected."));
+ }
+ /* try to configure using IP address instead of DHCP : */
+ Ethernet.begin(mac, ip, myDns);
+ }
+ else {
+ Serial.print(F(" DHCP assigned IP "));
+ Serial.println(Ethernet.localIP());
+ }
+ /* We'll assume the Ethernet connection is ready to go. */
+#endif
+
+ Serial.println(F("********************************************************"));
+ Serial.print(F(" wolfSSL Example Server IP = "));
+#if defined(USING_WIFI)
+ Serial.println(WiFi.localIP());
+#else
+ Serial.println(Ethernet.localIP());
+#endif
+ /* In server mode, there's no host definition. */
+ /* See companion example: wolfssl_client.ino */
+ Serial.println(F("********************************************************"));
+ Serial.println(F("Setup network complete."));
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* Arduino setup_wolfssl() */
+/*****************************************************************************/
+int setup_wolfssl(void)
+{
+ int ret = 0;
+ WOLFSSL_METHOD* method;
+
+ /* Show a revision of wolfssl user_settings.h file in use when available: */
+#if defined(WOLFSSL_USER_SETTINGS_ID)
+ Serial.print(F("WOLFSSL_USER_SETTINGS_ID: "));
+ Serial.println(F(WOLFSSL_USER_SETTINGS_ID));
+#else
+ Serial.println(F("No WOLFSSL_USER_SETTINGS_ID found."));
+#endif
+
+#if defined(NO_WOLFSSL_SERVER)
+ Serial.println(F("wolfSSL server code disabled to save space."));
+#endif
+#if defined(NO_WOLFSSL_CLIENT)
+ Serial.println(F("wolfSSL client code disabled to save space."));
+#endif
+
+#if defined(DEBUG_WOLFSSL)
+ Serial.println(F("wolfSSL Debugging is available! (DEBUG_WOLFSSL)"));
+ #if defined(DEBUG_WOLFSSL_MESSAGES_ON)
+ Serial.println(F("Enabling verbose messages wolfSSL_Debugging_ON"));
+ wolfSSL_Debugging_ON();
+ #else
+ Serial.println(F("Enable verbose messages with wolfSSL_Debugging_ON"));
+ Serial.println(F("or define DEBUG_WOLFSSL_MESSAGES_ON"));
+ #endif
+#else
+ Serial.println(F("wolfSSL Debugging is Off! (enable with DEBUG_WOLFSSL)"));
+#endif
+
+ /* See ssl.c for TLS cache settings. Larger cache = use more RAM. */
+#if defined(NO_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS NO_SESSION_CACHE"));
+#elif defined(MICRO_SESSION_CACHEx)
+ Serial.println(F("wolfSSL TLS MICRO_SESSION_CACHE"));
+#elif defined(SMALL_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS SMALL_SESSION_CACHE"));
+#elif defined(MEDIUM_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS MEDIUM_SESSION_CACHE"));
+#elif defined(BIG_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS BIG_SESSION_CACHE"));
+#elif defined(HUGE_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS HUGE_SESSION_CACHE"));
+#elif defined(HUGE_SESSION_CACHE)
+ Serial.println(F("wolfSSL TLS HUGE_SESSION_CACHE"));
+#else
+ Serial.println(F("WARNING: Unknown or no TLS session cache setting."));
+ /* See wolfssl/src/ssl.c for amount of memory used.
+ * It is best on embedded devices to choose a TLS session cache size. */
+#endif
+
+ /* Initialize wolfSSL before assigning ctx */
+ ret = wolfSSL_Init();
+ if (ret == WOLFSSL_SUCCESS) {
+ Serial.println("Successfully called wolfSSL_Init");
+ }
+ else {
+ Serial.println("ERROR: wolfSSL_Init failed");
+ }
+
+ /* See companion server example with wolfSSLv23_server_method here.
+ * method = wolfSSLv23_client_method()); SSL 3.0 - TLS 1.3.
+ * method = wolfTLSv1_2_client_method(); only TLS 1.2
+ * method = wolfTLSv1_3_client_method(); only TLS 1.3
+ *
+ * see Arduino\libraries\wolfssl\src\user_settings.h */
+
+ Serial.println("Here we go!");
+
+#ifdef WOLFSSL_DTLS13
+ Serial.println(F("Setting wolfDTLSv1_3_client_method"));
+ method = wolfDTLSv1_3_server_method();
+#else
+ Serial.println(F("Setting wolfDTLSv1_2_client_method"));
+ method = wolfDTLSv1_2_servert_method();
+#endif
+ ctx = wolfSSL_CTX_new(method);
+ if (ctx == NULL) {
+ fail_wait();
+ }
+
+ if (method == NULL) {
+ Serial.println(F("Unable to get wolfssl client method"));
+ fail_wait();
+ }
+
+ ctx = wolfSSL_CTX_new(method);
+ if (ctx == NULL) {
+ Serial.println(F("unable to get ctx"));
+ fail_wait();
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* Arduino setup_certificates() */
+/*****************************************************************************/
+int setup_certificates(void)
+{
+ int ret = 0;
+
+/* See user_settings.h that should have included wolfssl/certs_test.h */
+
+Serial.println(F("Initializing certificates..."));
+show_memory();
+
+ /* Load CA certificates */
+ if (ret == WOLFSSL_SUCCESS) {
+ /* caCertLoc[] = "../certs/ca-cert.pem"; */
+ ret = wolfSSL_CTX_load_verify_buffer(ctx,
+ CTX_CA_CERT,
+ CTX_CA_CERT_SIZE,
+ CTX_SERVER_CERT_TYPE);
+ }
+
+ /* If successful, Load server certificates */
+ Serial.println("Initializing certificates...");
+ ret = wolfSSL_CTX_use_certificate_buffer(ctx,
+ CTX_SERVER_CERT,
+ CTX_SERVER_CERT_SIZE,
+ CTX_CA_CERT_TYPE);
+
+ if (ret == WOLFSSL_SUCCESS) {
+ Serial.print("Success: use certificate: ");
+ Serial.println(xstr(CTX_SERVER_CERT));
+ }
+ else {
+ Serial.print("Error: wolfSSL_CTX_use_certificate_buffer failed: ");
+ wc_ErrorString(ret, wc_error_message);
+ Serial.println(wc_error_message);
+ fail_wait();
+ }
+
+ /* Setup private server key */
+ ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx,
+ CTX_SERVER_KEY,
+ CTX_SERVER_KEY_SIZE,
+ CTX_SERVER_KEY_TYPE);
+ if (ret == WOLFSSL_SUCCESS) {
+ Serial.print("Success: use private key buffer: ");
+ Serial.println(xstr(CTX_SERVER_KEY));
+ }
+ else {
+ Serial.print("Error: wolfSSL_CTX_use_PrivateKey_buffer failed: ");
+ wc_ErrorString(ret, wc_error_message);
+ Serial.println(wc_error_message);
+ fail_wait();
+ }
+
+ /* Setup private server key */
+ ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx,
+ CTX_SERVER_KEY,
+ CTX_SERVER_KEY_SIZE,
+ CTX_SERVER_KEY_TYPE);
+
+ if (ret == WOLFSSL_SUCCESS) {
+ Serial.print("Success: use private key buffer: ");
+ Serial.println(xstr(CTX_SERVER_KEY));
+ }
+ else {
+ Serial.print("Error: wolfSSL_CTX_use_PrivateKey_buffer failed: ");
+ wc_ErrorString(ret, wc_error_message);
+ Serial.println(wc_error_message);
+ fail_wait();
+ }
+
+ return ret;
+} /* Arduino setup */
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino setup() */
+/*****************************************************************************/
+/*****************************************************************************/
+void setup(void)
+{
+ int i = 0;
+ Serial.begin(SERIAL_BAUD);
+ while (!Serial && (i < 10)) {
+ /* wait for serial port to connect. Needed for native USB port only */
+ delay(1000);
+ i++;
+ }
+
+ Serial.println(F(""));
+ Serial.println(F(""));
+ Serial.println(F("wolfSSL DTLS Server Example Startup."));
+
+ /* Optionally pre-allocate a large block of memory for testing */
+#if defined(MEMORY_STRESS_TEST)
+ Serial.println(F("WARNING: Memory Stress Test Active!"));
+ Serial.print(F("Allocating extra memory: "));
+ Serial.print(MEMORY_STRESS_INITIAL);
+ Serial.println(F(" bytes..."));
+ memory_stress[mem_ctr] = (char*)malloc(MEMORY_STRESS_INITIAL);
+ show_memory();
+#endif
+
+ setup_hardware();
+
+ setup_network();
+
+ setup_datetime();
+
+ setup_wolfssl();
+
+ setup_certificates();
+
+#if defined THIS_USER_SETTINGS_VERSION
+ Serial.print(F("This user_settings.h version:"))
+ Serial.println(THIS_USER_SETTINGS_VERSION)
+#endif
+
+ /* Start the server
+ * See https://www.arduino.cc/reference/en/libraries/ethernet/server.begin/
+ */
+
+ Serial.println(F("Completed Arduino setup()"));
+
+ server.begin();
+ Serial.println("Begin Server... (waiting for remote client to connect)");
+
+ /* See companion wolfssl_client.ino code */
+ return;
+} /* Arduino setup */
+
+/*****************************************************************************/
+/* wolfSSL error_check() */
+/*****************************************************************************/
+int error_check(int this_ret, bool halt_on_error,
+ const __FlashStringHelper* message) {
+ int ret = 0;
+ if (this_ret == WOLFSSL_SUCCESS) {
+ Serial.print(F("Success: "));
+ Serial.println(message);
+ }
+ else {
+ Serial.print(F("ERROR: return = "));
+ Serial.print(this_ret);
+ Serial.print(F(": "));
+ Serial.println(message);
+ Serial.println(wc_GetErrorString(this_ret));
+ if (halt_on_error) {
+ fail_wait();
+ }
+ }
+ show_memory();
+
+ return ret;
+} /* error_check */
+
+/*****************************************************************************/
+/* wolfSSL error_check_ssl */
+/* Parameters: */
+/* ssl is the current WOLFSSL object pointer */
+/* halt_on_error set to true to suspend operations for critical error */
+/* message is expected to be a memory-efficient F("") macro string */
+/*****************************************************************************/
+int error_check_ssl(WOLFSSL* ssl, int this_ret, bool halt_on_error,
+ const __FlashStringHelper* message) {
+ int err = 0;
+
+ if (ssl == NULL) {
+ Serial.println(F("ssl is Null; Unable to allocate SSL object?"));
+#ifndef DEBUG_WOLFSSL
+ Serial.println(F("Define DEBUG_WOLFSSL in user_settings.h for more."));
+#else
+ Serial.println(F("See wolfssl/wolfcrypt/error-crypt.h for codes."));
+#endif
+ Serial.print(F("ERROR: "));
+ Serial.println(message);
+ show_memory();
+ if (halt_on_error) {
+ fail_wait();
+ }
+ }
+ else {
+ err = wolfSSL_get_error(ssl, this_ret);
+ if (err == WOLFSSL_SUCCESS) {
+ Serial.print(F("Success m: "));
+ Serial.println(message);
+ }
+ else {
+ if (err < 0) {
+ wolfSSL_ERR_error_string(err, errBuf);
+ Serial.print(F("WOLFSSL Error: "));
+ Serial.print(err);
+ Serial.print(F("; "));
+ Serial.println(errBuf);
+ }
+ else {
+ Serial.println(F("Success: ssl object."));
+ }
+ }
+ }
+
+ return err;
+} /* error_check_ssl */
+
+static void sig_handler(const int sig);
+static void free_resources(void);
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino loop() */
+/*****************************************************************************/
+/*****************************************************************************/
+void loop()
+{
+ int exitVal = 1;
+ struct sockaddr_in servAddr; /* our server's address */
+ struct sockaddr_in cliaddr; /* the client's address */
+ int ret;
+ int err;
+ int recvLen = 0; /* length of message */
+ socklen_t cliLen;
+ char buff[MAXLINE]; /* the incoming message */
+ char ack[] = "I hear you fashizzle!\n";
+
+ /* Initialize wolfSSL before assigning ctx */
+ if (wolfSSL_Init() != WOLFSSL_SUCCESS) {
+ fprintf(stderr, "wolfSSL_Init error.\n");
+ fail_wait();
+ }
+
+ /* No-op when debugging is not compiled in */
+ wolfSSL_Debugging_ON();
+
+
+ /* Create a UDP/IP socket */
+ if ((listenfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
+ perror("socket()");
+ goto cleanup;
+ }
+ printf("Socket allocated\n");
+ memset((char *)&servAddr, 0, sizeof(servAddr));
+ /* host-to-network-long conversion (htonl) */
+ /* host-to-network-short conversion (htons) */
+ servAddr.sin_family = AF_INET;
+ servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ servAddr.sin_port = htons(WOLFSSL_PORT);
+
+ /* Bind Socket */
+ if (bind(listenfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0) {
+ perror("bind()");
+ goto cleanup;
+ }
+
+ // signal(SIGINT, sig_handler);
+
+ while (1) {
+ printf("Awaiting client connection on port %d\n", WOLFSSL_PORT);
+
+ cliLen = sizeof(cliaddr);
+ ret = (int)recvfrom(listenfd, (char *)&buff, sizeof(buff), MSG_PEEK,
+ (struct sockaddr*)&cliaddr, &cliLen);
+
+ if (ret < 0) {
+ perror("recvfrom()");
+ goto cleanup;
+ }
+ else if (ret == 0) {
+ fprintf(stderr, "recvfrom zero return\n");
+ goto cleanup;
+ }
+
+ /* Create the WOLFSSL Object */
+ if ((ssl = wolfSSL_new(ctx)) == NULL) {
+ fprintf(stderr, "wolfSSL_new error.\n");
+ goto cleanup;
+ }
+
+ if (wolfSSL_dtls_set_peer(ssl, &cliaddr, cliLen) != WOLFSSL_SUCCESS) {
+ fprintf(stderr, "wolfSSL_dtls_set_peer error.\n");
+ goto cleanup;
+ }
+
+ if (wolfSSL_set_fd(ssl, listenfd) != WOLFSSL_SUCCESS) {
+ fprintf(stderr, "wolfSSL_set_fd error.\n");
+ break;
+ }
+
+ if (wolfSSL_accept(ssl) != WOLFSSL_SUCCESS) {
+ err = wolfSSL_get_error(ssl, 0);
+ fprintf(stderr, "error = %d, %s\n", err,
+ wolfSSL_ERR_reason_error_string(err));
+ fprintf(stderr, "SSL_accept failed.\n");
+ goto cleanup;
+ }
+
+ while (1) {
+ if ((recvLen = wolfSSL_read(ssl, buff, sizeof(buff)-1)) > 0) {
+ printf("heard %d bytes\n", recvLen);
+
+ buff[recvLen] = '\0';
+ printf("I heard this: \"%s\"\n", buff);
+ }
+ else if (recvLen <= 0) {
+ err = wolfSSL_get_error(ssl, 0);
+ if (err == WOLFSSL_ERROR_ZERO_RETURN) /* Received shutdown */
+ break;
+ fprintf(stderr, "error = %d, %s\n", err,
+ wolfSSL_ERR_reason_error_string(err));
+ fprintf(stderr, "SSL_read failed.\n");
+ goto cleanup;
+ }
+ printf("Sending reply.\n");
+ if (wolfSSL_write(ssl, ack, sizeof(ack)) < 0) {
+ err = wolfSSL_get_error(ssl, 0);
+ fprintf(stderr, "error = %d, %s\n", err,
+ wolfSSL_ERR_reason_error_string(err));
+ fprintf(stderr, "wolfSSL_write failed.\n");
+ goto cleanup;
+ }
+ }
+
+ printf("reply sent \"%s\"\n", ack);
+
+ /* Attempt a full shutdown */
+ ret = wolfSSL_shutdown(ssl);
+ if (ret == WOLFSSL_SHUTDOWN_NOT_DONE)
+ ret = wolfSSL_shutdown(ssl);
+ if (ret != WOLFSSL_SUCCESS) {
+ err = wolfSSL_get_error(ssl, 0);
+ fprintf(stderr, "err = %d, %s\n", err,
+ wolfSSL_ERR_reason_error_string(err));
+ fprintf(stderr, "wolfSSL_shutdown failed\n");
+ }
+ wolfSSL_free(ssl);
+ ssl = NULL;
+
+ printf("Awaiting new connection\n");
+ }
+
+ exitVal = 0;
+cleanup:
+ free_resources();
+ wolfSSL_Cleanup();
+
+ Serial.println(F("Done!"));
+ while (1) {
+ delay(1000);
+ }
+}
+
+
+static void sig_handler(const int sig)
+{
+ (void)sig;
+ free_resources();
+ wolfSSL_Cleanup();
+}
+
+static void free_resources(void)
+{
+ if (ssl != NULL) {
+ wolfSSL_shutdown(ssl);
+ wolfSSL_free(ssl);
+ ssl = NULL;
+ }
+ if (ctx != NULL) {
+ wolfSSL_CTX_free(ctx);
+ ctx = NULL;
+ }
+ if (listenfd != INVALID_SOCKET) {
+ close(listenfd);
+ listenfd = INVALID_SOCKET;
+ }
+}
+
diff --git a/examples/wolfssl_version/README.md b/examples/wolfssl_version/README.md
new file mode 100644
index 0000000..3abfe82
--- /dev/null
+++ b/examples/wolfssl_version/README.md
@@ -0,0 +1,3 @@
+# Arduino Basic Hello World
+
+This example simply compiles in wolfSSL and shows the current version number.
diff --git a/examples/wolfssl_version/wolfssl_version.ino b/examples/wolfssl_version/wolfssl_version.ino
new file mode 100644
index 0000000..ac34124
--- /dev/null
+++ b/examples/wolfssl_version/wolfssl_version.ino
@@ -0,0 +1,81 @@
+/* wolfssl_server.ino
+ *
+ * Copyright (C) 2006-2025 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 3 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
+ */
+
+#include
+
+#if defined(ARDUINO_PORTENTA_X8)
+ /* The Portenta is a Linux device. See wolfSSL examples:
+ * https://github.com/wolfSSL/wolfssl/tree/master/examples
+ * By default Serial is disabled and mapped to ErrorSerial */
+ #include
+#endif
+
+ /* wolfSSL user_settings.h must be included from settings.h
+ * Make all configurations changes in user_settings.h
+ * Do not edit wolfSSL `settings.h` or `config.h` files.
+ * Do not explicitly include user_settings.h in any source code.
+ * Each Arduino sketch that uses wolfSSL must have: #include "wolfssl.h"
+ * C/C++ source files can use: #include
+ * The wolfSSL "settings.h" must be included in each source file using wolfSSL.
+ * The wolfSSL "settings.h" must appear before any other wolfSSL include.
+ */
+
+/* This is Arduino sketch example 1 of 2: single file .ino compile. */
+/* See also template.ino project example using multiple files. */
+
+#include
+#include
+
+/* Choose a monitor serial baud rate: 9600, 14400, 19200, 57600, 74880, etc. */
+#define SERIAL_BAUD 115200
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino setup() */
+/*****************************************************************************/
+/*****************************************************************************/
+void setup() {
+ Serial.begin(SERIAL_BAUD);
+ while (!Serial) {
+ /* wait for serial port to connect. Needed for native USB port only */
+ }
+ Serial.println(F(""));
+ Serial.println(F(""));
+ Serial.println(F("wolfSSL setup complete!"));
+
+ /* See https://github.com/wolfSSL/wolfssl/blob/master/examples/configs/user_settings_arduino.h */
+ /* Various historical versions have differing features enabled. */
+#ifdef WOLFSSL_USER_SETTINGS_ID
+ /* Print the release version at runtime for reference. */
+ Serial.println(WOLFSSL_USER_SETTINGS_ID);
+#endif
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+/* Arduino loop() */
+/*****************************************************************************/
+/*****************************************************************************/
+void loop() {
+ Serial.print("wolfSSL Version: ");
+ Serial.println(LIBWOLFSSL_VERSION_STRING);
+ delay(60000);
+}
diff --git a/library.json.pio b/library.json.pio
new file mode 100644
index 0000000..220b438
--- /dev/null
+++ b/library.json.pio
@@ -0,0 +1,24 @@
+{
+ "name": "Arduino-wolfSSL",
+ "version": "5.7.4",
+ "description": "5.7.4 (Arduino-wolfSSL for PlatformIO) A lightweight SSL/TLS library written in ANSI C and targeted for embedded, RTOS, and resource-constrained environments.",
+ "keywords": "FIPS, DO-178, TLS, DTLS, DSA, PSK, X.509, RSA, ECC, AES, GCM, PQ, SHA, SHA256, 3DES, SHA512, MD5, ASN, CMAC, Blake, camellia, ChaCha, ChaCha20, DH, OCSP, ALPN, SNI, CRL, dilithium, ed25519, ed448, kdf, pkcs7, pkcs12, poly1305, Curve25519, sakke, SM, SM2, SM3, SM4, TFM, PKI, SRP, wolfcrypt, wolfssl, Post-quantum cryptography, Certificate management, SSL-TLS handshake, Session caching, Hash, Secure hashing, Public key infrastructure, Cryptanalysis, Lightweight cryptography, Hardware-based security",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/wolfSSL/Arduino-wolfSSL.git"
+ },
+ "authors": [
+ {
+ "name": "wolfSSL Inc.",
+ "email": "support@wolfssl.com",
+ "url": "https://www.wolfssl.com/contact/",
+ "maintainer": true
+ }
+ ],
+ "license": "GPL-2.0-only",
+ "homepage": "https://www.wolfssl.com/",
+ "dependencies": {
+ },
+ "frameworks": "*",
+ "platforms": "*"
+}
diff --git a/library.properties b/library.properties
index 67823c1..05d11ef 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=wolfssl
-version=5.6.6-Arduino.2
+version=5.8.4
author=wolfSSL Inc.
maintainer=wolfSSL inc
sentence=A lightweight SSL/TLS library written in ANSI C and targeted for embedded, RTOS, and resource-constrained environments.
diff --git a/library.properties.pio b/library.properties.pio
new file mode 100644
index 0000000..f772f1f
--- /dev/null
+++ b/library.properties.pio
@@ -0,0 +1,9 @@
+name=Arduino-wolfSSL
+version=5.7.4
+author=wolfSSL Inc.
+maintainer=wolfSSL inc
+sentence=A lightweight SSL/TLS library written in ANSI C and targeted for embedded, RTOS, and resource-constrained environments.
+paragraph=Manual: https://www.wolfssl.com/documentation/manuals/wolfssl/index.html.
+category=Communication
+url=https://www.wolfssl.com/
+architectures=*
diff --git a/src/src/bio.c b/src/src/bio.c
index 2dab43e..8321dab 100644
--- a/src/src/bio.c
+++ b/src/src/bio.c
@@ -1,12 +1,12 @@
/* bio.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,15 +19,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
-#ifdef HAVE_CONFIG_H
- #include
-#endif
+#include
-#include
-#if defined(OPENSSL_EXTRA) && !defined(_WIN32)
+#if defined(OPENSSL_EXTRA) && !defined(_WIN32) && !defined(_GNU_SOURCE)
/* turn on GNU extensions for XVASPRINTF with wolfSSL_BIO_printf */
- #undef _GNU_SOURCE
- #define _GNU_SOURCE
+ #define _GNU_SOURCE 1
#endif
#if !defined(WOLFSSL_BIO_INCLUDED)
@@ -50,7 +46,7 @@
*/
static int wolfSSL_BIO_BASE64_read(WOLFSSL_BIO* bio, void* buf, int len)
{
- word32 frmtSz = len;
+ word32 frmtSz = (word32)len;
WOLFSSL_ENTER("wolfSSL_BIO_BASE64_read");
@@ -77,6 +73,8 @@ static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
if (buf == NULL || len == 0)
return 0;
+ /* default no retry */
+ bio->flags &= ~(WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY);
sz1 = wolfSSL_BIO_nread(bio, &pt, len);
if (sz1 > 0) {
XMEMCPY(buf, pt, sz1);
@@ -91,8 +89,10 @@ static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
}
}
}
- if (sz1 == 0)
+ if (sz1 == 0) {
+ bio->flags |= WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY;
sz1 = -1;
+ }
return sz1;
}
@@ -139,11 +139,11 @@ static int wolfSSL_BIO_MEMORY_read(WOLFSSL_BIO* bio, void* buf, int len)
return WOLFSSL_BIO_ERROR;
}
- XMEMCPY(buf, bio->mem_buf->data + bio->rdIdx, sz);
+ XMEMCPY(buf, bio->mem_buf->data + bio->rdIdx, (size_t)sz);
bio->rdIdx += sz;
if (bio->rdIdx >= bio->wrSz) {
- if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
+ if (bio->flags & WOLFSSL_BIO_FLAG_MEM_RDONLY) {
bio->wrSz = bio->wrSzReset;
}
else {
@@ -157,26 +157,26 @@ static int wolfSSL_BIO_MEMORY_read(WOLFSSL_BIO* bio, void* buf, int len)
bio->wrSz = 0;
bio->mem_buf->length = 0;
}
- bio->ptr = bio->mem_buf->data;
+ bio->ptr.mem_buf_data = (byte *)bio->mem_buf->data;
}
else if (bio->rdIdx >= WOLFSSL_BIO_RESIZE_THRESHOLD &&
- !(bio->flags & BIO_FLAGS_MEM_RDONLY)) {
+ !(bio->flags & WOLFSSL_BIO_FLAG_MEM_RDONLY)) {
/* Resize the memory so we are not taking up more than necessary.
* memmove reverts internally to memcpy if areas don't overlap */
XMEMMOVE(bio->mem_buf->data, bio->mem_buf->data + bio->rdIdx,
- bio->wrSz - bio->rdIdx);
+ (long unsigned int)bio->wrSz - (size_t)bio->rdIdx);
bio->wrSz -= bio->rdIdx;
bio->rdIdx = 0;
/* Resize down to WOLFSSL_BIO_RESIZE_THRESHOLD for fewer
* allocations. */
if (wolfSSL_BUF_MEM_resize(bio->mem_buf,
- bio->wrSz > WOLFSSL_BIO_RESIZE_THRESHOLD ? bio->wrSz :
- WOLFSSL_BIO_RESIZE_THRESHOLD) == 0) {
+ bio->wrSz > WOLFSSL_BIO_RESIZE_THRESHOLD ?
+ (size_t)bio->wrSz : WOLFSSL_BIO_RESIZE_THRESHOLD) == 0) {
WOLFSSL_MSG("wolfSSL_BUF_MEM_resize error");
return WOLFSSL_BIO_ERROR;
}
- bio->mem_buf->length = bio->wrSz;
- bio->ptr = bio->mem_buf->data;
+ bio->mem_buf->length = (size_t)bio->wrSz;
+ bio->ptr.mem_buf_data = (byte *)bio->mem_buf->data;
}
}
else {
@@ -197,6 +197,7 @@ int wolfSSL_BIO_method_type(const WOLFSSL_BIO *b)
}
#ifndef WOLFCRYPT_ONLY
+#ifndef NO_TLS
/* Helper function to read from WOLFSSL_BIO_SSL type
*
* returns the number of bytes read on success
@@ -213,11 +214,11 @@ static int wolfSSL_BIO_SSL_read(WOLFSSL_BIO* bio, void* buf,
return WOLFSSL_FATAL_ERROR;
bio->flags &= ~(WOLFSSL_BIO_FLAG_RETRY); /* default no retry */
- ret = wolfSSL_read((WOLFSSL*)bio->ptr, buf, len);
+ ret = wolfSSL_read(bio->ptr.ssl, buf, len);
if (ret == 0)
front->eof = 1;
else if (ret < 0) {
- int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0);
+ int err = wolfSSL_get_error(bio->ptr.ssl, 0);
if ( !(err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) ) {
front->eof = 1;
}
@@ -228,25 +229,26 @@ static int wolfSSL_BIO_SSL_read(WOLFSSL_BIO* bio, void* buf,
return ret;
}
+#endif /* !NO_TLS */
static int wolfSSL_BIO_MD_read(WOLFSSL_BIO* bio, void* buf, int sz)
{
- if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) {
- if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf,
- sz) != WOLFSSL_SUCCESS)
+ if (wolfSSL_EVP_MD_CTX_type(bio->ptr.md_ctx) == WC_NID_hmac) {
+ if (wolfSSL_EVP_DigestSignUpdate(bio->ptr.md_ctx, buf,
+ (unsigned int)sz) != WOLFSSL_SUCCESS)
{
return WOLFSSL_FATAL_ERROR;
}
}
else {
- if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, sz)
+ if (wolfSSL_EVP_DigestUpdate(bio->ptr.md_ctx, buf, (size_t)sz)
!= WOLFSSL_SUCCESS) {
return WOLFSSL_FATAL_ERROR;
}
}
return sz;
}
-#endif /* WOLFCRYPT_ONLY */
+#endif /* !WOLFCRYPT_ONLY */
/* Used to read data from a WOLFSSL_BIO structure
@@ -286,6 +288,9 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
}
while (bio != NULL && ret >= 0) {
+#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
+ int inhibit_flow_increment = 0;
+#endif
/* check for custom read */
if (bio->method && bio->method->readCb) {
ret = bio->method->readCb(bio, (char*)buf, len);
@@ -298,19 +303,22 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
break;
case WOLFSSL_BIO_BIO: /* read BIOs */
ret = wolfSSL_BIO_BIO_read(bio, buf, len);
+#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
+ inhibit_flow_increment = 1;
+#endif
break;
case WOLFSSL_BIO_MEMORY:
ret = wolfSSL_BIO_MEMORY_read(bio, buf, len);
break;
case WOLFSSL_BIO_FILE:
#ifndef NO_FILESYSTEM
- if (bio->ptr) {
- ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr);
+ if (bio->ptr.fh) {
+ ret = (int)XFREAD(buf, 1, (size_t)len, bio->ptr.fh);
}
else {
- #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \
+ #if defined(XREAD) && !defined(NO_WOLFSSL_DIR) && \
!defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2)
- ret = (int)XREAD(bio->num, buf, len);
+ ret = (int)XREAD(bio->num.fd, buf, (size_t)len);
#else
WOLFSSL_MSG("No file pointer and XREAD not enabled");
ret = NOT_COMPILED_IN;
@@ -322,7 +330,7 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
#endif /* !NO_FILESYSTEM */
break;
case WOLFSSL_BIO_SSL:
- #ifndef WOLFCRYPT_ONLY
+ #if !defined(WOLFCRYPT_ONLY) && !defined(NO_TLS)
ret = wolfSSL_BIO_SSL_read(bio, buf, len, front);
#else
WOLFSSL_MSG("WOLFSSL_BIO_SSL used with WOLFCRYPT_ONLY");
@@ -341,14 +349,56 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len)
#ifdef USE_WOLFSSL_IO
/* BIO requires built-in socket support
* (cannot be used with WOLFSSL_USER_IO) */
- ret = wolfIO_Recv(bio->num, (char*)buf, len, 0);
+ bio->flags &= ~WOLFSSL_BIO_FLAG_RETRY;
+ ret = wolfIO_Recv(bio->num.fd, (char*)buf, len, 0);
+ if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ)) {
+ bio->flags |= WOLFSSL_BIO_FLAG_RETRY;
+ }
+ if (ret < 0) {
+ ret = WOLFSSL_BIO_ERROR;
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ break;
+
+ case WOLFSSL_BIO_DGRAM:
+ #if defined(WOLFSSL_HAVE_BIO_ADDR) && defined(WOLFSSL_DTLS) && \
+ defined(USE_WOLFSSL_IO)
+ /* BIO requires built-in socket support
+ * (cannot be used with WOLFSSL_USER_IO) */
+ bio->flags &= ~WOLFSSL_BIO_FLAG_RETRY;
+ if (bio->connected)
+ ret = wolfIO_Recv(bio->num.fd, (char*)buf, len, 0);
+ else {
+ wolfSSL_BIO_ADDR_clear(&bio->peer_addr);
+ ret = wolfIO_RecvFrom(bio->num.fd, &bio->peer_addr,
+ (char*)buf, len, 0);
+ }
+ if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ)) {
+ bio->flags |= WOLFSSL_BIO_FLAG_RETRY;
+ }
+ if (ret < 0) {
+ ret = WOLFSSL_BIO_ERROR;
+ }
#else
ret = NOT_COMPILED_IN;
#endif
break;
+
+ case WOLFSSL_BIO_NULL:
+ ret = 0;
+ break;
+
} /* switch */
}
+#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
+ if ((ret > 0) && (!inhibit_flow_increment)) {
+ bio->bytes_read += (word32)ret;
+ }
+#endif
+
/* case where front of list is done */
if (bio == front) {
break; /* at front of list so be done */
@@ -399,14 +449,15 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data,
/* get the encoded length */
if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) {
if (Base64_Encode_NoNl((const byte*)data, inLen, NULL,
- &sz) != LENGTH_ONLY_E) {
+ &sz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
WOLFSSL_MSG("Error with base64 get length");
return WOLFSSL_FATAL_ERROR;
}
}
else {
- if (Base64_Encode((const byte*)data, inLen, NULL, &sz) !=
- LENGTH_ONLY_E) {
+ if (Base64_Encode((const byte*)data, inLen, NULL, &sz)
+ != WC_NO_ERR_TRACE(LENGTH_ONLY_E))
+ {
WOLFSSL_MSG("Error with base64 get length");
return WOLFSSL_FATAL_ERROR;
}
@@ -448,11 +499,11 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data,
(void)heap;
- return inLen;
+ return (int)inLen;
}
#endif /* WOLFSSL_BASE64_ENCODE */
-#ifndef WOLFCRYPT_ONLY
+#if !defined(WOLFCRYPT_ONLY) && !defined(NO_TLS)
/* Helper function for writing to a WOLFSSL_BIO_SSL type
*
* returns the amount written in bytes on success
@@ -464,16 +515,16 @@ static int wolfSSL_BIO_SSL_write(WOLFSSL_BIO* bio, const void* data,
WOLFSSL_ENTER("wolfSSL_BIO_SSL_write");
- if (bio->ptr == NULL) {
+ if (bio->ptr.ssl == NULL) {
return BAD_FUNC_ARG;
}
bio->flags &= ~(WOLFSSL_BIO_FLAG_RETRY); /* default no retry */
- ret = wolfSSL_write((WOLFSSL*)bio->ptr, data, len);
+ ret = wolfSSL_write(bio->ptr.ssl, data, len);
if (ret == 0)
front->eof = 1;
else if (ret < 0) {
- int err = wolfSSL_get_error((WOLFSSL*)bio->ptr, 0);
+ int err = wolfSSL_get_error(bio->ptr.ssl, 0);
if ( !(err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) ) {
front->eof = 1;
}
@@ -483,7 +534,7 @@ static int wolfSSL_BIO_SSL_write(WOLFSSL_BIO* bio, const void* data,
}
return ret;
}
-#endif /* WOLFCRYPT_ONLY */
+#endif /* !WOLFCRYPT_ONLY && !NO_TLS */
/* Writes to a WOLFSSL_BIO_BIO type.
*
@@ -502,8 +553,11 @@ static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data,
if (bio == NULL || data == NULL || len == 0)
return 0;
+ /* default no retry */
+ bio->flags &= ~(WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY);
sz1 = wolfSSL_BIO_nwrite(bio, &buf, len);
if (sz1 == 0) {
+ bio->flags |= WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY;
WOLFSSL_MSG("No room left to write");
return WOLFSSL_BIO_ERROR;
}
@@ -511,7 +565,7 @@ static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data,
WOLFSSL_MSG("Error in wolfSSL_BIO_nwrite");
return sz1;
}
- XMEMCPY(buf, data, sz1);
+ XMEMCPY(buf, data, (size_t)sz1);
data = (char*)data + sz1;
len -= sz1;
@@ -519,8 +573,10 @@ static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data,
/* try again to see if maybe we wrapped around the ring buffer */
sz2 = wolfSSL_BIO_nwrite(bio, &buf, len);
if (sz2 > 0) {
- XMEMCPY(buf, data, sz2);
+ XMEMCPY(buf, data, (size_t)sz2);
sz1 += sz2;
+ if (len > sz2)
+ bio->flags |= WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY;
}
}
@@ -548,15 +604,15 @@ static int wolfSSL_BIO_MEMORY_write(WOLFSSL_BIO* bio, const void* data,
WOLFSSL_MSG("one of input parameters is null");
return WOLFSSL_FAILURE;
}
- if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
+ if (bio->flags & WOLFSSL_BIO_FLAG_MEM_RDONLY) {
return WOLFSSL_FAILURE;
}
if (len == 0)
return WOLFSSL_SUCCESS; /* Return early to make logic simpler */
- if (wolfSSL_BUF_MEM_grow_ex(bio->mem_buf, bio->wrSz + len, 0)
- == 0) {
+ if (wolfSSL_BUF_MEM_grow_ex(bio->mem_buf, ((size_t)bio->wrSz) +
+ ((size_t)len), 0) == 0) {
WOLFSSL_MSG("Error growing memory area");
return WOLFSSL_FAILURE;
}
@@ -566,9 +622,9 @@ static int wolfSSL_BIO_MEMORY_write(WOLFSSL_BIO* bio, const void* data,
return WOLFSSL_FAILURE;
}
- XMEMCPY(bio->mem_buf->data + bio->wrSz, data, len);
- bio->ptr = bio->mem_buf->data;
- bio->num = (int)bio->mem_buf->max;
+ XMEMCPY(bio->mem_buf->data + bio->wrSz, data, (size_t)len);
+ bio->ptr.mem_buf_data = (byte *)bio->mem_buf->data;
+ bio->num.length = bio->mem_buf->max;
bio->wrSz += len;
bio->wrIdx += len;
@@ -589,14 +645,14 @@ static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len)
return BAD_FUNC_ARG;
}
- if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) {
- if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data,
- len) != WOLFSSL_SUCCESS) {
+ if (wolfSSL_EVP_MD_CTX_type(bio->ptr.md_ctx) == WC_NID_hmac) {
+ if (wolfSSL_EVP_DigestSignUpdate(bio->ptr.md_ctx, data,
+ (unsigned int)len) != WOLFSSL_SUCCESS) {
ret = WOLFSSL_BIO_ERROR;
}
}
else {
- if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, len)
+ if (wolfSSL_EVP_DigestUpdate(bio->ptr.md_ctx, data, (size_t)len)
!= WOLFSSL_SUCCESS) {
ret = WOLFSSL_BIO_ERROR;
}
@@ -638,6 +694,9 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
}
while (bio != NULL && ret >= 0) {
+#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
+ int inhibit_flow_increment = 0;
+#endif
/* check for custom write */
if (bio->method && bio->method->writeCb) {
ret = bio->method->writeCb(bio, (const char*)data, len);
@@ -652,7 +711,7 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
if (ret > 0) {
/* change so that data is formatted buffer */
data = frmt;
- len = frmtSz;
+ len = (int)frmtSz;
}
#else
WOLFSSL_MSG("WOLFSSL_BIO_BASE64 used without "
@@ -663,19 +722,22 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
}
case WOLFSSL_BIO_BIO: /* write bios */
ret = wolfSSL_BIO_BIO_write(bio, data, len);
+#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
+ inhibit_flow_increment = 1;
+#endif
break;
case WOLFSSL_BIO_MEMORY:
ret = wolfSSL_BIO_MEMORY_write(bio, data, len);
break;
case WOLFSSL_BIO_FILE:
#ifndef NO_FILESYSTEM
- if (bio->ptr) {
- ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr);
+ if (bio->ptr.fh) {
+ ret = (int)XFWRITE(data, 1, (size_t)len, bio->ptr.fh);
}
else {
- #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \
+ #if defined(XWRITE) && !defined(NO_WOLFSSL_DIR) && \
!defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2)
- ret = (int)XWRITE(bio->num, data, len);
+ ret = (int)XWRITE(bio->num.fd, data, (size_t)len);
#else
WOLFSSL_MSG("No file pointer and XWRITE not enabled");
ret = NOT_COMPILED_IN;
@@ -687,7 +749,7 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
#endif /* !NO_FILESYSTEM */
break;
case WOLFSSL_BIO_SSL:
- #ifndef WOLFCRYPT_ONLY
+ #if !defined(WOLFCRYPT_ONLY) && !defined(NO_TLS)
/* already got eof, again is error */
if (front->eof) {
ret = WOLFSSL_FATAL_ERROR;
@@ -716,19 +778,59 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
#ifdef USE_WOLFSSL_IO
/* BIO requires built-in socket support
* (cannot be used with WOLFSSL_USER_IO) */
- ret = wolfIO_Send(bio->num, (char*)data, len, 0);
+ bio->flags &= ~WOLFSSL_BIO_FLAG_RETRY;
+ ret = wolfIO_Send(bio->num.fd, (char*)data, len, 0);
+ if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_WRITE)) {
+ bio->flags |= WOLFSSL_BIO_FLAG_RETRY;
+ }
+ if (ret < 0) {
+ ret = WOLFSSL_BIO_ERROR;
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ break;
+
+ case WOLFSSL_BIO_DGRAM:
+ #if defined(WOLFSSL_HAVE_BIO_ADDR) && defined(WOLFSSL_DTLS) && \
+ defined(USE_WOLFSSL_IO)
+ /* BIO requires built-in socket support
+ * (cannot be used with WOLFSSL_USER_IO) */
+ bio->flags &= ~WOLFSSL_BIO_FLAG_RETRY;
+ if (bio->connected)
+ ret = wolfIO_Send(bio->num.fd, (char*)data, len, 0);
+ else if (bio->peer_addr.sa.sa_family == AF_UNSPEC)
+ ret = SOCKET_ERROR_E;
+ else
+ ret = wolfIO_SendTo(bio->num.fd, &bio->peer_addr, (char*)data, len, 0);
+ if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_WRITE)) {
+ bio->flags |= WOLFSSL_BIO_FLAG_RETRY;
+ }
+ if (ret < 0) {
+ ret = WOLFSSL_BIO_ERROR;
+ }
#else
ret = NOT_COMPILED_IN;
#endif
break;
+
+ case WOLFSSL_BIO_NULL:
+ ret = len;
+ break;
+
} /* switch */
}
+#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
+ if ((ret > 0) && (! inhibit_flow_increment))
+ bio->bytes_written += (word32)ret;
+#endif
+
/* advance to the next bio in list */
bio = bio->next;
}
-#ifndef WOLFCRYPT_ONLY
+#if !defined(WOLFCRYPT_ONLY) && !defined(NO_TLS)
exit_chain:
#endif
@@ -739,7 +841,7 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len)
(const char*)data, len, 0, ret);
}
- if (frmt != NULL) {
+ if (front != NULL) {
XFREE(frmt, front->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
@@ -771,19 +873,62 @@ long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *parg)
}
switch(cmd) {
- case BIO_CTRL_PENDING:
- case BIO_CTRL_WPENDING:
+ case WOLFSSL_BIO_CTRL_PENDING:
+ case WOLFSSL_BIO_CTRL_WPENDING:
ret = (long)wolfSSL_BIO_ctrl_pending(bio);
break;
- case BIO_CTRL_INFO:
+ case WOLFSSL_BIO_CTRL_INFO:
ret = (long)wolfSSL_BIO_get_mem_data(bio, parg);
break;
- case BIO_CTRL_FLUSH:
+ case WOLFSSL_BIO_CTRL_FLUSH:
ret = (long)wolfSSL_BIO_flush(bio);
break;
- case BIO_CTRL_RESET:
+ case WOLFSSL_BIO_CTRL_RESET:
ret = (long)wolfSSL_BIO_reset(bio);
break;
+
+#ifdef WOLFSSL_HAVE_BIO_ADDR
+ case WOLFSSL_BIO_CTRL_DGRAM_CONNECT:
+ case WOLFSSL_BIO_CTRL_DGRAM_SET_PEER:
+ {
+ socklen_t addr_size;
+ if (parg == NULL) {
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+ addr_size = wolfSSL_BIO_ADDR_size((WOLFSSL_BIO_ADDR *)parg);
+ if (addr_size == 0) {
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+ XMEMCPY(&bio->peer_addr, parg, addr_size);
+ ret = WOLFSSL_SUCCESS;
+ break;
+ }
+
+ case WOLFSSL_BIO_CTRL_DGRAM_SET_CONNECTED:
+ if (parg == NULL) {
+ wolfSSL_BIO_ADDR_clear(&bio->peer_addr);
+ bio->connected = 0;
+ }
+ else {
+ socklen_t addr_size = wolfSSL_BIO_ADDR_size((WOLFSSL_BIO_ADDR *)parg);
+ if (addr_size == 0) {
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+ XMEMCPY(&bio->peer_addr, parg, addr_size);
+ bio->connected = 1;
+ }
+ ret = WOLFSSL_SUCCESS;
+ break;
+
+ case WOLFSSL_BIO_CTRL_DGRAM_QUERY_MTU:
+ ret = 0; /* not implemented */
+ break;
+
+#endif /* WOLFSSL_HAVE_BIO_ADDR */
+
default:
WOLFSSL_MSG("CMD not yet implemented");
ret = WOLFSSL_FAILURE;
@@ -817,8 +962,51 @@ int wolfSSL_BIO_up_ref(WOLFSSL_BIO* bio)
return WOLFSSL_FAILURE;
}
+
+#ifdef WOLFSSL_HAVE_BIO_ADDR
+WOLFSSL_BIO_ADDR *wolfSSL_BIO_ADDR_new(void) {
+ WOLFSSL_BIO_ADDR *addr =
+ (WOLFSSL_BIO_ADDR *)XMALLOC(sizeof(*addr), NULL, DYNAMIC_TYPE_BIO);
+ if (addr)
+ addr->sa.sa_family = AF_UNSPEC;
+ return addr;
+}
+
+void wolfSSL_BIO_ADDR_free(WOLFSSL_BIO_ADDR *addr) {
+ XFREE(addr, NULL, DYNAMIC_TYPE_BIO);
+}
+
+void wolfSSL_BIO_ADDR_clear(WOLFSSL_BIO_ADDR *addr) {
+ if (addr == NULL)
+ return;
+ XMEMSET(addr, 0, sizeof(*addr));
+ addr->sa.sa_family = AF_UNSPEC;
+}
+
+socklen_t wolfSSL_BIO_ADDR_size(const WOLFSSL_BIO_ADDR *addr) {
+ switch (addr->sa.sa_family) {
+#ifndef WOLFSSL_NO_BIO_ADDR_IN
+ case AF_INET:
+ return sizeof(addr->sa_in);
+#endif
+#ifdef WOLFSSL_IPV6
+ case AF_INET6:
+ return sizeof(addr->sa_in6);
#endif
+#if defined(HAVE_SYS_UN_H) && !defined(WOLFSSL_NO_SOCKADDR_UN)
+ case AF_UNIX:
+ return sizeof(addr->sa_un);
+#endif
+ default:
+ /* must return zero if length can't be determined, to avoid buffer
+ * overruns in callers.
+ */
+ return 0;
+ }
+}
+#endif /* WOLFSSL_HAVE_BIO_ADDR */
+#endif /* OPENSSL_ALL || OPENSSL_EXTRA */
/* helper function for wolfSSL_BIO_gets
* size till a newline is hit
@@ -879,15 +1067,15 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz)
switch (bio->type) {
#ifndef NO_FILESYSTEM
case WOLFSSL_BIO_FILE:
- if (((XFILE)bio->ptr) == XBADFILE) {
+ if (bio->ptr.fh == XBADFILE) {
return WOLFSSL_BIO_ERROR;
}
#if defined(MICRIUM) || defined(LSR_FS) || defined(EBSNET)
WOLFSSL_MSG("XFGETS not ported for this system yet");
- ret = XFGETS(buf, sz, (XFILE)bio->ptr);
+ ret = XFGETS(buf, sz, bio->ptr.fh);
#else
- if (XFGETS(buf, sz, (XFILE)bio->ptr) != NULL) {
+ if (XFGETS(buf, sz, bio->ptr.fh) != NULL) {
ret = (int)XSTRLEN(buf);
}
else {
@@ -955,7 +1143,7 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz)
ret = wolfSSL_BIO_nread(bio, &c, cSz);
if (ret > 0 && ret < sz) {
- XMEMCPY(buf, c, ret);
+ XMEMCPY(buf, c, (size_t)ret);
}
break;
}
@@ -963,21 +1151,25 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz)
#ifndef WOLFCRYPT_ONLY
/* call final on hash */
case WOLFSSL_BIO_MD:
- if (wolfSSL_EVP_MD_CTX_size((WOLFSSL_EVP_MD_CTX*)bio->ptr) > sz) {
+ if (wolfSSL_EVP_MD_CTX_size(bio->ptr.md_ctx) > sz) {
WOLFSSL_MSG("Output buffer was too small for digest");
ret = WOLFSSL_FAILURE;
}
else {
unsigned int szOut = 0;
- ret = wolfSSL_EVP_DigestFinal((WOLFSSL_EVP_MD_CTX*)bio->ptr,
+ ret = wolfSSL_EVP_DigestFinal(bio->ptr.md_ctx,
(unsigned char*)buf, &szOut);
if (ret == WOLFSSL_SUCCESS) {
- ret = szOut;
+ ret = (int)szOut;
}
}
break;
#endif /* WOLFCRYPT_ONLY */
+ case WOLFSSL_BIO_NULL:
+ ret = 0;
+ break;
+
default:
WOLFSSL_MSG("BIO type not supported yet with wolfSSL_BIO_gets");
}
@@ -1073,13 +1265,13 @@ size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio)
return 0;
if (bio->type == WOLFSSL_BIO_MEMORY) {
- return bio->wrSz;
+ return (size_t)bio->wrSz;
}
/* type BIO_BIO then check paired buffer */
if (bio->type == WOLFSSL_BIO_BIO && bio->pair != NULL) {
WOLFSSL_BIO* pair = bio->pair;
- return pair->wrIdx;
+ return (size_t)pair->wrIdx;
}
return 0;
@@ -1124,13 +1316,13 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
}
#ifndef WOLFCRYPT_ONLY
- if (bio->type == WOLFSSL_BIO_SSL && bio->ptr != NULL) {
- return (long)wolfSSL_pending((WOLFSSL*)bio->ptr);
+ if (bio->type == WOLFSSL_BIO_SSL && bio->ptr.ssl != NULL) {
+ return (size_t)wolfSSL_pending(bio->ptr.ssl);
}
#endif
if (bio->type == WOLFSSL_BIO_MEMORY) {
- return bio->wrSz - bio->rdIdx;
+ return (size_t)(bio->wrSz - bio->rdIdx);
}
/* type BIO_BIO then check paired buffer */
@@ -1139,11 +1331,12 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
if (pair->wrIdx > 0 && pair->wrIdx <= pair->rdIdx) {
/* in wrap around state where beginning of buffer is being
* overwritten */
- return pair->wrSz - pair->rdIdx + pair->wrIdx;
+ return ((size_t)pair->wrSz) - ((size_t)pair->rdIdx) +
+ ((size_t)pair->wrIdx);
}
else {
/* simple case where has not wrapped around */
- return pair->wrIdx - pair->rdIdx;
+ return (size_t)(pair->wrIdx - pair->rdIdx);
}
}
return 0;
@@ -1153,7 +1346,7 @@ size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio)
long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr)
{
WOLFSSL_BIO* front = bio;
- long ret = WOLFSSL_FAILURE;
+ long ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
WOLFSSL_ENTER("wolfSSL_BIO_get_mem_ptr");
@@ -1179,7 +1372,10 @@ long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr)
bio = bio->prev;
}
- return ret;
+ if (ret == WOLFSSL_SUCCESS)
+ return ret;
+ else
+ return WOLFSSL_FAILURE;
}
#ifdef OPENSSL_ALL
@@ -1187,7 +1383,7 @@ long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr)
int closeFlag)
{
if (!bio || !bufMem ||
- (closeFlag != BIO_NOCLOSE && closeFlag != BIO_CLOSE))
+ (closeFlag != WOLFSSL_BIO_NOCLOSE && closeFlag != WOLFSSL_BIO_CLOSE))
return BAD_FUNC_ARG;
if (bio->mem_buf)
@@ -1195,12 +1391,12 @@ long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr)
wolfSSL_BUF_MEM_free(bio->mem_buf);
bio->mem_buf = bufMem;
- bio->shutdown = closeFlag;
+ bio->shutdown = closeFlag ? WOLFSSL_BIO_CLOSE : WOLFSSL_BIO_NOCLOSE;
bio->wrSz = (int)bio->mem_buf->length;
bio->wrSzReset = bio->wrSz;
- bio->num = (int)bio->mem_buf->max;
- bio->ptr = bio->mem_buf->data;
+ bio->num.length = bio->mem_buf->max;
+ bio->ptr.mem_buf_data = (byte *)bio->mem_buf->data;
bio->wrIdx = 0;
bio->rdIdx = 0;
@@ -1208,7 +1404,7 @@ long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr)
}
#endif
-WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg)
+long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg)
{
(void) bp;
(void) cmd;
@@ -1233,15 +1429,16 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size)
return WOLFSSL_FAILURE;
}
- if (bio->ptr != NULL) {
- XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ if (bio->ptr.mem_buf_data != NULL) {
+ XFREE(bio->ptr.mem_buf_data, bio->heap, DYNAMIC_TYPE_OPENSSL);
}
- bio->ptr = (byte*)XMALLOC(size, bio->heap, DYNAMIC_TYPE_OPENSSL);
- if (bio->ptr == NULL) {
+ bio->ptr.mem_buf_data = (byte*)XMALLOC((size_t)size, bio->heap,
+ DYNAMIC_TYPE_OPENSSL);
+ if (bio->ptr.mem_buf_data == NULL) {
WOLFSSL_MSG("Memory allocation error");
bio->wrSz = 0;
- bio->num = 0;
+ bio->num.length = 0;
bio->wrIdx = 0;
bio->rdIdx = 0;
if (bio->mem_buf != NULL) {
@@ -1252,13 +1449,13 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size)
return WOLFSSL_FAILURE;
}
bio->wrSz = (int)size;
- bio->num = (int)size;
+ bio->num.length = (size_t)size;
bio->wrIdx = 0;
bio->rdIdx = 0;
if (bio->mem_buf != NULL) {
- bio->mem_buf->data = (char*)bio->ptr;
- bio->mem_buf->length = bio->num;
- bio->mem_buf->max = bio->num;
+ bio->mem_buf->data = (char*)bio->ptr.mem_buf_data;
+ bio->mem_buf->length = bio->num.length;
+ bio->mem_buf->max = bio->num.length;
}
return WOLFSSL_SUCCESS;
@@ -1286,12 +1483,12 @@ int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2)
}
/* set default write size if not already set */
- if (b1->ptr == NULL && wolfSSL_BIO_set_write_buf_size(b1,
+ if (b1->ptr.mem_buf_data == NULL && wolfSSL_BIO_set_write_buf_size(b1,
WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) {
return WOLFSSL_FAILURE;
}
- if (b2->ptr == NULL && wolfSSL_BIO_set_write_buf_size(b2,
+ if (b2->ptr.mem_buf_data == NULL && wolfSSL_BIO_set_write_buf_size(b2,
WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) {
return WOLFSSL_FAILURE;
}
@@ -1332,7 +1529,7 @@ int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf)
WOLFSSL_BIO* pair = bio->pair;
/* case where have wrapped around write buffer */
- *buf = (char*)pair->ptr + pair->rdIdx;
+ *buf = (char*)pair->ptr.mem_buf_data + pair->rdIdx;
if (pair->wrIdx > 0 && pair->rdIdx >= pair->wrIdx) {
return pair->wrSz - pair->rdIdx;
}
@@ -1364,7 +1561,7 @@ int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num)
if (bio->pair != NULL) {
/* special case if asking to read 0 bytes */
if (num == 0) {
- *buf = (char*)bio->pair->ptr + bio->pair->rdIdx;
+ *buf = (char*)bio->pair->ptr.mem_buf_data + bio->pair->rdIdx;
return 0;
}
@@ -1378,6 +1575,9 @@ int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num)
sz = num;
}
bio->pair->rdIdx += sz;
+#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
+ bio->pair->bytes_read += (word32)sz;
+#endif
/* check if have read to the end of the buffer and need to reset */
if (bio->pair->rdIdx == bio->pair->wrSz) {
@@ -1415,7 +1615,7 @@ int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num)
if (bio->pair != NULL) {
if (num == 0) {
- *buf = (char*)bio->ptr + bio->wrIdx;
+ *buf = (char*)bio->ptr.mem_buf_data + bio->wrIdx;
return 0;
}
@@ -1454,8 +1654,11 @@ int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num)
if (num < sz) {
sz = num;
}
- *buf = (char*)bio->ptr + bio->wrIdx;
+ *buf = (char*)bio->ptr.mem_buf_data + bio->wrIdx;
bio->wrIdx += sz;
+#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
+ bio->bytes_written += (word32)sz;
+#endif
/* if at the end of the buffer and space for wrap around then set
* write index back to 0 */
@@ -1467,6 +1670,37 @@ int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num)
return sz;
}
+#ifdef WOLFSSL_BIO_HAVE_FLOW_STATS
+word64 wolfSSL_BIO_number_read(WOLFSSL_BIO *bio)
+{
+ word64 ret = 0;
+ if (bio == NULL) {
+ WOLFSSL_MSG("NULL argument passed in");
+ return 0;
+ }
+ while (bio) {
+ ret += bio->bytes_read;
+ bio = bio->next;
+ }
+
+ return ret;
+}
+
+word64 wolfSSL_BIO_number_written(WOLFSSL_BIO *bio)
+{
+ word64 ret = 0;
+ if (bio == NULL) {
+ WOLFSSL_MSG("NULL argument passed in");
+ return 0;
+ }
+ while (bio) {
+ ret += bio->bytes_written;
+ bio = bio->next;
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_BIO_HAVE_FLOW_STATS */
/* Reset BIO to initial state */
int wolfSSL_BIO_reset(WOLFSSL_BIO *bio)
@@ -1482,46 +1716,46 @@ int wolfSSL_BIO_reset(WOLFSSL_BIO *bio)
switch (bio->type) {
#ifndef NO_FILESYSTEM
case WOLFSSL_BIO_FILE:
- if (XFSEEK((XFILE)bio->ptr, 0, XSEEK_SET) != 0)
+ if (XFSEEK(bio->ptr.fh, 0, XSEEK_SET) != 0)
return WOLFSSL_BIO_ERROR;
else
- return 0;
+ return WOLFSSL_SUCCESS;
#endif
case WOLFSSL_BIO_BIO:
bio->rdIdx = 0;
bio->wrIdx = 0;
- return 0;
+ return WOLFSSL_SUCCESS;
case WOLFSSL_BIO_MEMORY:
bio->rdIdx = 0;
- if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
+ if (bio->flags & WOLFSSL_BIO_FLAG_MEM_RDONLY) {
bio->wrIdx = bio->wrSzReset;
bio->wrSz = bio->wrSzReset;
}
else {
bio->wrSz = 0;
- XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
- bio->ptr = NULL;
- bio->num = 0;
+ XFREE(bio->ptr.mem_buf_data, bio->heap, DYNAMIC_TYPE_OPENSSL);
+ bio->ptr.mem_buf_data = NULL;
+ bio->num.length = 0;
if (bio->mem_buf != NULL) {
bio->mem_buf->data = NULL;
bio->mem_buf->length = 0;
bio->mem_buf->max = 0;
}
}
- return 0;
+ return WOLFSSL_SUCCESS;
#ifndef WOLFCRYPT_ONLY
case WOLFSSL_BIO_MD:
- if (bio->ptr != NULL) {
+ if (bio->ptr.md_ctx != NULL) {
const WOLFSSL_EVP_MD* md =
- wolfSSL_EVP_MD_CTX_md((WOLFSSL_EVP_MD_CTX*)bio->ptr);
- wolfSSL_EVP_MD_CTX_cleanup((WOLFSSL_EVP_MD_CTX*)bio->ptr);
- wolfSSL_EVP_MD_CTX_init((WOLFSSL_EVP_MD_CTX*)bio->ptr);
- wolfSSL_EVP_DigestInit((WOLFSSL_EVP_MD_CTX*)bio->ptr, md);
+ wolfSSL_EVP_MD_CTX_md(bio->ptr.md_ctx);
+ wolfSSL_EVP_MD_CTX_cleanup(bio->ptr.md_ctx);
+ wolfSSL_EVP_MD_CTX_init(bio->ptr.md_ctx);
+ wolfSSL_EVP_DigestInit(bio->ptr.md_ctx, md);
}
- return 0;
+ return WOLFSSL_SUCCESS;
#endif /* WOLFCRYPT_ONLY */
default:
@@ -1571,7 +1805,7 @@ long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c)
}
bio->shutdown = (byte)c;
- bio->ptr = (XFILE)fp;
+ bio->ptr.fh = fp;
return WOLFSSL_SUCCESS;
}
@@ -1589,7 +1823,7 @@ long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp)
return WOLFSSL_FAILURE;
}
- *fp = (XFILE)bio->ptr;
+ *fp = bio->ptr.fh;
return WOLFSSL_SUCCESS;
}
@@ -1604,15 +1838,20 @@ int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name)
}
if (bio->type == WOLFSSL_BIO_FILE) {
- if (((XFILE)bio->ptr) != XBADFILE && bio->shutdown == BIO_CLOSE) {
- XFCLOSE((XFILE)bio->ptr);
+ if (bio->ptr.fh != XBADFILE && bio->shutdown == WOLFSSL_BIO_CLOSE) {
+ XFCLOSE(bio->ptr.fh);
}
- bio->ptr = XFOPEN(name, "w");
- if (((XFILE)bio->ptr) == XBADFILE) {
+ /* 'b' flag is ignored on POSIX targets, but on Windows it assures
+ * inhibition of LF<->CRLF rewriting, so that there is consistency
+ * between the size and contents of the representation in memory and on
+ * disk.
+ */
+ bio->ptr.fh = XFOPEN(name, "wb");
+ if (bio->ptr.fh == XBADFILE) {
return WOLFSSL_FAILURE;
}
- bio->shutdown = BIO_CLOSE;
+ bio->shutdown = WOLFSSL_BIO_CLOSE;
return WOLFSSL_SUCCESS;
}
@@ -1626,13 +1865,13 @@ int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs)
WOLFSSL_ENTER("wolfSSL_BIO_seek");
if (bio == NULL) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* offset ofs from beginning of file */
if (bio->type == WOLFSSL_BIO_FILE &&
- XFSEEK((XFILE)bio->ptr, ofs, SEEK_SET) < 0) {
- return -1;
+ XFSEEK(bio->ptr.fh, ofs, SEEK_SET) < 0) {
+ return WOLFSSL_FATAL_ERROR;
}
return 0;
@@ -1649,16 +1888,16 @@ int wolfSSL_BIO_tell(WOLFSSL_BIO* bio)
WOLFSSL_ENTER("wolfSSL_BIO_tell");
if (bio == NULL) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (bio->type != WOLFSSL_BIO_FILE) {
return 0;
}
- pos = (int)XFTELL((XFILE)bio->ptr);
+ pos = (int)XFTELL(bio->ptr.fh);
if (pos < 0)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
else
return pos;
}
@@ -1679,7 +1918,7 @@ long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v)
int wolfSSL_BIO_get_len(WOLFSSL_BIO *bio)
{
- int len;
+ int len = 0;
#ifndef NO_FILESYSTEM
long memSz = 0;
XFILE file;
@@ -1785,15 +2024,16 @@ long wolfSSL_BIO_set_nbio(WOLFSSL_BIO* bio, long on)
if (bio) {
switch (bio->type) {
case WOLFSSL_BIO_SOCKET:
+ case WOLFSSL_BIO_DGRAM:
#ifdef XFCNTL
{
int ret;
- int flag = XFCNTL(bio->num, F_GETFL, 0);
+ int flag = XFCNTL(bio->num.fd, F_GETFL, 0);
if (on) {
- ret = XFCNTL(bio->num, F_SETFL, flag | O_NONBLOCK);
+ ret = XFCNTL(bio->num.fd, F_SETFL, flag | O_NONBLOCK);
}
else {
- ret = XFCNTL(bio->num, F_SETFL, flag & ~O_NONBLOCK);
+ ret = XFCNTL(bio->num.fd, F_SETFL, flag & ~O_NONBLOCK);
}
if (ret == -1) {
@@ -1804,7 +2044,7 @@ long wolfSSL_BIO_set_nbio(WOLFSSL_BIO* bio, long on)
break;
case WOLFSSL_BIO_SSL:
#ifdef WOLFSSL_DTLS
- wolfSSL_dtls_set_using_nonblock((WOLFSSL*)bio->ptr, (int)on);
+ wolfSSL_dtls_set_using_nonblock(bio->ptr.ssl, (int)on);
#endif
break;
@@ -1952,7 +2192,7 @@ int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p)
}
if (p) {
- *(byte**)p = (byte*)mem_bio->ptr + mem_bio->rdIdx;
+ *(byte**)p = mem_bio->ptr.mem_buf_data + mem_bio->rdIdx;
}
return mem_bio->wrSz - mem_bio->rdIdx;
@@ -1973,11 +2213,11 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
if (bio->method != NULL && bio->method->ctrlCb != NULL) {
WOLFSSL_MSG("Calling custom BIO flush callback");
- return (int)bio->method->ctrlCb(bio, BIO_CTRL_FLUSH, 0, NULL);
+ return (int)bio->method->ctrlCb(bio, WOLFSSL_BIO_CTRL_FLUSH, 0, NULL);
}
else if (bio->type == WOLFSSL_BIO_FILE) {
#if !defined(NO_FILESYSTEM) && defined(XFFLUSH)
- if (XFFLUSH((FILE *)bio->ptr) != 0)
+ if (XFFLUSH(bio->ptr.fh) != 0)
return WOLFSSL_FAILURE;
#endif /* !NO_FILESYSTEM && XFFLUSH */
@@ -2001,14 +2241,17 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
/* return the context and initialize the BIO state */
int wolfSSL_BIO_get_md_ctx(WOLFSSL_BIO *bio, WOLFSSL_EVP_MD_CTX **mdcp)
{
- int ret = WOLFSSL_FAILURE;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
if ((bio != NULL) && (mdcp != NULL)) {
- *mdcp = (WOLFSSL_EVP_MD_CTX*)bio->ptr;
+ *mdcp = bio->ptr.md_ctx;
ret = WOLFSSL_SUCCESS;
}
- return ret;
+ if (ret == WOLFSSL_SUCCESS)
+ return ret;
+ else
+ return WOLFSSL_FAILURE;
}
WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void)
@@ -2076,6 +2319,15 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
return &meth;
}
+ WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_null(void)
+ {
+ static WOLFSSL_BIO_METHOD meth =
+ WOLFSSL_BIO_METHOD_INIT(WOLFSSL_BIO_NULL);
+
+ WOLFSSL_ENTER("wolfSSL_BIO_s_null");
+
+ return &meth;
+ }
WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void)
{
@@ -2096,10 +2348,37 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
if (bio) {
bio->type = WOLFSSL_BIO_SOCKET;
bio->shutdown = (byte)closeF;
- bio->num = sfd;
+ bio->num.fd = (SOCKET_T)sfd;
+ }
+ return bio;
+ }
+
+
+#if defined(WOLFSSL_HAVE_BIO_ADDR) && defined(WOLFSSL_DTLS)
+ WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_datagram(void)
+ {
+ static WOLFSSL_BIO_METHOD meth =
+ WOLFSSL_BIO_METHOD_INIT(WOLFSSL_BIO_DGRAM);
+
+ WOLFSSL_ENTER("wolfSSL_BIO_s_datagram");
+
+ return &meth;
+ }
+
+
+ WOLFSSL_BIO* wolfSSL_BIO_new_dgram(int fd, int closeF)
+ {
+ WOLFSSL_BIO* bio = wolfSSL_BIO_new(wolfSSL_BIO_s_datagram());
+
+ WOLFSSL_ENTER("wolfSSL_BIO_new_dgram");
+ if (bio) {
+ bio->shutdown = (byte)closeF;
+ bio->num.fd = (SOCKET_T)fd;
}
return bio;
}
+#endif
+
/**
* Create new socket BIO object. This is a pure TCP connection with
@@ -2113,22 +2392,38 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
WOLFSSL_ENTER("wolfSSL_BIO_new_connect");
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_socket());
if (bio) {
- const char* port = XSTRSTR(str, ":");
+ const char* port;
+#ifdef WOLFSSL_IPV6
+ const char* ipv6Start = XSTRSTR(str, "[");
+ const char* ipv6End = XSTRSTR(str, "]");
+
+ if (ipv6End)
+ port = XSTRSTR(ipv6End, ":");
+ else
+#endif
+ port = XSTRSTR(str, ":");
if (port != NULL)
bio->port = (word16)XATOI(port + 1);
else
port = str + XSTRLEN(str); /* point to null terminator */
- bio->ip = (char*)XMALLOC((port - str) + 1, /* +1 for null char */
+#ifdef WOLFSSL_IPV6
+ if (ipv6Start && ipv6End) {
+ str = ipv6Start + 1;
+ port = ipv6End;
+ }
+#endif
+ bio->ip = (char*)XMALLOC(
+ (size_t)(port - str) + 1, /* +1 for null char */
bio->heap, DYNAMIC_TYPE_OPENSSL);
if (bio->ip != NULL) {
- XMEMCPY(bio->ip, str, port - str);
+ XMEMCPY(bio->ip, str, (size_t)(port - str));
bio->ip[port - str] = '\0';
bio->type = WOLFSSL_BIO_SOCKET;
}
else {
- BIO_free(bio);
+ wolfSSL_BIO_free(bio);
bio = NULL;
}
}
@@ -2145,9 +2440,21 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
{
WOLFSSL_BIO *bio;
WOLFSSL_ENTER("wolfSSL_BIO_new_accept");
+
+ if (port == NULL) {
+ return NULL;
+ }
+
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_socket());
if (bio) {
- bio->port = (word16)XATOI(port);
+ const char* portStr = port;
+#ifdef WOLFSSL_IPV6
+ const char* ipv6End = XSTRSTR(port, "]");
+ if (ipv6End) {
+ portStr = XSTRSTR(ipv6End, ":");
+ }
+#endif
+ bio->port = (word16)XATOI(portStr);
bio->type = WOLFSSL_BIO_SOCKET;
}
return bio;
@@ -2217,8 +2524,8 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
return WOLFSSL_FAILURE;
}
- b->num = (int)sfd;
- b->shutdown = BIO_CLOSE;
+ b->num.fd = sfd;
+ b->shutdown = WOLFSSL_BIO_CLOSE;
return WOLFSSL_SUCCESS;
}
@@ -2241,23 +2548,23 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
return WOLFSSL_FAILURE;
}
- if (b->num == WOLFSSL_BIO_ERROR) {
+ if (b->num.fd == SOCKET_INVALID) {
if (wolfIO_TcpBind(&sfd, b->port) < 0) {
WOLFSSL_MSG("wolfIO_TcpBind error");
return WOLFSSL_FAILURE;
}
- b->num = (int)sfd;
- b->shutdown = BIO_CLOSE;
+ b->num.fd = sfd;
+ b->shutdown = WOLFSSL_BIO_CLOSE;
}
else {
WOLFSSL_BIO* new_bio;
- int newfd = wolfIO_TcpAccept(b->num, NULL, NULL);
+ int newfd = wolfIO_TcpAccept(b->num.fd, NULL, NULL);
if (newfd < 0) {
WOLFSSL_MSG("wolfIO_TcpBind error");
return WOLFSSL_FAILURE;
}
/* Create a socket BIO for using the accept'ed connection */
- new_bio = wolfSSL_BIO_new_socket(newfd, BIO_CLOSE);
+ new_bio = wolfSSL_BIO_new_socket(newfd, WOLFSSL_BIO_CLOSE);
if (new_bio == NULL) {
WOLFSSL_MSG("wolfSSL_BIO_new_socket error");
CloseSocket(newfd);
@@ -2301,6 +2608,7 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
return ret;
}
+#ifndef NO_TLS
long wolfSSL_BIO_do_handshake(WOLFSSL_BIO *b)
{
WOLFSSL_ENTER("wolfSSL_BIO_do_handshake");
@@ -2308,8 +2616,8 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
- if (b->type == WOLFSSL_BIO_SSL && b->ptr != NULL) {
- return wolfSSL_negotiate((WOLFSSL*)b->ptr);
+ if (b->type == WOLFSSL_BIO_SSL && b->ptr.ssl != NULL) {
+ return wolfSSL_negotiate(b->ptr.ssl);
}
else {
WOLFSSL_MSG("Not SSL BIO or no SSL object set");
@@ -2334,27 +2642,28 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
return;
}
- if (b->ptr != NULL) {
- int rc = wolfSSL_shutdown((WOLFSSL*)b->ptr);
- if (rc == SSL_SHUTDOWN_NOT_DONE) {
+ if (b->ptr.ssl != NULL) {
+ int rc = wolfSSL_shutdown(b->ptr.ssl);
+ if (rc == WOLFSSL_SHUTDOWN_NOT_DONE) {
/* In this case, call again to give us a chance to read the
* close notify alert from the other end. */
- wolfSSL_shutdown((WOLFSSL*)b->ptr);
+ wolfSSL_shutdown(b->ptr.ssl);
}
}
else {
WOLFSSL_MSG("BIO has no SSL pointer set.");
}
}
+#endif
long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF)
{
- long ret = WOLFSSL_FAILURE;
+ long ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
WOLFSSL_ENTER("wolfSSL_BIO_set_ssl");
if (b != NULL) {
- b->ptr = ssl;
+ b->ptr.ssl = ssl;
b->shutdown = (byte)closeF;
if (b->next != NULL)
wolfSSL_set_bio(ssl, b->next, b->next);
@@ -2362,7 +2671,10 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
ret = WOLFSSL_SUCCESS;
}
- return ret;
+ if (ret == WOLFSSL_SUCCESS)
+ return ret;
+ else
+ return WOLFSSL_FAILURE;
}
long wolfSSL_BIO_get_ssl(WOLFSSL_BIO* bio, WOLFSSL** ssl)
@@ -2382,7 +2694,7 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
return WOLFSSL_FAILURE;
}
- *ssl = (WOLFSSL*)bio->ptr;
+ *ssl = bio->ptr.ssl;
return WOLFSSL_SUCCESS;
}
@@ -2420,7 +2732,7 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
else
wolfSSL_set_connect_state(ssl);
}
- if (err == 0 && wolfSSL_BIO_set_ssl(sslBio, ssl, BIO_CLOSE) !=
+ if (err == 0 && wolfSSL_BIO_set_ssl(sslBio, ssl, WOLFSSL_BIO_CLOSE) !=
WOLFSSL_SUCCESS) {
WOLFSSL_MSG("Failed to set SSL pointer in BIO.");
err = 1;
@@ -2504,9 +2816,23 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
}
else {
size_t currLen = XSTRLEN(b->ip);
+ #ifdef WOLFSSL_NO_REALLOC
+ char* tmp = NULL;
+ #endif
+
if (currLen != newLen) {
+ #ifdef WOLFSSL_NO_REALLOC
+ tmp = b->ip;
+ b->ip = (char*)XMALLOC(newLen+1, b->heap, DYNAMIC_TYPE_OPENSSL);
+ if (b->ip != NULL && tmp != NULL) {
+ XMEMCPY(b->ip, tmp, newLen);
+ XFREE(tmp, b->heap, DYNAMIC_TYPE_OPENSSL);
+ tmp = NULL;
+ }
+ #else
b->ip = (char*)XREALLOC(b->ip, newLen + 1, b->heap,
DYNAMIC_TYPE_OPENSSL);
+ #endif
if (b->ip == NULL) {
WOLFSSL_MSG("Hostname realloc failed.");
return WOLFSSL_FAILURE;
@@ -2526,7 +2852,7 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
WOLFSSL_ENTER("wolfSSL_BIO_set_fd");
if (b != NULL) {
- b->num = fd;
+ b->num.fd = (SOCKET_T)fd;
b->shutdown = (byte)closeF;
}
@@ -2569,8 +2895,22 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
#else
bio->method = method;
#endif
- bio->shutdown = BIO_CLOSE; /* default to close things */
- bio->num = WOLFSSL_BIO_ERROR;
+ bio->shutdown = WOLFSSL_BIO_CLOSE; /* default to close things */
+
+ if ((bio->type == WOLFSSL_BIO_SOCKET) ||
+ (bio->type == WOLFSSL_BIO_DGRAM))
+ {
+ bio->num.fd = SOCKET_INVALID;
+ }
+ else if (bio->type == WOLFSSL_BIO_FILE) {
+#ifndef NO_FILESYSTEM
+ bio->ptr.fh = XBADFILE;
+#endif
+ bio->num.fd = SOCKET_INVALID;
+ }
+ else {
+ bio->num.length = 0;
+ }
bio->init = 1;
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
@@ -2602,8 +2942,8 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
}
if (method->type == WOLFSSL_BIO_MD) {
- bio->ptr = wolfSSL_EVP_MD_CTX_new();
- if (bio->ptr == NULL) {
+ bio->ptr.md_ctx = wolfSSL_EVP_MD_CTX_new();
+ if (bio->ptr.md_ctx == NULL) {
WOLFSSL_MSG("Memory error");
wolfSSL_BIO_free(bio);
return NULL;
@@ -2637,17 +2977,17 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
len = (int)XSTRLEN((const char*)buf) + 1;
}
- if (len > 0 && wolfSSL_BUF_MEM_resize(bio->mem_buf, len) == 0) {
+ if (len > 0 && wolfSSL_BUF_MEM_resize(bio->mem_buf, (size_t)len) == 0) {
wolfSSL_BIO_free(bio);
return NULL;
}
- bio->num = (int)bio->mem_buf->max;
+ bio->num.length = bio->mem_buf->max;
bio->wrSz = len;
- bio->ptr = bio->mem_buf->data;
- if (len > 0 && bio->ptr != NULL) {
- XMEMCPY(bio->ptr, buf, len);
- bio->flags |= BIO_FLAGS_MEM_RDONLY;
+ bio->ptr.mem_buf_data = (byte *)bio->mem_buf->data;
+ if (len > 0 && bio->ptr.mem_buf_data != NULL) {
+ XMEMCPY(bio->ptr.mem_buf_data, buf, (size_t)len);
+ bio->flags |= WOLFSSL_BIO_FLAG_MEM_RDONLY;
bio->wrSzReset = bio->wrSz;
}
@@ -2709,44 +3049,53 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
bio->pair->pair = NULL;
}
- if (bio->ip != NULL) {
- XFREE(bio->ip, bio->heap, DYNAMIC_TYPE_OPENSSL);
- }
+ XFREE(bio->ip, bio->heap, DYNAMIC_TYPE_OPENSSL);
if (bio->shutdown) {
- if (bio->type == WOLFSSL_BIO_SSL && bio->ptr)
- wolfSSL_free((WOLFSSL*)bio->ptr);
+ if (bio->type == WOLFSSL_BIO_SSL && bio->ptr.ssl)
+ wolfSSL_free(bio->ptr.ssl);
#ifdef CloseSocket
- if ((bio->type == WOLFSSL_BIO_SOCKET) && (bio->num > 0))
- CloseSocket(bio->num);
+ if (((bio->type == WOLFSSL_BIO_SOCKET) ||
+ (bio->type == WOLFSSL_BIO_DGRAM)) &&
+ (bio->num.fd != SOCKET_INVALID))
+ {
+ CloseSocket(bio->num.fd);
+ }
#endif
}
#ifndef NO_FILESYSTEM
- if (bio->type == WOLFSSL_BIO_FILE && bio->shutdown == BIO_CLOSE) {
- if (bio->ptr) {
- XFCLOSE((XFILE)bio->ptr);
+ if (bio->type == WOLFSSL_BIO_FILE &&
+ bio->shutdown == WOLFSSL_BIO_CLOSE)
+ {
+ if (bio->ptr.fh) {
+ XFCLOSE(bio->ptr.fh);
}
#if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\
&& !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2)
- else if (bio->num != WOLFSSL_BIO_ERROR) {
- XCLOSE(bio->num);
+ else if (bio->num.fd != SOCKET_INVALID) {
+ XCLOSE(bio->num.fd);
}
#endif
}
#endif
- if (bio->shutdown != BIO_NOCLOSE) {
- if (bio->type == WOLFSSL_BIO_MEMORY && bio->ptr != NULL) {
+ if (bio->shutdown != WOLFSSL_BIO_NOCLOSE) {
+ if (bio->type == WOLFSSL_BIO_MEMORY &&
+ bio->ptr.mem_buf_data != NULL)
+ {
if (bio->mem_buf != NULL) {
- if (bio->mem_buf->data != (char*)bio->ptr) {
- XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
- bio->ptr = NULL;
+ if ((byte *)bio->mem_buf->data != bio->ptr.mem_buf_data)
+ {
+ XFREE(bio->ptr.mem_buf_data, bio->heap,
+ DYNAMIC_TYPE_OPENSSL);
+ bio->ptr.mem_buf_data = NULL;
}
}
else {
- XFREE(bio->ptr, bio->heap, DYNAMIC_TYPE_OPENSSL);
- bio->ptr = NULL;
+ XFREE(bio->ptr.mem_buf_data, bio->heap,
+ DYNAMIC_TYPE_OPENSSL);
+ bio->ptr.mem_buf_data = NULL;
}
}
if (bio->mem_buf != NULL) {
@@ -2756,7 +3105,7 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
}
if (bio->type == WOLFSSL_BIO_MD) {
- wolfSSL_EVP_MD_CTX_free((WOLFSSL_EVP_MD_CTX*)bio->ptr);
+ wolfSSL_EVP_MD_CTX_free(bio->ptr.md_ctx);
}
XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
@@ -2795,8 +3144,8 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
}
/* SSL BIO's should use the next object in the chain for IO */
- if (top->type == WOLFSSL_BIO_SSL && top->ptr)
- wolfSSL_set_bio((WOLFSSL*)top->ptr, append, append);
+ if (top->type == WOLFSSL_BIO_SSL && top->ptr.ssl)
+ wolfSSL_set_bio(top->ptr.ssl, append, append);
return top;
}
@@ -2900,9 +3249,11 @@ int wolfSSL_BIO_get_fd(WOLFSSL_BIO *bio, int* fd)
WOLFSSL_ENTER("wolfSSL_BIO_get_fd");
if (bio != NULL) {
+ if (bio->num.fd == SOCKET_INVALID)
+ return WOLFSSL_BIO_ERROR;
if (fd != NULL)
- *fd = bio->num;
- return bio->num;
+ *fd = (int)bio->num.fd;
+ return (int)bio->num.fd;
}
return WOLFSSL_BIO_ERROR;
@@ -2977,10 +3328,10 @@ int wolfSSL_BIO_vprintf(WOLFSSL_BIO* bio, const char* format, va_list args)
switch (bio->type) {
#if !defined(NO_FILESYSTEM)
case WOLFSSL_BIO_FILE:
- if (bio->ptr == NULL) {
- return -1;
+ if (bio->ptr.fh == XBADFILE) {
+ return WOLFSSL_FATAL_ERROR;
}
- ret = XVFPRINTF((XFILE)bio->ptr, format, args);
+ ret = XVFPRINTF(bio->ptr.fh, format, args);
break;
#endif
@@ -2988,7 +3339,7 @@ int wolfSSL_BIO_vprintf(WOLFSSL_BIO* bio, const char* format, va_list args)
/* In Visual Studio versions prior to Visual Studio 2013, the va_* symbols
aren't defined. If using Visual Studio 2013 or later, define
HAVE_VA_COPY. */
- #if !defined(_WIN32) || defined(HAVE_VA_COPY)
+ #if defined(XVSNPRINTF) && (!defined(_WIN32) || defined(HAVE_VA_COPY))
case WOLFSSL_BIO_SSL:
{
int count;
@@ -3004,11 +3355,11 @@ int wolfSSL_BIO_vprintf(WOLFSSL_BIO* bio, const char* format, va_list args)
count = XVSNPRINTF(NULL, 0, format, args);
if (count >= 0)
{
- pt = (char*)XMALLOC(count + 1, bio->heap,
+ pt = (char*)XMALLOC((size_t)count + 1, bio->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pt != NULL)
{
- count = XVSNPRINTF(pt, count + 1, format, copy);
+ count = XVSNPRINTF(pt, (size_t)count + 1, format, copy);
if (count >= 0)
{
ret = wolfSSL_BIO_write(bio, pt, count);
@@ -3019,7 +3370,7 @@ int wolfSSL_BIO_vprintf(WOLFSSL_BIO* bio, const char* format, va_list args)
va_end(copy);
}
break;
- #endif /* !_WIN32 || HAVE_VA_COPY */
+ #endif /* XVSNPRINTF && (!_WIN32 || HAVE_VA_COPY) */
default:
WOLFSSL_MSG("Unsupported WOLFSSL_BIO type for wolfSSL_BIO_printf");
@@ -3074,21 +3425,24 @@ int wolfSSL_BIO_dump(WOLFSSL_BIO *bio, const char *buf, int length)
return wolfSSL_BIO_write(bio, "\tNULL", 5);
}
- XSPRINTF(line, "%04x - ", lineOffset);
+ (void)XSNPRINTF(line, sizeof(line), "%04x - ", lineOffset);
o = 7;
for (i = 0; i < BIO_DUMP_LINE_LEN; i++) {
if (i < length)
- XSPRINTF(line + o,"%02x ", (unsigned char)buf[i]);
+ (void)XSNPRINTF(line + o, (size_t)((int)sizeof(line) - o),
+ "%02x ", (unsigned char)buf[i]);
else
- XSPRINTF(line + o, " ");
+ (void)XSNPRINTF(line + o, (size_t)((int)sizeof(line) - o),
+ " ");
if (i == 7)
- XSPRINTF(line + o + 2, "-");
+ (void)XSNPRINTF(line + o + 2, (size_t)((int)sizeof(line) -
+ (o + 2)), "-");
o += 3;
}
- XSPRINTF(line + o, " ");
+ (void)XSNPRINTF(line + o, (size_t)((int)sizeof(line) - o), " ");
o += 2;
for (i = 0; (i < BIO_DUMP_LINE_LEN) && (i < length); i++) {
- XSPRINTF(line + o, "%c",
+ (void)XSNPRINTF(line + o, (size_t)((int)sizeof(line) - o), "%c",
((31 < buf[i]) && (buf[i] < 127)) ? buf[i] : '.');
o++;
}
@@ -3130,7 +3484,7 @@ int wolfSSL_BIO_dump(WOLFSSL_BIO *bio, const char *buf, int length)
if (fp == XBADFILE)
return WOLFSSL_BAD_FILE;
- if (wolfSSL_BIO_set_fp(b, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
+ if (wolfSSL_BIO_set_fp(b, fp, WOLFSSL_BIO_CLOSE) != WOLFSSL_SUCCESS) {
XFCLOSE(fp);
return WOLFSSL_BAD_FILE;
}
@@ -3167,7 +3521,7 @@ WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode)
return bio;
}
- if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) {
+ if (wolfSSL_BIO_set_fp(bio, fp, WOLFSSL_BIO_CLOSE) != WOLFSSL_SUCCESS) {
XFCLOSE(fp);
wolfSSL_BIO_free(bio);
bio = NULL;
diff --git a/src/src/conf.c b/src/src/conf.c
index cfc6085..e0a8b03 100644
--- a/src/src/conf.c
+++ b/src/src/conf.c
@@ -1,12 +1,12 @@
/* conf.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,12 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
-
-#ifdef HAVE_CONFIG_H
- #include
-#endif
-
-#include
+#include
#if !defined(WOLFSSL_CONF_INCLUDED)
#ifndef WOLFSSL_IGNORE_FILE_WARN
@@ -133,7 +128,7 @@ WOLFSSL_TXT_DB *wolfSSL_TXT_DB_read(WOLFSSL_BIO *in, int num)
XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
goto error;
}
- if (wolfSSL_sk_push(ret->data, strBuf) != WOLFSSL_SUCCESS) {
+ if (wolfSSL_sk_push(ret->data, strBuf) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_push error");
XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
goto error;
@@ -146,9 +141,7 @@ WOLFSSL_TXT_DB *wolfSSL_TXT_DB_read(WOLFSSL_BIO *in, int num)
wolfSSL_TXT_DB_free(ret);
ret = NULL;
}
- if (buf) {
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- }
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
@@ -204,7 +197,10 @@ long wolfSSL_TXT_DB_write(WOLFSSL_BIO *out, WOLFSSL_TXT_DB *db)
return WOLFSSL_FAILURE;
}
}
- idx[-1] = '\n';
+ if (idx > buf)
+ idx[-1] = '\n';
+ else
+ return WOLFSSL_FAILURE;
sz = (int)(idx - buf);
if (wolfSSL_BIO_write(out, buf, sz) != sz) {
@@ -228,7 +224,7 @@ int wolfSSL_TXT_DB_insert(WOLFSSL_TXT_DB *db, WOLFSSL_STRING *row)
return WOLFSSL_FAILURE;
}
- if (wolfSSL_sk_push(db->data, row) != WOLFSSL_SUCCESS) {
+ if (wolfSSL_sk_push(db->data, row) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_push error");
return WOLFSSL_FAILURE;
}
@@ -452,11 +448,11 @@ int wolfSSL_CONF_add_string(WOLFSSL_CONF *conf,
sk = (WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *)section->value;
value->section = section->section;
- if (wolfSSL_sk_CONF_VALUE_push(sk, value) != WOLFSSL_SUCCESS) {
+ if (wolfSSL_sk_CONF_VALUE_push(sk, value) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
return WOLFSSL_FAILURE;
}
- if (wolfSSL_sk_CONF_VALUE_push(conf->data, value) != WOLFSSL_SUCCESS) {
+ if (wolfSSL_sk_CONF_VALUE_push(conf->data, value) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
wolfssl_sk_pop_type(sk, STACK_TYPE_CONF_VALUE);
return WOLFSSL_FAILURE;
@@ -499,7 +495,7 @@ WOLFSSL_CONF_VALUE *wolfSSL_CONF_new_section(WOLFSSL_CONF *conf,
ret->value = (char*)sk;
- if (wolfSSL_sk_CONF_VALUE_push(conf->data, ret) != WOLFSSL_SUCCESS) {
+ if (wolfSSL_sk_CONF_VALUE_push(conf->data, ret) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
goto error;
}
@@ -605,7 +601,7 @@ char *wolfSSL_NCONF_get_string(const WOLFSSL_CONF *conf,
return NULL;
}
-int wolfSSL_NCONF_get_number(const CONF *conf, const char *group,
+int wolfSSL_NCONF_get_number(const WOLFSSL_CONF *conf, const char *group,
const char *name, long *result)
{
char *str;
@@ -772,8 +768,18 @@ static char* expandValue(WOLFSSL_CONF *conf, const char* section,
/* This will allocate slightly more memory than necessary
* but better be safe */
strLen += valueLen;
+ #ifdef WOLFSSL_NO_REALLOC
+ newRet = (char*)XMALLOC(strLen + 1, NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (newRet != NULL && ret != NULL) {
+ XMEMCPY(newRet, ret, (strLen - valueLen) + 1);
+ XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
+ ret = NULL;
+ }
+ #else
newRet = (char*)XREALLOC(ret, strLen + 1, NULL,
DYNAMIC_TYPE_OPENSSL);
+ #endif
if (!newRet) {
WOLFSSL_MSG("realloc error");
goto expand_cleanup;
@@ -793,8 +799,7 @@ static char* expandValue(WOLFSSL_CONF *conf, const char* section,
return ret ? ret : str;
expand_cleanup:
- if (ret)
- XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
+ XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
@@ -803,7 +808,7 @@ static char* expandValue(WOLFSSL_CONF *conf, const char* section,
{(idx)++;}
int wolfSSL_NCONF_load(WOLFSSL_CONF *conf, const char *file, long *eline)
{
- int ret = WOLFSSL_FAILURE;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
WOLFSSL_BIO *in = NULL;
char* buf = NULL;
char* idx = NULL;
@@ -961,8 +966,7 @@ int wolfSSL_NCONF_load(WOLFSSL_CONF *conf, const char *file, long *eline)
cleanup:
if (in)
wolfSSL_BIO_free(in);
- if (buf)
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (eline)
*eline = line;
return ret;
@@ -980,27 +984,18 @@ void wolfSSL_NCONF_free(WOLFSSL_CONF *conf)
void wolfSSL_X509V3_conf_free(WOLFSSL_CONF_VALUE *val)
{
- WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
-
if (val) {
if (val->name) {
/* Not a section. Don't free section as it is a shared pointer. */
XFREE(val->name, NULL, DYNAMIC_TYPE_OPENSSL);
- if (val->value)
- XFREE(val->value, NULL, DYNAMIC_TYPE_OPENSSL);
+ XFREE(val->value, NULL, DYNAMIC_TYPE_OPENSSL);
}
else {
/* Section so val->value is a stack */
- if (val->section)
- XFREE(val->section, NULL, DYNAMIC_TYPE_OPENSSL);
+ XFREE(val->section, NULL, DYNAMIC_TYPE_OPENSSL);
/* Only free the stack structures. The contained conf values
* will be freed in wolfSSL_NCONF_free */
- sk = (WOLF_STACK_OF(WOLFSSL_CONF_VALUE)*)val->value;
- while (sk) {
- WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *tmp = sk->next;
- XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
- sk = tmp;
- }
+ wolfSSL_sk_free((WOLF_STACK_OF(WOLFSSL_CONF_VALUE)*)val->value);
}
XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL);
}
@@ -1026,19 +1021,9 @@ WOLFSSL_STACK *wolfSSL_sk_CONF_VALUE_new(
*/
void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk)
{
- WOLFSSL_STACK* tmp;
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_free");
- if (sk == NULL)
- return;
-
- /* parse through stack freeing each node */
- while (sk) {
- tmp = sk->next;
- wolfSSL_X509V3_conf_free(sk->data.conf);
- XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
- sk = tmp;
- }
+ wolfSSL_sk_pop_free(sk, NULL);
}
int wolfSSL_sk_CONF_VALUE_num(const WOLFSSL_STACK *sk)
@@ -1545,7 +1530,7 @@ static const conf_cmd_tbl* wolfssl_conf_find_cmd(WOLFSSL_CONF_CTX* cctx,
*/
int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value)
{
- int ret = WOLFSSL_FAILURE;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
const conf_cmd_tbl* confcmd = NULL;
WOLFSSL_ENTER("wolfSSL_CONF_cmd");
@@ -1588,7 +1573,7 @@ int wolfSSL_CONF_cmd_value_type(WOLFSSL_CONF_CTX *cctx, const char *cmd)
confcmd = wolfssl_conf_find_cmd(cctx, cmd);
if (confcmd == NULL)
- return SSL_CONF_TYPE_UNKNOWN;
+ return WOLFSSL_CONF_TYPE_UNKNOWN;
return (int)confcmd->data_type;
}
@@ -1599,4 +1584,33 @@ int wolfSSL_CONF_cmd_value_type(WOLFSSL_CONF_CTX *cctx, const char *cmd)
* END OF CONF API
******************************************************************************/
+#if defined(OPENSSL_EXTRA)
+WOLFSSL_INIT_SETTINGS* wolfSSL_OPENSSL_INIT_new(void)
+{
+ WOLFSSL_INIT_SETTINGS* init = (WOLFSSL_INIT_SETTINGS*)XMALLOC(
+ sizeof(WOLFSSL_INIT_SETTINGS), NULL, DYNAMIC_TYPE_OPENSSL);
+
+ return init;
+}
+
+void wolfSSL_OPENSSL_INIT_free(WOLFSSL_INIT_SETTINGS* init)
+{
+ XFREE(init, NULL, DYNAMIC_TYPE_OPENSSL);
+}
+
+#ifndef NO_WOLFSSL_STUB
+int wolfSSL_OPENSSL_INIT_set_config_appname(WOLFSSL_INIT_SETTINGS* init,
+ char* appname)
+{
+ (void)init;
+ (void)appname;
+ WOLFSSL_STUB("OPENSSL_INIT_set_config_appname");
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
+#endif /* OPENSSL_EXTRA */
+
+
+
#endif /* WOLFSSL_CONF_INCLUDED */
diff --git a/src/src/crl.c b/src/src/crl.c
index 3e61ec9..9056bd1 100644
--- a/src/src/crl.c
+++ b/src/src/crl.c
@@ -1,12 +1,12 @@
/* crl.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+#include
/*
CRL Options:
@@ -32,19 +33,15 @@ CRL Options:
* Return any errors encountered during loading CRL
* from a directory.
*/
-#ifdef HAVE_CONFIG_H
- #include
-#endif
-
-#include
#ifndef WOLFCRYPT_ONLY
#ifdef HAVE_CRL
#include
#include
+#include
-#ifndef WOLFSSL_LINUXKM
+#ifndef NO_STRING_H
#include
#endif
@@ -87,6 +84,13 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
WOLFSSL_MSG("Init Mutex failed");
return BAD_MUTEX_E;
}
+#ifdef OPENSSL_ALL
+ {
+ int ret;
+ wolfSSL_RefInit(&crl->ref, &ret);
+ (void)ret;
+ }
+#endif
return 0;
}
@@ -110,18 +114,18 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
#if defined(OPENSSL_EXTRA)
crle->lastDateAsn1.length = MAX_DATE_SIZE;
XMEMCPY (crle->lastDateAsn1.data, crle->lastDate,
- crle->lastDateAsn1.length);
+ (size_t)crle->lastDateAsn1.length);
crle->lastDateAsn1.type = crle->lastDateFormat;
crle->nextDateAsn1.length = MAX_DATE_SIZE;
XMEMCPY (crle->nextDateAsn1.data, crle->nextDate,
- crle->nextDateAsn1.length);
+ (size_t)crle->nextDateAsn1.length);
crle->nextDateAsn1.type = crle->nextDateFormat;
crle->issuer = NULL;
wolfSSL_d2i_X509_NAME(&crle->issuer, (unsigned char**)&dcrl->issuer,
dcrl->issuerSz);
if (crle->issuer == NULL) {
- return WOLFSSL_FAILURE;
+ return WOLFSSL_FATAL_ERROR;
}
#endif
#ifdef CRL_STATIC_REVOKED_LIST
@@ -132,7 +136,10 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
#endif
dcrl->certs = NULL;
crle->totalCerts = dcrl->totalCerts;
- crle->crlNumber = dcrl->crlNumber;
+ crle->crlNumberSet = dcrl->crlNumberSet;
+ if (crle->crlNumberSet) {
+ XMEMCPY(crle->crlNumber, dcrl->crlNumber, CRL_MAX_NUM_SZ);
+ }
crle->verified = verified;
if (!verified) {
crle->tbsSz = dcrl->sigIndex - dcrl->certBegin;
@@ -141,13 +148,13 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap,
DYNAMIC_TYPE_CRL_ENTRY);
if (crle->toBeSigned == NULL)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
crle->signature = (byte*)XMALLOC(crle->signatureSz, heap,
DYNAMIC_TYPE_CRL_ENTRY);
if (crle->signature == NULL) {
XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY);
crle->toBeSigned = NULL;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#ifdef WC_RSA_PSS
@@ -160,7 +167,7 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
crle->toBeSigned = NULL;
XFREE(crle->signature, heap, DYNAMIC_TYPE_CRL_ENTRY);
crle->signature = NULL;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
XMEMCPY(crle->sigParams, buff + dcrl->sigParamsIndex,
crle->sigParamsSz);
@@ -203,29 +210,29 @@ static CRL_Entry* CRL_Entry_new(void* heap)
/* Free all CRL Entry resources */
static void CRL_Entry_free(CRL_Entry* crle, void* heap)
{
-#ifdef CRL_STATIC_REVOKED_LIST
- if (crle != NULL) {
- XMEMSET(crle->certs, 0, CRL_MAX_REVOKED_CERTS*sizeof(RevokedCert));
+ WOLFSSL_ENTER("CRL_Entry_free");
+ if (crle == NULL) {
+ WOLFSSL_MSG("CRL Entry is null");
+ return;
}
+#ifdef CRL_STATIC_REVOKED_LIST
+ XMEMSET(crle->certs, 0, CRL_MAX_REVOKED_CERTS*sizeof(RevokedCert));
#else
- RevokedCert* tmp = crle->certs;
- RevokedCert* next;
+ {
+ RevokedCert* tmp;
+ RevokedCert* next;
- WOLFSSL_ENTER("FreeCRL_Entry");
+ for (tmp = crle->certs; tmp != NULL; tmp = next) {
+ next = tmp->next;
+ XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED);
+ }
- while (tmp) {
- next = tmp->next;
- XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED);
- tmp = next;
}
#endif
- if (crle->signature != NULL)
- XFREE(crle->signature, heap, DYNAMIC_TYPE_CRL_ENTRY);
- if (crle->toBeSigned != NULL)
- XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY);
+ XFREE(crle->signature, heap, DYNAMIC_TYPE_CRL_ENTRY);
+ XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY);
#ifdef WC_RSA_PSS
- if (crle->sigParams != NULL)
- XFREE(crle->sigParams, heap, DYNAMIC_TYPE_CRL_ENTRY);
+ XFREE(crle->sigParams, heap, DYNAMIC_TYPE_CRL_ENTRY);
#endif
#if defined(OPENSSL_EXTRA)
if (crle->issuer != NULL) {
@@ -244,11 +251,25 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
{
CRL_Entry* tmp;
+ WOLFSSL_ENTER("FreeCRL");
+
if (crl == NULL)
return;
+#ifdef OPENSSL_ALL
+ {
+ int ret;
+ int doFree = 0;
+ wolfSSL_RefDec(&crl->ref, &doFree, &ret);
+ if (ret != 0)
+ WOLFSSL_MSG("Couldn't lock x509 mutex");
+ if (!doFree)
+ return;
+ wolfSSL_RefFree(&crl->ref);
+ }
+#endif
+
tmp = crl->crlList;
- WOLFSSL_ENTER("FreeCRL");
#ifdef HAVE_CRL_MONITOR
if (crl->monitors[0].path)
XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
@@ -314,18 +335,17 @@ static int FindRevokedSerial(RevokedCert* rc, byte* serial, int serialSz,
#else
(void)totalCerts;
/* search in the linked list*/
-
while (rc) {
if (serialHash == NULL) {
if (rc->serialSz == serialSz &&
- XMEMCMP(rc->serialNumber, serial, rc->serialSz) == 0) {
+ XMEMCMP(rc->serialNumber, serial, (size_t)rc->serialSz) == 0) {
WOLFSSL_MSG("Cert revoked");
ret = CRL_CERT_REVOKED;
break;
}
}
else {
- ret = CalcHashId(rc->serialNumber, rc->serialSz, hash);
+ ret = CalcHashId(rc->serialNumber, (word32)rc->serialSz, hash);
if (ret != 0)
break;
if (XMEMCMP(hash, serialHash, SIGNER_DIGEST_SIZE) == 0) {
@@ -362,7 +382,7 @@ static int VerifyCRLE(const WOLFSSL_CRL* crl, CRL_Entry* crle)
ret = VerifyCRL_Signature(&sigCtx, crle->toBeSigned, crle->tbsSz,
crle->signature, crle->signatureSz, crle->signatureOID,
#ifdef WC_RSA_PSS
- crle->sigParams, crle->sigParamsSz,
+ crle->sigParams, (int)crle->sigParamsSz,
#else
NULL, 0,
#endif
@@ -392,6 +412,8 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial,
for (crle = crl->crlList; crle != NULL; crle = crle->next) {
if (XMEMCMP(crle->issuerHash, issuerHash, CRL_DIGEST_SIZE) == 0) {
+ int nextDateValid = 1;
+
WOLFSSL_MSG("Found CRL Entry on list");
if (crle->verified == 0) {
@@ -424,19 +446,22 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial,
#endif
{
#if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK)
- if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, AFTER)) {
+ if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, ASN_AFTER)) {
WOLFSSL_MSG("CRL next date is no longer valid");
- ret = ASN_AFTER_DATE_E;
+ nextDateValid = 0;
}
#endif
}
- if (ret == 0) {
+ if (nextDateValid) {
foundEntry = 1;
ret = FindRevokedSerial(crle->certs, serial, serialSz,
serialHash, crle->totalCerts);
if (ret != 0)
break;
}
+ else if (foundEntry == 0) {
+ ret = CRL_CERT_DATE_ERR;
+ }
}
}
@@ -476,8 +501,9 @@ int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial,
if (foundEntry == 0) {
/* perform embedded lookup */
if (crl->crlIOCb) {
- ret = crl->crlIOCb(crl, (const char*)extCrlInfo, extCrlInfoSz);
- if (ret == WOLFSSL_CBIO_ERR_WANT_READ) {
+ int cbRet = crl->crlIOCb(crl, (const char*)extCrlInfo,
+ extCrlInfoSz);
+ if (cbRet == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ)) {
ret = OCSP_WANT_READ;
}
else if (ret >= 0) {
@@ -498,11 +524,11 @@ int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial,
/* Loading .rN form CRL file if find at the folder, */
/* and try again checking Cert in the CRL list. */
/* When not set the folder or not use hash_dir, do nothing. */
- if ((foundEntry == 0) && (ret != OCSP_WANT_READ)) {
- if (crl->cm->x509_store_p != NULL) {
- ret = LoadCertByIssuer(crl->cm->x509_store_p,
+ if ((foundEntry == 0) && (ret != WC_NO_ERR_TRACE(OCSP_WANT_READ))) {
+ if (crl->cm != NULL && crl->cm->x509_store_p != NULL) {
+ int loadRet = LoadCertByIssuer(crl->cm->x509_store_p,
(WOLFSSL_X509_NAME*)issuerName, X509_LU_CRL);
- if (ret == WOLFSSL_SUCCESS) {
+ if (loadRet == WOLFSSL_SUCCESS) {
/* try again */
ret = CheckCertCRLList(crl, issuerHash, serial, serialSz,
serialHash, &foundEntry);
@@ -512,18 +538,18 @@ int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial,
#endif
if (foundEntry == 0) {
WOLFSSL_MSG("Couldn't find CRL for status check");
- if (ret != CRL_CERT_DATE_ERR) {
+ if (ret != WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR)) {
ret = CRL_MISSING;
}
- if (crl->cm->cbMissingCRL) {
+ if (crl->cm != NULL && crl->cm->cbMissingCRL) {
char url[256];
WOLFSSL_MSG("Issuing missing CRL callback");
url[0] = '\0';
if (extCrlInfo) {
if (extCrlInfoSz < (int)sizeof(url) -1 ) {
- XMEMCPY(url, extCrlInfo, extCrlInfoSz);
+ XMEMCPY(url, extCrlInfo, (size_t)extCrlInfoSz);
url[extCrlInfoSz] = '\0';
}
else {
@@ -533,6 +559,13 @@ int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial,
crl->cm->cbMissingCRL(url);
}
+
+ if (crl->cm != NULL && crl->cm->crlCb &&
+ crl->cm->crlCb(ret, crl, crl->cm, crl->cm->crlCbCtx)) {
+ if (ret != 0)
+ WOLFSSL_MSG("Overriding CRL error");
+ ret = 0;
+ }
}
return ret;
@@ -550,17 +583,98 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
NULL, cert->extCrlInfo, cert->extCrlInfoSz, issuerName);
}
+#ifdef HAVE_CRL_UPDATE_CB
+static void SetCrlInfo(CRL_Entry* entry, CrlInfo *info)
+{
+ info->issuerHash = (byte *)entry->issuerHash;
+ info->issuerHashLen = CRL_DIGEST_SIZE;
+ info->lastDate = (byte *)entry->lastDate;
+ info->lastDateMaxLen = MAX_DATE_SIZE;
+ info->lastDateFormat = entry->lastDateFormat;
+ info->nextDate = (byte *)entry->nextDate;
+ info->nextDateMaxLen = MAX_DATE_SIZE;
+ info->nextDateFormat = entry->nextDateFormat;
+ info->crlNumberSet = entry->crlNumberSet;
+ if (info->crlNumberSet)
+ XMEMCPY(info->crlNumber, entry->crlNumber, CRL_MAX_NUM_SZ);
+}
+
+static void SetCrlInfoFromDecoded(DecodedCRL* entry, CrlInfo *info)
+{
+ info->issuerHash = (byte *)entry->issuerHash;
+ info->issuerHashLen = SIGNER_DIGEST_SIZE;
+ info->lastDate = (byte *)entry->lastDate;
+ info->lastDateMaxLen = MAX_DATE_SIZE;
+ info->lastDateFormat = entry->lastDateFormat;
+ info->nextDate = (byte *)entry->nextDate;
+ info->nextDateMaxLen = MAX_DATE_SIZE;
+ info->nextDateFormat = entry->nextDateFormat;
+ info->crlNumberSet = entry->crlNumberSet;
+ if (info->crlNumberSet)
+ XMEMCPY(info->crlNumber, entry->crlNumber, CRL_MAX_NUM_SZ);
+}
+#endif
+
+/* Returns MP_GT if prev crlNumber is smaller
+ * MP_EQ if equal
+ * MP_LT if prev crlNumber is larger */
+static int CompareCRLnumber(CRL_Entry* prev, CRL_Entry* curr)
+{
+ int ret = 0;
+ DECL_MP_INT_SIZE_DYN(prev_num, CRL_MAX_NUM_SZ * CHAR_BIT,
+ CRL_MAX_NUM_SZ * CHAR_BIT);
+ DECL_MP_INT_SIZE_DYN(curr_num, CRL_MAX_NUM_SZ * CHAR_BIT,
+ CRL_MAX_NUM_SZ * CHAR_BIT);
+
+ NEW_MP_INT_SIZE(prev_num, CRL_MAX_NUM_SZ * CHAR_BIT, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ NEW_MP_INT_SIZE(curr_num, CRL_MAX_NUM_SZ * CHAR_BIT, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+#ifdef MP_INT_SIZE_CHECK_NULL
+ if ((prev_num == NULL) || (curr_num == NULL)) {
+ ret = MEMORY_E;
+ }
+#endif
+
+ if (ret == 0 && ((INIT_MP_INT_SIZE(prev_num, CRL_MAX_NUM_SZ * CHAR_BIT)
+ != MP_OKAY) || (INIT_MP_INT_SIZE(curr_num,
+ CRL_MAX_NUM_SZ * CHAR_BIT)) != MP_OKAY)) {
+ ret = MP_INIT_E;
+ }
+
+ if (ret == 0 && (mp_read_radix(prev_num, (char*)prev->crlNumber,
+ MP_RADIX_HEX) != MP_OKAY ||
+ mp_read_radix(curr_num, (char*)curr->crlNumber,
+ MP_RADIX_HEX) != MP_OKAY)) {
+ ret = BAD_FUNC_ARG;
+ }
+
+ if (ret == 0)
+ ret = mp_cmp(prev_num, curr_num);
+
+ FREE_MP_INT_SIZE(prev_num, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ FREE_MP_INT_SIZE(curr_num, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
/* Add Decoded CRL, 0 on success */
static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
int verified)
{
CRL_Entry* crle = NULL;
+ CRL_Entry* curr = NULL;
+ CRL_Entry* prev = NULL;
+#ifdef HAVE_CRL_UPDATE_CB
+ CrlInfo old;
+ CrlInfo cnew;
+#endif
+ int ret = 0;
WOLFSSL_ENTER("AddCRL");
if (crl == NULL)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
crle = crl->currentEntry;
@@ -575,7 +689,7 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) {
WOLFSSL_MSG("Init CRL Entry failed");
CRL_Entry_free(crle, crl->heap);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (wc_LockRwLock_Wr(&crl->crlLock) != 0) {
@@ -584,8 +698,50 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
return BAD_MUTEX_E;
}
- crle->next = crl->crlList;
- crl->crlList = crle;
+ for (curr = crl->crlList; curr != NULL; curr = curr->next) {
+ if (XMEMCMP(curr->issuerHash, crle->issuerHash, CRL_DIGEST_SIZE) == 0) {
+ ret = CompareCRLnumber(crle, curr);
+ /* Error out if the CRL we're attempting to add isn't more
+ * authoritative than the existing entry */
+ if (ret == MP_LT || ret == MP_EQ) {
+ WOLFSSL_MSG("Same or newer CRL entry already exists");
+ CRL_Entry_free(crle, crl->heap);
+ wc_UnLockRwLock(&crl->crlLock);
+ return BAD_FUNC_ARG;
+ }
+ else if (ret < 0) {
+ WOLFSSL_MSG("Error comparing CRL Numbers");
+ return ret;
+ }
+
+ crle->next = curr->next;
+ if (prev != NULL) {
+ prev->next = crle;
+ }
+ else {
+ crl->crlList = crle;
+ }
+
+#ifdef HAVE_CRL_UPDATE_CB
+ if (crl->cm && crl->cm->cbUpdateCRL != NULL) {
+ SetCrlInfo(curr, &old);
+ SetCrlInfo(crle, &cnew);
+ crl->cm->cbUpdateCRL(&old, &cnew);
+ }
+#endif
+
+ break;
+ }
+ prev = curr;
+ }
+
+ if (curr != NULL) {
+ CRL_Entry_free(curr, crl->heap);
+ }
+ else {
+ crle->next = crl->crlList;
+ crl->crlList = crle;
+ }
wc_UnLockRwLock(&crl->crlLock);
/* Avoid heap-use-after-free after crl->crlList is released */
crl->currentEntry = NULL;
@@ -601,11 +757,7 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
int ret = WOLFSSL_SUCCESS;
const byte* myBuffer = buff; /* if DER ok, otherwise switch */
DerBuffer* der = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- DecodedCRL* dcrl;
-#else
- DecodedCRL dcrl[1];
-#endif
+ WC_DECLARE_VAR(dcrl, DecodedCRL, 1, 0);
WOLFSSL_ENTER("BufferLoadCRL");
@@ -622,7 +774,7 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
else {
WOLFSSL_MSG("Pem to Der failed");
FreeDer(&der);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#else
ret = NOT_COMPILED_IN;
@@ -639,10 +791,8 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
crl->currentEntry = CRL_Entry_new(crl->heap);
if (crl->currentEntry == NULL) {
- WOLFSSL_MSG("alloc CRL Entry failed");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+ WOLFSSL_MSG_CERT_LOG("alloc CRL Entry failed");
+ WC_FREE_VAR_EX(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
FreeDer(&der);
return MEMORY_E;
}
@@ -650,42 +800,122 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
InitDecodedCRL(dcrl, crl->heap);
ret = ParseCRL(crl->currentEntry->certs, dcrl, myBuffer, (word32)sz,
verify, crl->cm);
- if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) {
- WOLFSSL_MSG("ParseCRL error");
+
+ if (ret != 0 && !(ret == WC_NO_ERR_TRACE(ASN_CRL_NO_SIGNER_E)
+ && verify == NO_VERIFY)) {
+ WOLFSSL_MSG_CERT_LOG("ParseCRL error");
+ WOLFSSL_MSG_CERT_EX("ParseCRL verify = %d, ret = %d", verify, ret);
CRL_Entry_free(crl->currentEntry, crl->heap);
crl->currentEntry = NULL;
}
else {
- ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E);
+ ret = AddCRL(crl, dcrl, myBuffer,
+ ret != WC_NO_ERR_TRACE(ASN_CRL_NO_SIGNER_E));
if (ret != 0) {
- WOLFSSL_MSG("AddCRL error");
+ WOLFSSL_MSG_CERT_LOG("AddCRL error");
crl->currentEntry = NULL;
}
}
FreeDecodedCRL(dcrl);
+ WC_FREE_VAR_EX(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ FreeDer(&der);
+
+ return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
+}
+
+#ifdef HAVE_CRL_UPDATE_CB
+/* Fill out CRL info structure, WOLFSSL_SUCCESS on ok */
+int GetCRLInfo(WOLFSSL_CRL* crl, CrlInfo* info, const byte* buff,
+ long sz, int type)
+{
+ int ret = WOLFSSL_SUCCESS;
+ const byte* myBuffer = buff; /* if DER ok, otherwise switch */
+ DerBuffer* der = NULL;
+ CRL_Entry* crle = NULL;
+ WC_DECLARE_VAR(dcrl, DecodedCRL, 1, 0);
+
+ WOLFSSL_ENTER("GetCRLInfo");
+
+ if (crl == NULL || info == NULL || buff == NULL || sz == 0)
+ return BAD_FUNC_ARG;
+
+ if (type == WOLFSSL_FILETYPE_PEM) {
+ #ifdef WOLFSSL_PEM_TO_DER
+ ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL);
+ if (ret == 0) {
+ myBuffer = der->buffer;
+ sz = der->length;
+ }
+ else {
+ WOLFSSL_MSG("Pem to Der failed");
+ FreeDer(&der);
+ return -1;
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+
#ifdef WOLFSSL_SMALL_STACK
- XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (dcrl == NULL) {
+ FreeDer(&der);
+ return MEMORY_E;
+ }
#endif
+ crle = CRL_Entry_new(crl->heap);
+ if (crle == NULL) {
+ WOLFSSL_MSG("alloc CRL Entry failed");
+ WC_FREE_VAR_EX(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ FreeDer(&der);
+ return MEMORY_E;
+ }
+
+ InitDecodedCRL(dcrl, crl->heap);
+ ret = ParseCRL(crle->certs, dcrl, myBuffer, (word32)sz,
+ 0, crl->cm);
+ if (ret != 0 && !(ret == WC_NO_ERR_TRACE(ASN_CRL_NO_SIGNER_E))) {
+ WOLFSSL_MSG("ParseCRL error");
+ CRL_Entry_free(crle, crl->heap);
+ crle = NULL;
+ }
+ else {
+ SetCrlInfoFromDecoded((DecodedCRL*)dcrl, info);
+ }
+
+ FreeDecodedCRL(dcrl);
+
+ WC_FREE_VAR_EX(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
FreeDer(&der);
+ CRL_Entry_free(crle, crl->heap);
return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
}
+#endif
#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
/* helper function to create a new dynamic WOLFSSL_X509_CRL structure */
static WOLFSSL_X509_CRL* wolfSSL_X509_crl_new(WOLFSSL_CERT_MANAGER* cm)
{
WOLFSSL_X509_CRL* ret;
+ void* heap = NULL;
- ret = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), cm->heap,
- DYNAMIC_TYPE_CRL);
+ if (cm != NULL) {
+ heap = cm->heap;
+ }
+
+ ret = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), heap,
+ DYNAMIC_TYPE_CRL);
if (ret != NULL) {
if (InitCRL(ret, cm) < 0) {
WOLFSSL_MSG("Unable to initialize new CRL structure");
- XFREE(ret, cm->heap, DYNAMIC_TYPE_CRL);
+ XFREE(ret, heap, DYNAMIC_TYPE_CRL);
ret = NULL;
}
}
@@ -738,7 +968,7 @@ static RevokedCert *DupRevokedCertList(RevokedCert* in, void* heap)
static CRL_Entry* DupCRL_Entry(const CRL_Entry* ent, void* heap)
{
CRL_Entry *dupl;
- const size_t copyOffset = OFFSETOF(CRL_Entry, verifyMutex) +
+ const size_t copyOffset = WC_OFFSETOF(CRL_Entry, verifyMutex) +
sizeof(ent->verifyMutex);
#ifdef CRL_STATIC_REVOKED_LIST
if (ent->totalCerts > CRL_MAX_REVOKED_CERTS) {
@@ -756,9 +986,17 @@ static CRL_Entry* DupCRL_Entry(const CRL_Entry* ent, void* heap)
#ifndef CRL_STATIC_REVOKED_LIST
dupl->certs = DupRevokedCertList(ent->certs, heap);
+ if (ent->certs != NULL && dupl->certs == NULL) {
+ CRL_Entry_free(dupl, heap);
+ return NULL;
+ }
#endif
#ifdef OPENSSL_EXTRA
dupl->issuer = wolfSSL_X509_NAME_dup(ent->issuer);
+ if (ent->issuer != NULL && dupl->issuer == NULL) {
+ CRL_Entry_free(dupl, heap);
+ return NULL;
+ }
#endif
if (!ent->verified) {
@@ -772,7 +1010,8 @@ static CRL_Entry* DupCRL_Entry(const CRL_Entry* ent, void* heap)
#endif
if (dupl->toBeSigned == NULL || dupl->signature == NULL
#ifdef WC_RSA_PSS
- || dupl->sigParams == NULL
+ /* allow sigParamsSz is zero and XMALLOC(0) to return NULL */
+ || (dupl->sigParams == NULL && dupl->sigParamsSz != 0)
#endif
) {
CRL_Entry_free(dupl, heap);
@@ -844,7 +1083,7 @@ static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl)
#ifdef HAVE_CRL_MONITOR
if (crl->monitors[0].path) {
- int pathSz = (int)XSTRLEN(crl->monitors[0].path) + 1;
+ size_t pathSz = XSTRLEN(crl->monitors[0].path) + 1;
dupl->monitors[0].path = (char*)XMALLOC(pathSz, dupl->heap,
DYNAMIC_TYPE_CRL_MONITOR);
if (dupl->monitors[0].path != NULL) {
@@ -856,7 +1095,7 @@ static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl)
}
if (crl->monitors[1].path) {
- int pathSz = (int)XSTRLEN(crl->monitors[1].path) + 1;
+ size_t pathSz = XSTRLEN(crl->monitors[1].path) + 1;
dupl->monitors[1].path = (char*)XMALLOC(pathSz, dupl->heap,
DYNAMIC_TYPE_CRL_MONITOR);
if (dupl->monitors[1].path != NULL) {
@@ -866,6 +1105,7 @@ static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl)
if (dupl->monitors[0].path != NULL) {
XFREE(dupl->monitors[0].path, dupl->heap,
DYNAMIC_TYPE_CRL_MONITOR);
+ dupl->monitors[0].path = NULL;
}
return MEMORY_E;
}
@@ -873,6 +1113,8 @@ static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl)
#endif
dupl->crlList = DupCRL_list(crl->crlList, dupl->heap);
+ if (dupl->crlList == NULL)
+ return MEMORY_E;
#ifdef HAVE_CRL_IO
dupl->crlIOCb = crl->crlIOCb;
#endif
@@ -880,6 +1122,20 @@ static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl)
return 0;
}
+WOLFSSL_X509_CRL* wolfSSL_X509_CRL_dup(const WOLFSSL_X509_CRL* crl)
+{
+ WOLFSSL_X509_CRL* ret;
+
+ WOLFSSL_ENTER("wolfSSL_X509_CRL_dup");
+
+ ret = wolfSSL_X509_crl_new(crl->cm);
+ if (ret != NULL && DupX509_CRL(ret, crl) != 0) {
+ FreeCRL(ret, 1);
+ ret = NULL;
+ }
+ return ret;
+}
+
/* returns WOLFSSL_SUCCESS on success. Does not take ownership of newcrl */
int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl)
{
@@ -927,7 +1183,7 @@ int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newc
}
if (crl != newcrl && wc_LockRwLock_Rd(&newcrl->crlLock) != 0) {
- WOLFSSL_MSG("wc_LockRwLock_Wr failed");
+ WOLFSSL_MSG("wc_LockRwLock_Rd failed");
wc_UnLockRwLock(&crl->crlLock);
return BAD_MUTEX_E;
}
@@ -982,24 +1238,15 @@ static int SwapLists(WOLFSSL_CRL* crl)
{
int ret;
CRL_Entry* newList;
-#ifdef WOLFSSL_SMALL_STACK
- WOLFSSL_CRL* tmp;
-#else
- WOLFSSL_CRL tmp[1];
-#endif
+ WC_DECLARE_VAR(tmp, WOLFSSL_CRL, 1, 0);
-#ifdef WOLFSSL_SMALL_STACK
- tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (tmp == NULL)
- return MEMORY_E;
-#endif
+ WC_ALLOC_VAR_EX(tmp, WOLFSSL_CRL, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER,
+ return MEMORY_E);
if (InitCRL(tmp, crl->cm) < 0) {
WOLFSSL_MSG("Init tmp CRL failed");
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return -1;
+ WC_FREE_VAR_EX(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FATAL_ERROR;
}
if (crl->monitors[0].path) {
@@ -1007,10 +1254,8 @@ static int SwapLists(WOLFSSL_CRL* crl)
if (ret != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("PEM LoadCRL on dir change failed");
FreeCRL(tmp, 0);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return -1;
+ WC_FREE_VAR_EX(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FATAL_ERROR;
}
}
@@ -1019,20 +1264,16 @@ static int SwapLists(WOLFSSL_CRL* crl)
if (ret != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("DER LoadCRL on dir change failed");
FreeCRL(tmp, 0);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return -1;
+ WC_FREE_VAR_EX(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FATAL_ERROR;
}
}
if (wc_LockRwLock_Wr(&crl->crlLock) != 0) {
WOLFSSL_MSG("wc_LockRwLock_Wr failed");
FreeCRL(tmp, 0);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return -1;
+ WC_FREE_VAR_EX(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FATAL_ERROR;
}
newList = tmp->crlList;
@@ -1045,9 +1286,7 @@ static int SwapLists(WOLFSSL_CRL* crl)
FreeCRL(tmp, 0);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return 0;
}
@@ -1081,10 +1320,14 @@ static int StopMonitor(wolfSSL_CRL_mfd_t mfd)
struct kevent change;
/* trigger custom shutdown */
+#if defined(NOTE_TRIGGER)
EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
+#elif defined(EV_TRIGGER)
+ EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_TRIGGER, 0, 0, NULL);
+#endif
if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
WOLFSSL_MSG("kevent trigger customer event failed");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
return 0;
@@ -1216,7 +1459,7 @@ static int StopMonitor(wolfSSL_CRL_mfd_t mfd)
/* write to our custom event */
if (write(mfd, &w64, sizeof(w64)) < 0) {
WOLFSSL_MSG("StopMonitor write failed");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
return 0;
@@ -1229,11 +1472,7 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
int notifyFd;
int wd = -1;
WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
-#ifdef WOLFSSL_SMALL_STACK
- char* buff;
-#else
- char buff[8192];
-#endif
+ WC_DECLARE_VAR(buff, char, 8192, 0);
WOLFSSL_ENTER("DoMonitor");
@@ -1338,9 +1577,7 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
}
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (wd > 0) {
if (inotify_rm_watch(notifyFd, wd) < 0)
@@ -1359,14 +1596,14 @@ static int StopMonitor(wolfSSL_CRL_mfd_t mfd)
{
if (SetEvent(mfd) == 0) {
WOLFSSL_MSG("SetEvent custom event trigger failed");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
return 0;
}
#ifdef DEBUG_WOLFSSL
#define SHOW_WINDOWS_ERROR() do { \
- LPVOID lpMsgBuf; \
+ LPVOID lpMsgBuf = NULL; \
DWORD dw = GetLastError(); \
FormatMessageA( \
FORMAT_MESSAGE_ALLOCATE_BUFFER | \
@@ -1550,22 +1787,14 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
{
int ret = WOLFSSL_SUCCESS;
char* name = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- ReadDirCtx* readCtx = NULL;
-#else
- ReadDirCtx readCtx[1];
-#endif
+ WC_DECLARE_VAR(readCtx, ReadDirCtx, 1, 0);
WOLFSSL_ENTER("LoadCRL");
if (crl == NULL)
return BAD_FUNC_ARG;
-#ifdef WOLFSSL_SMALL_STACK
- readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (readCtx == NULL)
- return MEMORY_E;
-#endif
+ WC_ALLOC_VAR_EX(readCtx, ReadDirCtx, 1, crl->heap,
+ DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
/* try to load each regular file in path */
ret = wc_ReadDirFirst(readCtx, path, &name);
@@ -1596,6 +1825,8 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
ret = ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl, VERIFY);
if (ret != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("CRL file load failed");
+ wc_ReadDirClose(readCtx);
+ WC_FREE_VAR_EX(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
}
@@ -1608,9 +1839,7 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
/* load failures not reported, for backwards compat */
ret = WOLFSSL_SUCCESS;
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (monitor & WOLFSSL_CRL_MONITOR) {
#ifdef HAVE_CRL_MONITOR
diff --git a/src/src/dtls.c b/src/src/dtls.c
index aecd260..dff1ffa 100644
--- a/src/src/dtls.c
+++ b/src/src/dtls.c
@@ -1,12 +1,12 @@
/* dtls.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+#include
+
/*
* WOLFSSL_DTLS_NO_HVR_ON_RESUME
* WOLFSSL_DTLS13_NO_HRR_ON_RESUME
@@ -46,12 +48,6 @@
* to explicitly enable this during runtime.
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-
#ifndef WOLFCRYPT_ONLY
#include
@@ -101,20 +97,29 @@ void DtlsResetState(WOLFSSL* ssl)
ssl->options.tls = 0;
ssl->options.tls1_1 = 0;
ssl->options.tls1_3 = 0;
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ ssl->buffers.dtlsCtx.processingPendingRecord = 0;
+ /* Clear the pending peer in case user set */
+ XFREE(ssl->buffers.dtlsCtx.pendingPeer.sa, ssl->heap,
+ DYNAMIC_TYPE_SOCKADDR);
+ ssl->buffers.dtlsCtx.pendingPeer.sa = NULL;
+ ssl->buffers.dtlsCtx.pendingPeer.sz = 0;
+ ssl->buffers.dtlsCtx.pendingPeer.bufSz = 0;
+#endif
}
int DtlsIgnoreError(int err)
{
/* Whitelist of errors not to ignore */
switch (err) {
- case MEMORY_E:
- case MEMORY_ERROR:
- case ASYNC_INIT_E:
- case ASYNC_OP_E:
- case SOCKET_ERROR_E:
- case WANT_READ:
- case WANT_WRITE:
- case COOKIE_ERROR:
+ case WC_NO_ERR_TRACE(MEMORY_E):
+ case WC_NO_ERR_TRACE(MEMORY_ERROR):
+ case WC_NO_ERR_TRACE(ASYNC_INIT_E):
+ case WC_NO_ERR_TRACE(ASYNC_OP_E):
+ case WC_NO_ERR_TRACE(SOCKET_ERROR_E):
+ case WC_NO_ERR_TRACE(WANT_READ):
+ case WC_NO_ERR_TRACE(WANT_WRITE):
+ case WC_NO_ERR_TRACE(COOKIE_ERROR):
return 0;
default:
return 1;
@@ -187,14 +192,14 @@ typedef struct WolfSSL_CH {
byte dtls12cookieSet:1;
} WolfSSL_CH;
-static int ReadVector8(const byte* input, WolfSSL_ConstVector* v)
+static word32 ReadVector8(const byte* input, WolfSSL_ConstVector* v)
{
v->size = *input;
v->elements = input + OPAQUE8_LEN;
return v->size + OPAQUE8_LEN;
}
-static int ReadVector16(const byte* input, WolfSSL_ConstVector* v)
+static word32 ReadVector16(const byte* input, WolfSSL_ConstVector* v)
{
word16 size16;
ato16(input, &size16);
@@ -221,6 +226,7 @@ static int CreateDtls12Cookie(const WOLFSSL* ssl, const WolfSSL_CH* ch,
ssl->buffers.dtlsCookieSecret.buffer,
ssl->buffers.dtlsCookieSecret.length);
if (ret == 0) {
+ /* peerLock not necessary. Still in handshake phase. */
ret = wc_HmacUpdate(&cookieHmac,
(const byte*)ssl->buffers.dtlsCtx.peer.sa,
ssl->buffers.dtlsCtx.peer.sz);
@@ -267,7 +273,7 @@ static int CheckDtlsCookie(const WOLFSSL* ssl, WolfSSL_CH* ch,
return BUFFER_E;
ret = TlsCheckCookie(ssl, ch->cookieExt.elements + OPAQUE16_LEN,
(word16)(ch->cookieExt.size - OPAQUE16_LEN));
- if (ret < 0 && ret != HRR_COOKIE_ERROR)
+ if (ret < 0 && ret != WC_NO_ERR_TRACE(HRR_COOKIE_ERROR))
return ret;
*cookieGood = ret > 0;
ret = 0;
@@ -355,7 +361,8 @@ static int FindExtByType(WolfSSL_ConstVector* ret, word16 extType,
ato16(exts.elements + idx, &type);
idx += OPAQUE16_LEN;
idx += ReadVector16(exts.elements + idx, &ext);
- if (idx > exts.size)
+ if (idx > exts.size ||
+ ext.elements + ext.size > exts.elements + exts.size)
return BUFFER_ERROR;
if (type == extType) {
XMEMCPY(ret, &ext, sizeof(ext));
@@ -488,7 +495,7 @@ static int TlsCheckSupportedVersion(const WOLFSSL* ssl,
ch->extension, &tlsxFound);
if (ret != 0)
return ret;
- if (!tlsxFound) {
+ if (!tlsxFound || tlsxSupportedVersions.elements == NULL) {
*isTls13 = 0;
return 0;
}
@@ -671,6 +678,8 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
ERROR_OUT(BUFFER_ERROR, dtls13_cleanup);
if ((sigAlgs.size % 2) != 0)
ERROR_OUT(BUFFER_ERROR, dtls13_cleanup);
+ if (sigAlgs.size > WOLFSSL_MAX_SIGALGO)
+ ERROR_OUT(BUFFER_ERROR, dtls13_cleanup);
suites.hashSigAlgoSz = (word16)sigAlgs.size;
XMEMCPY(suites.hashSigAlgo, sigAlgs.elements, sigAlgs.size);
haveSA = 1;
@@ -716,10 +725,20 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
* and if they don't match we will error out there anyway. */
byte modes;
+ /* TLSX_PreSharedKey_Parse_ClientHello uses word16 length */
+ if (tlsx.size > WOLFSSL_MAX_16BIT) {
+ ERROR_OUT(BUFFER_ERROR, dtls13_cleanup);
+ }
+
/* Ask the user for the ciphersuite matching this identity */
if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts,
- tlsx.elements, tlsx.size, ssl->heap) == 0)
+ tlsx.elements, (word16)tlsx.size, ssl->heap) == 0) {
+ /* suites only needs to be refined when searching for a PSK.
+ * MatchSuite_ex handles refining internally. */
+ refineSuites(WOLFSSL_SUITES(ssl), &suites, &suites,
+ ssl->options.useClientOrder);
FindPskSuiteFromExt(ssl, parsedExts, &pskInfo, &suites);
+ }
/* Revert to full handshake if PSK parsing failed */
if (pskInfo.isValid) {
@@ -729,8 +748,8 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
goto dtls13_cleanup;
if (!tlsxFound)
ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup);
- ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, tlsx.size,
- client_hello, &modes);
+ ret = TLSX_PskKeyModes_Parse_Modes(tlsx.elements, (word16)tlsx.size,
+ client_hello, &modes);
if (ret != 0)
goto dtls13_cleanup;
if ((modes & (1 << PSK_DHE_KE)) &&
@@ -739,8 +758,9 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup);
doKE = 1;
}
- else if ((modes & (1 << PSK_KE)) == 0) {
- ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup);
+ else if ((modes & (1 << PSK_KE)) == 0 ||
+ ssl->options.onlyPskDheKe) {
+ ERROR_OUT(PSK_KEY_ERROR, dtls13_cleanup);
}
usePSK = 1;
}
@@ -832,8 +852,6 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
WOLFSSL* nonConstSSL = (WOLFSSL*)ssl;
TLSX* sslExts = nonConstSSL->extensions;
- if (ret != 0)
- goto dtls13_cleanup;
nonConstSSL->options.tls = 1;
nonConstSSL->options.tls1_1 = 1;
nonConstSSL->options.tls1_3 = 1;
@@ -953,8 +971,13 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz,
int tlsxFound;
ret = FindExtByType(&ch.cookieExt, TLSX_COOKIE, ch.extension,
&tlsxFound);
- if (ret != 0)
+ if (ret != 0) {
+ if (isFirstCHFrag) {
+ WOLFSSL_MSG("\t\tCookie probably missing from first "
+ "fragment. Dropping.");
+ }
return ret;
+ }
}
}
#endif
@@ -1010,11 +1033,20 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz,
ssl->options.dtlsStateful = 1;
/* Update the window now that we enter the stateful parsing */
#ifdef WOLFSSL_DTLS13
- if (isTls13)
+ if (isTls13) {
+ /* Set record numbers before current record number as read */
+ Dtls13Epoch* e;
ret = Dtls13UpdateWindowRecordRecvd(ssl);
+ e = Dtls13GetEpoch(ssl, ssl->keys.curEpoch64);
+ if (e != NULL)
+ XMEMSET(e->window, 0xFF, sizeof(e->window));
+ }
else
#endif
DtlsUpdateWindow(ssl);
+ /* Set record numbers before current record number as read */
+ XMEMSET(ssl->keys.peerSeq->window, 0xFF,
+ sizeof(ssl->keys.peerSeq->window));
}
}
@@ -1024,22 +1056,6 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz,
#if defined(WOLFSSL_DTLS_CID)
-typedef struct ConnectionID {
- byte length;
-/* Ignore "nonstandard extension used : zero-sized array in struct/union"
- * MSVC warning */
-#ifdef _MSC_VER
-#pragma warning(disable: 4200)
-#endif
- byte id[];
-} ConnectionID;
-
-typedef struct CIDInfo {
- ConnectionID* tx;
- ConnectionID* rx;
- byte negotiated : 1;
-} CIDInfo;
-
static ConnectionID* DtlsCidNew(const byte* cid, byte size, void* heap)
{
ConnectionID* ret;
@@ -1105,6 +1121,26 @@ static int DtlsCidGet(WOLFSSL* ssl, unsigned char* buf, int bufferSz, int rx)
return WOLFSSL_SUCCESS;
}
+static int DtlsCidGet0(WOLFSSL* ssl, unsigned char** cid, int rx)
+{
+ ConnectionID* id;
+ CIDInfo* info;
+
+ if (ssl == NULL || cid == NULL)
+ return BAD_FUNC_ARG;
+
+ info = DtlsCidGetInfo(ssl);
+ if (info == NULL)
+ return WOLFSSL_FAILURE;
+
+ id = rx ? info->rx : info->tx;
+ if (id == NULL || id->length == 0)
+ return WOLFSSL_SUCCESS;
+
+ *cid = id->id;
+ return WOLFSSL_SUCCESS;
+}
+
static CIDInfo* DtlsCidGetInfoFromExt(byte* ext)
{
WOLFSSL** sslPtr;
@@ -1141,10 +1177,8 @@ void TLSX_ConnectionID_Free(byte* ext, void* heap)
info = DtlsCidGetInfoFromExt(ext);
if (info == NULL)
return;
- if (info->rx != NULL)
- XFREE(info->rx, heap, DYNAMIC_TYPE_TLSX);
- if (info->tx != NULL)
- XFREE(info->tx, heap, DYNAMIC_TYPE_TLSX);
+ XFREE(info->rx, heap, DYNAMIC_TYPE_TLSX);
+ XFREE(info->tx, heap, DYNAMIC_TYPE_TLSX);
XFREE(info, heap, DYNAMIC_TYPE_TLSX);
DtlsCidUnsetInfoFromExt(ext);
XFREE(ext, heap, DYNAMIC_TYPE_TLSX);
@@ -1190,7 +1224,7 @@ int TLSX_ConnectionID_Use(WOLFSSL* ssl)
info = (CIDInfo*)XMALLOC(sizeof(CIDInfo), ssl->heap, DYNAMIC_TYPE_TLSX);
if (info == NULL)
return MEMORY_ERROR;
- ext = (WOLFSSL**)XMALLOC(sizeof(WOLFSSL**), ssl->heap, DYNAMIC_TYPE_TLSX);
+ ext = (WOLFSSL**)XMALLOC(sizeof(WOLFSSL*), ssl->heap, DYNAMIC_TYPE_TLSX);
if (ext == NULL) {
XFREE(info, ssl->heap, DYNAMIC_TYPE_TLSX);
return MEMORY_ERROR;
@@ -1219,9 +1253,8 @@ int TLSX_ConnectionID_Use(WOLFSSL* ssl)
int TLSX_ConnectionID_Parse(WOLFSSL* ssl, const byte* input, word16 length,
byte isRequest)
{
- ConnectionID* id;
CIDInfo* info;
- byte cidSize;
+ byte cidSz;
TLSX* ext;
ext = TLSX_Find(ssl->extensions, TLSX_CONNECTION_ID);
@@ -1237,35 +1270,41 @@ int TLSX_ConnectionID_Parse(WOLFSSL* ssl, const byte* input, word16 length,
}
}
+ if (length < OPAQUE8_LEN)
+ return BUFFER_ERROR;
+
+ cidSz = *input;
+ if (cidSz + OPAQUE8_LEN > length)
+ return BUFFER_ERROR;
+
info = DtlsCidGetInfo(ssl);
if (info == NULL)
return BAD_STATE_E;
/* it may happen if we process two ClientHello because the server sent an
- * HRR request */
- if (info->tx != NULL) {
+ * HRR/HVR request */
+ if (info->tx != NULL || info->negotiated) {
if (ssl->options.side != WOLFSSL_SERVER_END &&
- ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE)
+ ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE &&
+ !IsSCR(ssl))
return BAD_STATE_E;
- XFREE(info->tx, ssl->heap, DYNAMIC_TYPE_TLSX);
- info->tx = NULL;
- }
-
- if (length < OPAQUE8_LEN)
- return BUFFER_ERROR;
-
- cidSize = *input;
- if (cidSize + OPAQUE8_LEN > length)
- return BUFFER_ERROR;
+ /* Should not be null if negotiated */
+ if (info->tx == NULL)
+ return BAD_STATE_E;
- if (cidSize > 0) {
- id = (ConnectionID*)XMALLOC(sizeof(*id) + cidSize, ssl->heap,
- DYNAMIC_TYPE_TLSX);
+ /* For now we don't support changing the CID on a rehandshake */
+ if (cidSz != info->tx->length ||
+ XMEMCMP(info->tx->id, input + OPAQUE8_LEN, cidSz) != 0)
+ return DTLS_CID_ERROR;
+ }
+ else if (cidSz > 0) {
+ ConnectionID* id = (ConnectionID*)XMALLOC(sizeof(*id) + cidSz,
+ ssl->heap, DYNAMIC_TYPE_TLSX);
if (id == NULL)
return MEMORY_ERROR;
- XMEMCPY(id->id, input + OPAQUE8_LEN, cidSize);
- id->length = cidSize;
+ XMEMCPY(id->id, input + OPAQUE8_LEN, cidSz);
+ id->length = cidSz;
info->tx = id;
}
@@ -1305,10 +1344,6 @@ int wolfSSL_dtls_cid_use(WOLFSSL* ssl)
{
int ret;
- /* CID is supported on DTLSv1.3 only */
- if (!IsAtLeastTLSv1_3(ssl->version))
- return WOLFSSL_FAILURE;
-
ssl->options.useDtlsCID = 1;
ret = TLSX_ConnectionID_Use(ssl);
if (ret != 0)
@@ -1334,8 +1369,9 @@ int wolfSSL_dtls_cid_set(WOLFSSL* ssl, unsigned char* cid, unsigned int size)
return WOLFSSL_FAILURE;
if (cidInfo->rx != NULL) {
- XFREE(cidInfo->rx, ssl->heap, DYNAMIC_TYPE_TLSX);
- cidInfo->rx = NULL;
+ WOLFSSL_MSG("wolfSSL doesn't support changing the CID during a "
+ "connection");
+ return WOLFSSL_FAILURE;
}
/* empty CID */
@@ -1363,6 +1399,11 @@ int wolfSSL_dtls_cid_get_rx(WOLFSSL* ssl, unsigned char* buf,
return DtlsCidGet(ssl, buf, bufferSz, 1);
}
+int wolfSSL_dtls_cid_get0_rx(WOLFSSL* ssl, unsigned char** cid)
+{
+ return DtlsCidGet0(ssl, cid, 1);
+}
+
int wolfSSL_dtls_cid_get_tx_size(WOLFSSL* ssl, unsigned int* size)
{
return DtlsCidGetSize(ssl, size, 0);
@@ -1374,7 +1415,77 @@ int wolfSSL_dtls_cid_get_tx(WOLFSSL* ssl, unsigned char* buf,
return DtlsCidGet(ssl, buf, bufferSz, 0);
}
+int wolfSSL_dtls_cid_get0_tx(WOLFSSL* ssl, unsigned char** cid)
+{
+ return DtlsCidGet0(ssl, cid, 0);
+}
+
+int wolfSSL_dtls_cid_max_size(void)
+{
+ return DTLS_CID_MAX_SIZE;
+}
+
+const unsigned char* wolfSSL_dtls_cid_parse(const unsigned char* msg,
+ unsigned int msgSz, unsigned int cidSz)
+{
+ /* we need at least the first byte to check version */
+ if (msg == NULL || cidSz == 0 || msgSz < OPAQUE8_LEN + cidSz)
+ return NULL;
+ if (msg[0] == dtls12_cid) {
+ /* DTLS 1.2 CID packet */
+ if (msgSz < DTLS_RECORD_HEADER_SZ + cidSz)
+ return NULL;
+ /* content type(1) + version(2) + epoch(2) + sequence(6) */
+ return msg + ENUM_LEN + VERSION_SZ + OPAQUE16_LEN + OPAQUE16_LEN +
+ OPAQUE32_LEN;
+ }
+#ifdef WOLFSSL_DTLS13
+ else if (Dtls13UnifiedHeaderCIDPresent(msg[0])) {
+ /* DTLS 1.3 CID packet */
+ if (msgSz < OPAQUE8_LEN + cidSz)
+ return NULL;
+ return msg + OPAQUE8_LEN;
+ }
+#endif
+ return NULL;
+}
#endif /* WOLFSSL_DTLS_CID */
+
+byte DtlsGetCidTxSize(WOLFSSL* ssl)
+{
+#ifdef WOLFSSL_DTLS_CID
+ unsigned int cidSz;
+ int ret;
+ ret = wolfSSL_dtls_cid_get_tx_size(ssl, &cidSz);
+ if (ret != WOLFSSL_SUCCESS)
+ return 0;
+ return (byte)cidSz;
+#else
+ (void)ssl;
+ return 0;
+#endif
+}
+
+byte DtlsGetCidRxSize(WOLFSSL* ssl)
+{
+#ifdef WOLFSSL_DTLS_CID
+ unsigned int cidSz;
+ int ret;
+ ret = wolfSSL_dtls_cid_get_rx_size(ssl, &cidSz);
+ if (ret != WOLFSSL_SUCCESS)
+ return 0;
+ return (byte)cidSz;
+#else
+ (void)ssl;
+ return 0;
+#endif
+}
+
+byte wolfSSL_is_stateful(WOLFSSL* ssl)
+{
+ return (byte)(ssl != NULL ? ssl->options.dtlsStateful : 0);
+}
+
#endif /* WOLFSSL_DTLS */
#endif /* WOLFCRYPT_ONLY */
diff --git a/src/src/dtls13.c b/src/src/dtls13.c
index 86e5fb8..9c729fa 100644
--- a/src/src/dtls13.c
+++ b/src/src/dtls13.c
@@ -1,12 +1,12 @@
/* dtls13.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,11 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
+#include
#ifdef WOLFSSL_DTLS13
@@ -31,10 +27,7 @@
#include
#include
#include
-#include
#include
-#include
-#include
#ifdef NO_INLINE
#include
@@ -71,6 +64,8 @@ typedef struct Dtls13HandshakeHeader {
byte fragmentLength[3];
} Dtls13HandshakeHeader;
+wc_static_assert(sizeof(Dtls13HandshakeHeader) == DTLS13_HANDSHAKE_HEADER_SZ);
+
/**
* struct Dtls13Recordplaintextheader: represent header of unprotected DTLSv1.3
* record
@@ -183,7 +178,8 @@ int Dtls13RlAddPlaintextHeader(WOLFSSL* ssl, byte* out,
/* seq[0] combines the epoch and 16 MSB of sequence number. We write on the
epoch field and will overflow to the first two bytes of the sequence
number */
- c32toa(seq[0], hdr->epoch);
+ c16toa((word16)(seq[0] >> 16), hdr->epoch);
+ c16toa((word16)seq[0], hdr->sequenceNumber);
c32toa(seq[1], &hdr->sequenceNumber[2]);
c16toa(length, hdr->length);
@@ -258,7 +254,8 @@ static int Dtls13GetRnMask(WOLFSSL* ssl, const byte* ciphertext, byte* mask,
if (c->aes == NULL)
return BAD_STATE_E;
#if !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
+ (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)) \
+ || defined(WOLFSSL_KERNEL_MODE))
return wc_AesEncryptDirect(c->aes, mask, ciphertext);
#else
wc_AesEncryptDirect(c->aes, mask, ciphertext);
@@ -339,9 +336,17 @@ static void Dtls13MsgWasProcessed(WOLFSSL* ssl, enum HandShakeType hs)
if (ssl->options.dtlsStateful)
ssl->keys.dtls_expected_peer_handshake_number++;
- /* we need to send ACKs on the last message of a flight that needs explicit
- acknowledgment */
- ssl->dtls13Rtx.sendAcks = Dtls13RtxMsgNeedsAck(ssl, hs);
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_LockMutex(&ssl->dtls13Rtx.mutex) == 0)
+#endif
+ {
+ /* we need to send ACKs on the last message of a flight that needs
+ * explicit acknowledgment */
+ ssl->dtls13Rtx.sendAcks = Dtls13RtxMsgNeedsAck(ssl, hs);
+ #ifdef WOLFSSL_RW_THREADED
+ wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
+ #endif
+ }
}
int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
@@ -395,8 +400,10 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
* from there, the message can be considered processed successfully.
* WANT_WRITE means that we are done with processing the msg and we are
* waiting to flush the output buffer. */
- if ((ret == 0 || ret == WANT_WRITE) || (msg->type == certificate_request &&
- ssl->options.handShakeDone && ret == WC_PENDING_E)) {
+ if ((ret == 0 || ret == WC_NO_ERR_TRACE(WANT_WRITE)) ||
+ (msg->type == certificate_request &&
+ ssl->options.handShakeDone &&
+ ret == WC_NO_ERR_TRACE(WC_PENDING_E))) {
if (IsAtLeastTLSv1_3(ssl->version))
Dtls13MsgWasProcessed(ssl, (enum HandShakeType)msg->type);
else if (downgraded)
@@ -483,22 +490,25 @@ int Dtls13HashClientHello(const WOLFSSL* ssl, byte* hash, int* hashSz,
wc_HashAlg hashCtx;
int type = wolfSSL_GetHmacType_ex(specs);
+ if (type < 0)
+ return type;
+
header[0] = (byte)client_hello;
c32to24(length, header + 1);
- ret = wc_HashInit_ex(&hashCtx, type, ssl->heap, ssl->devId);
+ ret = wc_HashInit_ex(&hashCtx, (enum wc_HashType)type, ssl->heap, ssl->devId);
if (ret == 0) {
- ret = wc_HashUpdate(&hashCtx, type, header, OPAQUE32_LEN);
+ ret = wc_HashUpdate(&hashCtx, (enum wc_HashType)type, header, OPAQUE32_LEN);
if (ret == 0)
- ret = wc_HashUpdate(&hashCtx, type, body, length);
+ ret = wc_HashUpdate(&hashCtx, (enum wc_HashType)type, body, length);
if (ret == 0)
- ret = wc_HashFinal(&hashCtx, type, hash);
+ ret = wc_HashFinal(&hashCtx, (enum wc_HashType)type, hash);
if (ret == 0) {
- *hashSz = wc_HashGetDigestSize(type);
+ *hashSz = wc_HashGetDigestSize((enum wc_HashType)type);
if (*hashSz < 0)
ret = *hashSz;
}
- wc_HashFree(&hashCtx, type);
+ wc_HashFree(&hashCtx, (enum wc_HashType)type);
}
return ret;
}
@@ -556,9 +566,6 @@ static int Dtls13SendFragment(WOLFSSL* ssl, byte* output, word16 output_size,
else {
msg = output + recordHeaderLength;
- if (length <= recordHeaderLength)
- return BUFFER_ERROR;
-
if (hashOutput) {
ret = Dtls13HashHandshake(ssl, msg, recordLength);
if (ret != 0)
@@ -650,8 +657,17 @@ static void Dtls13RtxRecordUnlink(WOLFSSL* ssl, Dtls13RtxRecord** prevNext,
Dtls13RtxRecord* r)
{
/* if r was at the tail of the list, update the tail pointer */
- if (r->next == NULL)
- ssl->dtls13Rtx.rtxRecordTailPtr = prevNext;
+ if (r->next == NULL) {
+ #ifdef WOLFSSL_RW_THREADED
+ if (wc_LockMutex(&ssl->dtls13Rtx.mutex) == 0)
+ #endif
+ {
+ ssl->dtls13Rtx.rtxRecordTailPtr = prevNext;
+ #ifdef WOLFSSL_RW_THREADED
+ wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
+ #endif
+ }
+ }
/* unlink */
*prevNext = r->next;
@@ -702,18 +718,42 @@ static Dtls13RecordNumber* Dtls13NewRecordNumber(w64wrapper epoch,
return rn;
}
-static int Dtls13RtxAddAck(WOLFSSL* ssl, w64wrapper epoch, w64wrapper seq)
+int Dtls13RtxAddAck(WOLFSSL* ssl, w64wrapper epoch, w64wrapper seq)
{
Dtls13RecordNumber* rn;
WOLFSSL_ENTER("Dtls13RtxAddAck");
- rn = Dtls13NewRecordNumber(epoch, seq, ssl->heap);
- if (rn == NULL)
- return MEMORY_E;
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_LockMutex(&ssl->dtls13Rtx.mutex) == 0)
+#endif
+ {
+ /* Find location to insert new record */
+ Dtls13RecordNumber** prevNext = &ssl->dtls13Rtx.seenRecords;
+ Dtls13RecordNumber* cur = ssl->dtls13Rtx.seenRecords;
+
+ for (; cur != NULL; prevNext = &cur->next, cur = cur->next) {
+ if (w64Equal(cur->epoch, epoch) && w64Equal(cur->seq, seq)) {
+ /* already in list. no duplicates. */
+ return 0;
+ }
+ else if (w64LT(epoch, cur->epoch)
+ || (w64Equal(epoch, cur->epoch)
+ && w64LT(seq, cur->seq))) {
+ break;
+ }
+ }
+
+ rn = Dtls13NewRecordNumber(epoch, seq, ssl->heap);
+ if (rn == NULL)
+ return MEMORY_E;
- rn->next = ssl->dtls13Rtx.seenRecords;
- ssl->dtls13Rtx.seenRecords = rn;
+ *prevNext = rn;
+ rn->next = cur;
+ #ifdef WOLFSSL_RW_THREADED
+ wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
+ #endif
+ }
return 0;
}
@@ -726,15 +766,23 @@ static void Dtls13RtxFlushAcks(WOLFSSL* ssl)
WOLFSSL_ENTER("Dtls13RtxFlushAcks");
- list = ssl->dtls13Rtx.seenRecords;
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_LockMutex(&ssl->dtls13Rtx.mutex) == 0)
+#endif
+ {
+ list = ssl->dtls13Rtx.seenRecords;
- while (list != NULL) {
- rn = list;
- list = rn->next;
- XFREE(rn, ssl->heap, DYNAMIC_TYPE_DTLS_MSG);
- }
+ while (list != NULL) {
+ rn = list;
+ list = rn->next;
+ XFREE(rn, ssl->heap, DYNAMIC_TYPE_DTLS_MSG);
+ }
- ssl->dtls13Rtx.seenRecords = NULL;
+ ssl->dtls13Rtx.seenRecords = NULL;
+ #ifdef WOLFSSL_RW_THREADED
+ wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
+ #endif
+ }
}
static int Dtls13DetectDisruption(WOLFSSL* ssl, word32 fragOffset)
@@ -810,9 +858,7 @@ static void Dtls13MaybeSaveClientHello(WOLFSSL* ssl)
while (r != NULL) {
if (r->handshakeType == client_hello) {
Dtls13RtxRecordUnlink(ssl, prev_next, r);
- if (ssl->dtls13ClientHello != NULL)
- XFREE(ssl->dtls13ClientHello, ssl->heap,
- DYNAMIC_TYPE_DTLS_MSG);
+ XFREE(ssl->dtls13ClientHello, ssl->heap, DYNAMIC_TYPE_DTLS_MSG);
ssl->dtls13ClientHello = r->data;
ssl->dtls13ClientHelloSz = r->length;
r->data = NULL;
@@ -859,7 +905,7 @@ static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs,
/* the other peer may have retransmitted because an ACK for a flight
that needs explicit ACK was lost.*/
if (ssl->dtls13Rtx.seenRecords != NULL)
- ssl->dtls13Rtx.sendAcks = (byte)ssl->options.dtls13SendMoreAcks;
+ ssl->dtls13Rtx.sendAcks = 1;
}
if (ssl->keys.dtls_peer_handshake_number ==
@@ -920,7 +966,7 @@ static int Dtls13SendOneFragmentRtx(WOLFSSL* ssl,
handshakeType, hashOutput, Dtls13SendNow(ssl, handshakeType));
if (rtxRecord != NULL) {
- if (ret == 0 || ret == WANT_WRITE)
+ if (ret == 0 || ret == WC_NO_ERR_TRACE(WANT_WRITE))
Dtls13RtxAddRecord(&ssl->dtls13Rtx, rtxRecord);
else
Dtls13FreeRtxBufferRecord(ssl, rtxRecord);
@@ -980,7 +1026,7 @@ static int Dtls13SendFragmentedInternal(WOLFSSL* ssl)
ret = Dtls13SendOneFragmentRtx(ssl,
(enum HandShakeType)ssl->dtls13FragHandshakeType,
(word16)recordLength + MAX_MSG_EXTRA, output, (word32)recordLength, 0);
- if (ret == WANT_WRITE) {
+ if (ret == WC_NO_ERR_TRACE(WANT_WRITE)) {
ssl->dtls13FragOffset += fragLength;
return ret;
}
@@ -1052,45 +1098,26 @@ static WC_INLINE word8 Dtls13GetEpochBits(w64wrapper epoch)
}
#ifdef WOLFSSL_DTLS_CID
-static byte Dtls13GetCidTxSize(WOLFSSL* ssl)
-{
- unsigned int cidSz;
- int ret;
- ret = wolfSSL_dtls_cid_get_tx_size(ssl, &cidSz);
- if (ret != WOLFSSL_SUCCESS)
- return 0;
- return (byte)cidSz;
-}
-
-static byte Dtls13GetCidRxSize(WOLFSSL* ssl)
-{
- unsigned int cidSz;
- int ret;
- ret = wolfSSL_dtls_cid_get_rx_size(ssl, &cidSz);
- if (ret != WOLFSSL_SUCCESS)
- return 0;
- return (byte)cidSz;
-}
static int Dtls13AddCID(WOLFSSL* ssl, byte* flags, byte* out, word16* idx)
{
- byte cidSize;
+ byte cidSz;
int ret;
if (!wolfSSL_dtls_cid_is_enabled(ssl))
return 0;
- cidSize = Dtls13GetCidTxSize(ssl);
+ cidSz = DtlsGetCidTxSize(ssl);
/* no cid */
- if (cidSize == 0)
+ if (cidSz == 0)
return 0;
*flags |= DTLS13_CID_BIT;
- /* we know that we have at least cidSize of space */
- ret = wolfSSL_dtls_cid_get_tx(ssl, out + *idx, cidSize);
+ /* we know that we have at least cidSz of space */
+ ret = wolfSSL_dtls_cid_get_tx(ssl, out + *idx, cidSz);
if (ret != WOLFSSL_SUCCESS)
return ret;
- *idx += cidSize;
+ *idx += cidSz;
return 0;
}
@@ -1134,10 +1161,13 @@ static int Dtls13UnifiedHeaderParseCID(WOLFSSL* ssl, byte flags,
return 0;
}
+int Dtls13UnifiedHeaderCIDPresent(byte flags)
+{
+ return Dtls13IsUnifiedHeader(flags) && (flags & DTLS13_CID_BIT);
+}
+
#else
#define Dtls13AddCID(a, b, c, d) 0
-#define Dtls13GetCidRxSize(a) 0
-#define Dtls13GetCidTxSize(a) 0
#define Dtls13UnifiedHeaderParseCID(a, b, c, d, e) 0
#endif /* WOLFSSL_DTLS_CID */
@@ -1209,6 +1239,11 @@ int Dtls13HandshakeAddHeader(WOLFSSL* ssl, byte* output,
return 0;
}
+int Dtls13MinimumRecordLength(WOLFSSL* ssl)
+{
+ return Dtls13GetRlHeaderLength(ssl, 1) + DTLS13_MIN_CIPHERTEXT;
+}
+
/**
* Dtls13EncryptRecordNumber() - encrypt record number in the header
* @ssl: ssl object
@@ -1225,14 +1260,20 @@ int Dtls13EncryptRecordNumber(WOLFSSL* ssl, byte* hdr, word16 recordLength)
if (ssl == NULL || hdr == NULL)
return BAD_FUNC_ARG;
+#ifdef HAVE_NULL_CIPHER
+ /* Do not encrypt record numbers with null cipher. See RFC 9150 Sec 9 */
+ if (ssl->specs.bulk_cipher_algorithm == wolfssl_cipher_null)
+ return 0;
+#endif /*HAVE_NULL_CIPHER */
+
/* we need at least a 16 bytes of ciphertext to encrypt record number see
4.2.3*/
- if (recordLength < Dtls13GetRlHeaderLength(ssl, 1) + DTLS13_MIN_CIPHERTEXT)
+ if (recordLength < Dtls13MinimumRecordLength(ssl))
return BUFFER_ERROR;
seqLength = (*hdr & DTLS13_LEN_BIT) ? DTLS13_SEQ_16_LEN : DTLS13_SEQ_8_LEN;
- cidSz = Dtls13GetCidTxSize(ssl);
+ cidSz = DtlsGetCidTxSize(ssl);
/* header flags + seq number + CID size*/
hdrLength = OPAQUE8_LEN + seqLength + cidSz;
@@ -1263,7 +1304,7 @@ word16 Dtls13GetRlHeaderLength(WOLFSSL* ssl, byte isEncrypted)
if (!isEncrypted)
return DTLS_RECORD_HEADER_SZ;
- return DTLS13_UNIFIED_HEADER_SIZE + Dtls13GetCidTxSize(ssl);
+ return DTLS13_UNIFIED_HEADER_SIZE + DtlsGetCidTxSize(ssl);
}
/**
@@ -1390,7 +1431,7 @@ int Dtls13GetUnifiedHeaderSize(WOLFSSL* ssl, const byte input, word16* size)
return BAD_FUNC_ARG;
/* flags (1) + CID + seq 8bit (1) */
- *size = OPAQUE8_LEN + Dtls13GetCidRxSize(ssl) + OPAQUE8_LEN;
+ *size = OPAQUE8_LEN + DtlsGetCidRxSize(ssl) + OPAQUE8_LEN;
if (input & DTLS13_SEQ_LEN_BIT)
*size += OPAQUE8_LEN;
if (input & DTLS13_LEN_BIT)
@@ -1453,17 +1494,22 @@ int Dtls13ParseUnifiedRecordLayer(WOLFSSL* ssl, const byte* input,
hdrInfo->recordLength = inputSize - idx;
}
- /* minimum size for a dtls1.3 packet is 16 bytes (to have enough ciphertext
- to create record number xor mask). (draft 43 - Sec 4.2.3) */
- if (hdrInfo->recordLength < DTLS13_RN_MASK_SIZE)
- return LENGTH_ERROR;
- if (inputSize < idx + DTLS13_RN_MASK_SIZE)
- return BUFFER_ERROR;
+ /* Do not encrypt record numbers with null cipher. See RFC 9150 Sec 9 */
+ if (ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null)
+ {
+ /* minimum size for a dtls1.3 packet is 16 bytes (to have enough
+ * ciphertext to create record number xor mask).
+ * (draft 43 - Sec 4.2.3) */
+ if (hdrInfo->recordLength < DTLS13_RN_MASK_SIZE)
+ return LENGTH_ERROR;
+ if (inputSize < idx + DTLS13_RN_MASK_SIZE)
+ return BUFFER_ERROR;
- ret = Dtls13EncryptDecryptRecordNumber(ssl, seqNum, seqLen, input + idx,
- DEPROTECT);
- if (ret != 0)
- return ret;
+ ret = Dtls13EncryptDecryptRecordNumber(ssl, seqNum, seqLen, input + idx,
+ DEPROTECT);
+ if (ret != 0)
+ return ret;
+ }
if (seqLen == DTLS13_SEQ_16_LEN) {
hdrInfo->seqHiPresent = 1;
@@ -1515,11 +1561,14 @@ static int Dtls13RtxSendBuffered(WOLFSSL* ssl)
byte* output;
int isLast;
int sendSz;
+#ifndef NO_ASN_TIME
word32 now;
+#endif
int ret;
WOLFSSL_ENTER("Dtls13RtxSendBuffered");
+#ifndef NO_ASN_TIME
now = LowResTimer();
if (now - ssl->dtls13Rtx.lastRtx < DTLS13_MIN_RTX_INTERVAL) {
#ifdef WOLFSSL_DEBUG_TLS
@@ -1529,6 +1578,7 @@ static int Dtls13RtxSendBuffered(WOLFSSL* ssl)
}
ssl->dtls13Rtx.lastRtx = now;
+#endif
r = ssl->dtls13Rtx.rtxRecords;
prevNext = &ssl->dtls13Rtx.rtxRecords;
@@ -1562,7 +1612,7 @@ static int Dtls13RtxSendBuffered(WOLFSSL* ssl)
ret = Dtls13SendFragment(ssl, output, (word16)sendSz, r->length + headerLength,
(enum HandShakeType)r->handshakeType, 0,
isLast || !ssl->options.groupMessages);
- if (ret != 0 && ret != WANT_WRITE)
+ if (ret != 0 && ret != WC_NO_ERR_TRACE(WANT_WRITE))
return ret;
if (r->rnIdx >= DTLS13_RETRANS_RN_SIZE)
@@ -1576,7 +1626,7 @@ static int Dtls13RtxSendBuffered(WOLFSSL* ssl)
r->seq[r->rnIdx] = seq;
r->rnIdx++;
- if (ret == WANT_WRITE) {
+ if (ret == WC_NO_ERR_TRACE(WANT_WRITE)) {
/* this fragment will be sent eventually. Move it to the end of the
list so next time we start with a new one. */
Dtls13RtxMoveToEndOfList(ssl, prevNext, r);
@@ -1603,6 +1653,102 @@ static int Dtls13AcceptFragmented(WOLFSSL *ssl, enum HandShakeType type)
#endif
return 0;
}
+
+int Dtls13CheckEpoch(WOLFSSL* ssl, enum HandShakeType type)
+{
+ w64wrapper plainEpoch = w64From32(0x0, 0x0);
+ w64wrapper hsEpoch = w64From32(0x0, DTLS13_EPOCH_HANDSHAKE);
+ w64wrapper t0Epoch = w64From32(0x0, DTLS13_EPOCH_TRAFFIC0);
+
+ if (IsAtLeastTLSv1_3(ssl->version)) {
+ switch (type) {
+ case client_hello:
+ case server_hello:
+ case hello_verify_request:
+ case hello_retry_request:
+ case hello_request:
+ if (!w64Equal(ssl->keys.curEpoch64, plainEpoch)) {
+ WOLFSSL_MSG("Msg should be epoch 0");
+ WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
+ return SANITY_MSG_E;
+ }
+ break;
+ case encrypted_extensions:
+ case server_key_exchange:
+ case server_hello_done:
+ case client_key_exchange:
+ if (!w64Equal(ssl->keys.curEpoch64, hsEpoch)) {
+ if (ssl->options.side == WOLFSSL_CLIENT_END &&
+ ssl->options.serverState < SERVER_HELLO_COMPLETE) {
+ /* before processing SH we don't know which version
+ * will be negotiated. */
+ if (!w64Equal(ssl->keys.curEpoch64, plainEpoch)) {
+ WOLFSSL_MSG("Msg should be epoch 2 or 0");
+ WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
+ return SANITY_MSG_E;
+ }
+ }
+ else {
+ WOLFSSL_MSG("Msg should be epoch 2");
+ WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
+ return SANITY_MSG_E;
+ }
+ }
+ break;
+ case certificate_request:
+ case certificate:
+ case certificate_verify:
+ case finished:
+ if (!ssl->options.handShakeDone) {
+ if (!w64Equal(ssl->keys.curEpoch64, hsEpoch)) {
+ if (ssl->options.side == WOLFSSL_CLIENT_END &&
+ ssl->options.serverState < SERVER_HELLO_COMPLETE) {
+ /* before processing SH we don't know which version
+ * will be negotiated. */
+ if (!w64Equal(ssl->keys.curEpoch64, plainEpoch)) {
+ WOLFSSL_MSG("Msg should be epoch 2 or 0");
+ WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
+ return SANITY_MSG_E;
+ }
+ }
+ else {
+ WOLFSSL_MSG("Msg should be epoch 2");
+ WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
+ return SANITY_MSG_E;
+ }
+ }
+ }
+ else {
+ /* Allow epoch 2 in case of rtx */
+ if (!w64GTE(ssl->keys.curEpoch64, hsEpoch)) {
+ WOLFSSL_MSG("Msg should be epoch 2+");
+ WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
+ return SANITY_MSG_E;
+ }
+ }
+ break;
+ case certificate_status:
+ case change_cipher_hs:
+ case key_update:
+ case session_ticket:
+ if (!w64GTE(ssl->keys.curEpoch64, t0Epoch)) {
+ WOLFSSL_MSG("Msg should be epoch 3+");
+ WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
+ return SANITY_MSG_E;
+ }
+ break;
+ case end_of_early_data:
+ case message_hash:
+ case no_shake:
+ default:
+ WOLFSSL_MSG("Unknown message type");
+ WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
+ return SANITY_MSG_E;
+ }
+ }
+ return 0;
+}
+
/**
* Dtls13HandshakeRecv() - process an handshake message. Deal with
fragmentation if needed
@@ -1638,6 +1784,12 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
return ret;
}
+ ret = Dtls13CheckEpoch(ssl, (enum HandShakeType)handshakeType);
+ if (ret != 0) {
+ WOLFSSL_ERROR(ret);
+ return ret;
+ }
+
if (ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.acceptState < TLS13_ACCEPT_FIRST_REPLY_DONE) {
if (handshakeType != client_hello) {
@@ -1683,7 +1835,7 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
isFirst = fragOff == 0;
isComplete = isFirst && fragLength == messageLength;
- if (!isComplete && !Dtls13AcceptFragmented(ssl, handshakeType)) {
+ if (!isComplete && !Dtls13AcceptFragmented(ssl, (enum HandShakeType)handshakeType)) {
#ifdef WOLFSSL_DTLS_CH_FRAG
byte tls13 = 0;
/* check if the first CH fragment contains a valid cookie */
@@ -1746,11 +1898,11 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
ret = DoTls13HandShakeMsgType(ssl, input, &idx, handshakeType,
messageLength, size);
+ *processedSize = idx;
if (ret != 0)
return ret;
Dtls13MsgWasProcessed(ssl, (enum HandShakeType)handshakeType);
- *processedSize = idx;
/* check if we have buffered some message */
if (Dtls13NextMessageComplete(ssl))
@@ -1875,7 +2027,7 @@ int Dtls13HandshakeSend(WOLFSSL* ssl, byte* message, word16 outputSize,
if (maxLen < maxFrag) {
ret = Dtls13SendOneFragmentRtx(ssl, handshakeType, outputSize, message,
length, hashOutput);
- if (ret == 0 || ret == WANT_WRITE)
+ if (ret == 0 || ret == WC_NO_ERR_TRACE(WANT_WRITE))
ssl->keys.dtls_handshake_number++;
}
else {
@@ -1925,6 +2077,9 @@ int Dtls13DeriveSnKeys(WOLFSSL* ssl, int provision)
end:
ForceZero(key_dig, MAX_PRF_DIG);
+#ifdef WOLFSSL_CHECK_MEM_ZERO
+ wc_MemZero_Check(key_dig, sizeof(key_dig));
+#endif
return ret;
}
@@ -2383,7 +2538,7 @@ static int Dtls13GetAckListLength(Dtls13RecordNumber* list, word16* length)
return 0;
}
-static int Dtls13WriteAckMessage(WOLFSSL* ssl,
+int Dtls13WriteAckMessage(WOLFSSL* ssl,
Dtls13RecordNumber* recordNumberList, word32* length)
{
word16 msgSz, headerLength;
@@ -2463,19 +2618,16 @@ static int Dtls13RtxIsTrackedByRn(const Dtls13RtxRecord* r, w64wrapper epoch,
static int Dtls13KeyUpdateAckReceived(WOLFSSL* ssl)
{
int ret;
- w64Increment(&ssl->dtls13Epoch);
-
- /* Epoch wrapped up */
- if (w64IsZero(ssl->dtls13Epoch))
- return BAD_STATE_E;
ret = DeriveTls13Keys(ssl, update_traffic_key, ENCRYPT_SIDE_ONLY, 1);
if (ret != 0)
return ret;
- ret = Dtls13NewEpoch(ssl, ssl->dtls13Epoch, ENCRYPT_SIDE_ONLY);
- if (ret != 0)
- return ret;
+ w64Increment(&ssl->dtls13Epoch);
+
+ /* Epoch wrapped up */
+ if (w64IsZero(ssl->dtls13Epoch))
+ return BAD_STATE_E;
return Dtls13SetEpochKeys(ssl, ssl->dtls13Epoch, ENCRYPT_SIDE_ONLY);
}
@@ -2522,13 +2674,25 @@ static void Dtls13RtxRemoveRecord(WOLFSSL* ssl, w64wrapper epoch,
int Dtls13DoScheduledWork(WOLFSSL* ssl)
{
int ret;
+ int sendAcks;
WOLFSSL_ENTER("Dtls13DoScheduledWork");
ssl->dtls13SendingAckOrRtx = 1;
- if (ssl->dtls13Rtx.sendAcks) {
+#ifdef WOLFSSL_RW_THREADED
+ ret = wc_LockMutex(&ssl->dtls13Rtx.mutex);
+ if (ret < 0)
+ return ret;
+#endif
+ sendAcks = ssl->dtls13Rtx.sendAcks;
+ if (sendAcks) {
ssl->dtls13Rtx.sendAcks = 0;
+ }
+#ifdef WOLFSSL_RW_THREADED
+ ret = wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
+#endif
+ if (sendAcks) {
ret = SendDtls13Ack(ssl);
if (ret != 0)
return ret;
@@ -2585,7 +2749,7 @@ int Dtls13RtxTimeout(WOLFSSL* ssl)
/* Increase timeout on long timeout */
if (DtlsMsgPoolTimeout(ssl) != 0)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
return Dtls13RtxSendBuffered(ssl);
}
@@ -2604,13 +2768,28 @@ static int Dtls13RtxHasKeyUpdateBuffered(WOLFSSL* ssl)
return 0;
}
+int DoDtls13KeyUpdateAck(WOLFSSL* ssl)
+{
+ int ret = 0;
+
+ if (!Dtls13RtxHasKeyUpdateBuffered(ssl)) {
+ /* we removed the KeyUpdate message because it was ACKed */
+ ssl->dtls13WaitKeyUpdateAck = 0;
+ ret = Dtls13KeyUpdateAckReceived(ssl);
+ }
+
+ return ret;
+}
+
int DoDtls13Ack(WOLFSSL* ssl, const byte* input, word32 inputSize,
word32* processedSize)
{
const byte* ackMessage;
w64wrapper epoch, seq;
word16 length;
+#ifndef WOLFSSL_RW_THREADED
int ret;
+#endif
int i;
if (inputSize < OPAQUE16_LEN)
@@ -2642,15 +2821,13 @@ int DoDtls13Ack(WOLFSSL* ssl, const byte* input, word32 inputSize,
ssl->options.serverState = SERVER_FINISHED_ACKED;
}
+#ifndef WOLFSSL_RW_THREADED
if (ssl->dtls13WaitKeyUpdateAck) {
- if (!Dtls13RtxHasKeyUpdateBuffered(ssl)) {
- /* we removed the KeyUpdate message because it was ACKed */
- ssl->dtls13WaitKeyUpdateAck = 0;
- ret = Dtls13KeyUpdateAckReceived(ssl);
- if (ret != 0)
- return ret;
- }
+ ret = DoDtls13KeyUpdateAck(ssl);
+ if (ret != 0)
+ return ret;
}
+#endif
*processedSize = length + OPAQUE16_LEN;
@@ -2701,9 +2878,17 @@ int SendDtls13Ack(WOLFSSL* ssl)
if (ret != 0)
return ret;
- ret = Dtls13WriteAckMessage(ssl, ssl->dtls13Rtx.seenRecords, &length);
- if (ret != 0)
+#ifdef WOLFSSL_RW_THREADED
+ ret = wc_LockMutex(&ssl->dtls13Rtx.mutex);
+ if (ret < 0)
return ret;
+#endif
+ ret = Dtls13WriteAckMessage(ssl, ssl->dtls13Rtx.seenRecords, &length);
+#ifdef WOLFSSL_RW_THREADED
+ wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
+#endif
+ if (ret != 0)
+ return ret;
output = GetOutputBuffer(ssl);
diff --git a/src/src/internal.c b/src/src/internal.c
index 552cf10..30c27fb 100644
--- a/src/src/internal.c
+++ b/src/src/internal.c
@@ -1,12 +1,12 @@
/* internal.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,13 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
-
-
-#ifdef HAVE_CONFIG_H
- #include
-#endif
-
-#include
+#include
/*
* WOLFSSL_SMALL_CERT_VERIFY:
@@ -92,14 +86,10 @@
* WOLFSSL_NO_INIT_CTX_KEY
* Allows SSL objects to be created from a CTX without a loaded key/cert
* pair
+ * WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS:
+ * When defined, allows DTLS records to span across multiple datagrams.
*/
-
-#ifdef EXTERNAL_OPTS_OPENVPN
-#error EXTERNAL_OPTS_OPENVPN should not be defined\
- when building wolfSSL
-#endif
-
#ifndef WOLFCRYPT_ONLY
#include
@@ -149,7 +139,7 @@
#endif
-#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
+#define ERROR_OUT(err, eLabel) { ret = (int)(err); goto eLabel; }
#ifdef _MSC_VER
/* disable for while(0) cases at the .c level for now */
@@ -165,7 +155,7 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#error Cannot use both secure-renegotiation and renegotiation-indication
#endif
-#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_TLS) && !defined(WOLFSSL_NO_TLS12)
#ifndef NO_WOLFSSL_CLIENT
static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
@@ -178,7 +168,7 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
static int DoSessionTicket(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 size);
#endif
-#endif
+#endif /* !NO_WOLFSSL_CLIENT */
#ifndef NO_WOLFSSL_SERVER
@@ -191,7 +181,7 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#endif
#endif /* !NO_WOLFSSL_SERVER */
-#endif /* !WOLFSSL_NO_TLS12 */
+#endif /* !NO_TLS && !WOLFSSL_NO_TLS12 */
#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET)
#if defined(WOLFSSL_HAPROXY)
@@ -199,7 +189,7 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#else
#define SSL_TICKET_CTX(ssl) ssl->ctx->ticketEncCtx
#endif
- #if !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB)
+ #if !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && !defined(NO_TLS)
static int TicketEncCbCtx_Init(WOLFSSL_CTX* ctx,
TicketEncCbCtx* keyCtx);
static void TicketEncCbCtx_Free(TicketEncCbCtx* keyCtx);
@@ -210,8 +200,10 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
int enc, byte* ticket, int inLen, int* outLen,
void* userCtx);
#endif
-#endif
+#endif /* !NO_WOLFSSL_SERVER && HAVE_SESSION_TICKET */
+int writeAeadAuthData(WOLFSSL* ssl, word16 sz, byte type, byte* additional,
+ byte dec, byte** seq, int verifyOrder);
#ifdef WOLFSSL_DTLS
static int _DtlsCheckWindow(WOLFSSL* ssl);
@@ -221,7 +213,7 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#include
#include
#include
-static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs,
+static int DoAppleNativeCertValidation(WOLFSSL* ssl, const WOLFSSL_BUFFER_INFO* certs,
int totalCerts);
#endif /* #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */
@@ -246,13 +238,14 @@ enum processReply {
};
-#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_TLS) && !defined(WOLFSSL_NO_TLS12)
#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */
static const byte tls13Downgrade[7] = {
0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44
};
+
#define TLS13_DOWNGRADE_SZ sizeof(tls13Downgrade)
#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
@@ -263,7 +256,70 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
#endif
-#endif /* !WOLFSSL_NO_TLS12 */
+#endif /* !NO_TLS && !WOLFSSL_NO_TLS12 */
+
+
+#if !defined(NO_CERT) && defined(WOLFSSL_BLIND_PRIVATE_KEY)
+int wolfssl_priv_der_blind(WC_RNG* rng, DerBuffer* key, DerBuffer** mask)
+{
+ int ret = 0;
+ WC_RNG local_rng;
+
+ if (key != NULL) {
+ if (*mask != NULL) {
+ FreeDer(mask);
+ }
+ ret = AllocDer(mask, key->length, key->type, key->heap);
+ if ((ret == 0) && (rng == NULL)) {
+ if (wc_InitRng(&local_rng) != 0) {
+ ret = RNG_FAILURE_E;
+ }
+ else {
+ rng = &local_rng;
+ }
+ }
+ if (ret == 0) {
+ ret = wc_RNG_GenerateBlock(rng, (*mask)->buffer, (*mask)->length);
+ }
+ if (ret == 0) {
+ xorbuf(key->buffer, (*mask)->buffer, (*mask)->length);
+ }
+
+ if (rng == &local_rng) {
+ wc_FreeRng(rng);
+ }
+ }
+
+ return ret;
+}
+
+void wolfssl_priv_der_blind_toggle(DerBuffer* key, const DerBuffer* mask)
+{
+ if ((key != NULL) && (mask != NULL)) {
+ xorbuf(key->buffer, mask->buffer, mask->length);
+ }
+}
+
+DerBuffer *wolfssl_priv_der_unblind(const DerBuffer* key, const DerBuffer* mask)
+{
+ DerBuffer *ret;
+ if ((key == NULL) || (mask == NULL))
+ return NULL;
+ if (mask->length > key->length)
+ return NULL;
+ if (AllocDer(&ret, key->length, key->type, key->heap) != 0)
+ return NULL;
+ xorbufout(ret->buffer, key->buffer, mask->buffer, mask->length);
+ return ret;
+}
+
+void wolfssl_priv_der_unblind_free(DerBuffer* key)
+{
+ if (key != NULL)
+ FreeDer(&key);
+}
+
+#endif /* !NO_CERT && WOLFSSL_BLIND_PRIVATE_KEY */
#if defined(WOLFSSL_RENESAS_FSPSM_TLS) || defined(WOLFSSL_RENESAS_TSIP_TLS)
@@ -279,67 +335,47 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
const unsigned char* secret, int secretSz, void* ctx);
#endif
-
- /* Label string for client random. */
- #define SSC_CR "CLIENT_RANDOM"
-
/*
* This function builds up string for key-logging then call user's
- * key-log-callback to pass the string for TLS1.2 and older.
+ * key-log-callback to pass the string.
* The user's key-logging callback has been set via
* wolfSSL_CTX_set_keylog_callback function. The logging string format is:
- * "CLIENT_RANDOM "
+ * " "
+ *
* parameter
* - ssl: WOLFSSL object
- * - secret: pointer to the buffer holding master-secret
+ * - secret: pointer to the buffer holding secret
* - secretSz: size of secret
- * - ctx: not used
+ * - label: for logging string
+ * - labelSz: label size
* returns 0 on success, negative value on failure.
*/
- static int SessionSecret_callback(WOLFSSL* ssl, void* secret,
- int* secretSz, void* ctx)
+ static int SessionSecret_callback_common(const WOLFSSL* ssl,
+ const unsigned char* secret, int secretSz,
+ const char* label, int labelSz)
{
wolfSSL_CTX_keylog_cb_func logCb = NULL;
- int msSz;
- int hasVal;
- int i;
- const char* label = SSC_CR;
- int labelSz = sizeof(SSC_CR);
int buffSz;
byte* log = NULL;
word32 outSz;
int idx;
int ret;
- (void)ctx;
- if (ssl == NULL || secret == NULL || *secretSz == 0)
+ if (ssl == NULL || secret == NULL || secretSz == 0 ||
+ label == NULL || labelSz == 0)
return BAD_FUNC_ARG;
- if (ssl->arrays == NULL)
+ if (ssl->arrays == NULL || ssl->ctx == NULL)
return BAD_FUNC_ARG;
- /* get the user-callback func from CTX*/
+ /* get the user-callback func from CTX */
logCb = ssl->ctx->keyLogCb;
if (logCb == NULL)
return 0;
- /* need to make sure the given master-secret has a meaningful value */
- msSz = *secretSz;
- hasVal = 0;
- for (i = 0; i < msSz; i++) {
- if (*((byte*)secret) != 0) {
- hasVal = 1;
- break;
- }
- }
- if (hasVal == 0)
- return 0; /* master-secret looks invalid */
-
- /* build up a hex-decoded keylog string
- "CLIENT_RANDOM "
- note that each keylog string does not have CR/LF.
- */
- buffSz = labelSz + (RAN_LEN * 2) + 1 + ((*secretSz) * 2) + 1;
- log = XMALLOC(buffSz, ssl->heap, DYNAMIC_TYPE_SECRET);
+ /* prepare a log string for passing user callback
+ * " " */
+ buffSz = labelSz + (RAN_LEN * 2) + 1 + secretSz * 2 + 1;
+ log = XMALLOC(buffSz, ssl->heap, DYNAMIC_TYPE_SECRET);
if (log == NULL)
return MEMORY_E;
#ifdef WOLFSSL_CHECK_MEM_ZERO
@@ -347,8 +383,9 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
#endif
XMEMSET(log, 0, buffSz);
- XMEMCPY(log, label, labelSz -1); /* put label w/o terminator */
+ XMEMCPY(log, label, labelSz - 1); /* put label w/o terminator */
log[labelSz - 1] = ' '; /* '\0' -> ' ' */
+
idx = labelSz;
outSz = buffSz - idx;
if ((ret = Base16_Encode(ssl->arrays->clientRandom, RAN_LEN,
@@ -357,12 +394,11 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
outSz = buffSz - idx;
if (outSz > 1) {
- log[idx++] = ' '; /* add space*/
+ log[idx++] = ' '; /* add space*/
outSz = buffSz - idx;
- if ((ret = Base16_Encode((byte*)secret, *secretSz,
- log + idx, &outSz)) == 0) {
- /* pass the log to the client callback*/
+ if ((ret = Base16_Encode((byte*)secret, secretSz,
+ log + idx, &outSz)) == 0) {
logCb(ssl, (char*)log);
ret = 0;
}
@@ -376,6 +412,48 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
return ret;
}
+ /* Label string for client random. */
+ #define SSC_CR "CLIENT_RANDOM"
+
+ /*
+ * This function builds up string for key-logging then call user's
+ * key-log-callback to pass the string for TLS1.2 and older.
+ * The user's key-logging callback has been set via
+ * wolfSSL_CTX_set_keylog_callback function. The logging string format is:
+ * "CLIENT_RANDOM "
+ * parameter
+ * - ssl: WOLFSSL object
+ * - secret: pointer to the buffer holding master-secret
+ * - secretSz: size of secret
+ * - ctx: not used
+ * returns 0 on success, negative value on failure.
+ */
+ static int SessionSecret_callback(WOLFSSL* ssl, void* secret,
+ int* secretSz, void* ctx)
+ {
+ int invalidCount;
+ int i;
+ (void)ctx;
+
+ if (secret == NULL || secretSz == NULL || *secretSz == 0)
+ return BAD_FUNC_ARG;
+
+ /* make sure the given master-secret has a meaningful value */
+ invalidCount = 0;
+ for (i = 0; i < *secretSz; i++) {
+ if (((byte*)secret)[i] == 0) {
+ invalidCount++;
+ }
+ }
+ if (invalidCount == *secretSz) {
+ WOLFSSL_MSG("master-secret is not valid");
+ return 0; /* ignore error */
+ }
+
+ return SessionSecret_callback_common(ssl, secret, *secretSz,
+ SSC_CR, sizeof(SSC_CR));
+ }
+
#if defined(WOLFSSL_TLS13)
/* Label string for client early traffic secret. */
@@ -411,27 +489,10 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
static int SessionSecret_callback_Tls13(WOLFSSL* ssl, int id,
const unsigned char* secret, int secretSz, void* ctx)
{
- wolfSSL_CTX_keylog_cb_func logCb = NULL;
const char* label;
int labelSz = 0;
- int buffSz = 0;
- byte* log = NULL;
- word32 outSz;
- int idx;
- int ret;
-
(void)ctx;
- if (ssl == NULL || secret == NULL || secretSz == 0)
- return BAD_FUNC_ARG;
- if (ssl->arrays == NULL)
- return BAD_FUNC_ARG;
-
- /* get the user-callback func from CTX*/
- logCb = ssl->ctx->keyLogCb;
- if (logCb == NULL)
- return 0;
-
switch (id) {
case CLIENT_EARLY_TRAFFIC_SECRET:
labelSz = sizeof(SSC_TLS13_CETS);
@@ -471,44 +532,8 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
default:
return BAD_FUNC_ARG;
}
- /* prepare a log string for passing user callback
- * " " */
- buffSz = labelSz + (RAN_LEN * 2) + 1 + secretSz * 2 + 1;
- log = XMALLOC(buffSz, ssl->heap, DYNAMIC_TYPE_SECRET);
- if (log == NULL)
- return MEMORY_E;
-#ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("SessionSecret log", log, buffSz);
-#endif
-
- XMEMSET(log, 0, buffSz);
- XMEMCPY(log, label, labelSz - 1); /* put label w/o terminator */
- log[labelSz - 1] = ' '; /* '\0' -> ' ' */
-
- idx = labelSz;
- outSz = buffSz - idx;
- if ((ret = Base16_Encode(ssl->arrays->clientRandom, RAN_LEN,
- log + idx, &outSz)) == 0) {
- idx += (outSz - 1); /* reduce terminator byte */
- outSz = buffSz - idx;
-
- if (outSz >1) {
- log[idx++] = ' '; /* add space*/
- outSz = buffSz - idx;
-
- if ((ret = Base16_Encode((byte*)secret, secretSz,
- log + idx, &outSz)) == 0) {
- logCb(ssl, (char*)log);
- ret = 0;
- }
- }
- else
- ret = MEMORY_E;
- }
- /* Zero out Base16 encoded secret and other data. */
- ForceZero(log, buffSz);
- XFREE(log, ssl->heap, DYNAMIC_TYPE_SECRET);
- return ret;
+ return SessionSecret_callback_common(ssl, secret, secretSz,
+ label, labelSz);
}
#endif /* WOLFSSL_TLS13*/
#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK*/
@@ -517,6 +542,22 @@ int IsTLS(const WOLFSSL* ssl)
{
if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
return 1;
+#ifdef WOLFSSL_DTLS
+ if (ssl->version.major == DTLS_MAJOR)
+ return 1;
+#endif
+
+ return 0;
+}
+
+int IsTLS_ex(const ProtocolVersion pv)
+{
+ if (pv.major == SSLv3_MAJOR && pv.minor >=TLSv1_MINOR)
+ return 1;
+#ifdef WOLFSSL_DTLS
+ if (pv.major == DTLS_MAJOR)
+ return 1;
+#endif
return 0;
}
@@ -549,24 +590,27 @@ int IsAtLeastTLSv1_3(const ProtocolVersion pv)
int IsEncryptionOn(const WOLFSSL* ssl, int isSend)
{
- #ifdef WOLFSSL_DTLS
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+#ifdef WOLFSSL_DTLS
/* For DTLS, epoch 0 is always not encrypted. */
if (ssl->options.dtls && !isSend) {
if (!IsAtLeastTLSv1_3(ssl->version) && ssl->keys.curEpoch == 0)
return 0;
-#ifdef WOLFSSL_DTLS13
+ #ifdef WOLFSSL_DTLS13
else if (IsAtLeastTLSv1_3(ssl->version)
&& w64IsZero(ssl->keys.curEpoch64))
return 0;
-#endif /* WOLFSSL_DTLS13 */
+ #endif /* WOLFSSL_DTLS13 */
}
- #endif /* WOLFSSL_DTLS */
- #ifdef WOLFSSL_QUIC
+#endif /* WOLFSSL_DTLS */
+#ifdef WOLFSSL_QUIC
if (WOLFSSL_IS_QUIC(ssl) && IsAtLeastTLSv1_3(ssl->version)) {
return 0;
}
- #endif
+#endif /* WOLFSSL_QUIC */
return ssl->keys.encryptionOn &&
(isSend ? ssl->encrypt.setup : ssl->decrypt.setup);
}
@@ -734,16 +778,16 @@ static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver,
ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
byte *pt = (byte*)ssl->encrypt.aes->reg;
- if ((idx + 2*AES_BLOCK_SIZE) > len) {
+ if ((idx + 2*WC_AES_BLOCK_SIZE) > len) {
WOLFSSL_MSG("Can not fit AES state into buffer");
return BUFFER_E;
}
- XMEMCPY(exp + idx, pt, AES_BLOCK_SIZE);
- idx += AES_BLOCK_SIZE;
+ XMEMCPY(exp + idx, pt, WC_AES_BLOCK_SIZE);
+ idx += WC_AES_BLOCK_SIZE;
pt = (byte*)ssl->decrypt.aes->reg;
- XMEMCPY(exp + idx, pt, AES_BLOCK_SIZE);
- idx += AES_BLOCK_SIZE;
+ XMEMCPY(exp + idx, pt, WC_AES_BLOCK_SIZE);
+ idx += WC_AES_BLOCK_SIZE;
}
WOLFSSL_LEAVE("ExportCipherSpecState", idx);
@@ -986,12 +1030,12 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len,
if (type == WOLFSSL_EXPORT_TLS &&
ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
byte *pt = (byte*)ssl->encrypt.aes->reg;
- XMEMCPY(pt, exp + idx, AES_BLOCK_SIZE);
- idx += AES_BLOCK_SIZE;
+ XMEMCPY(pt, exp + idx, WC_AES_BLOCK_SIZE);
+ idx += WC_AES_BLOCK_SIZE;
pt = (byte*)ssl->decrypt.aes->reg;
- XMEMCPY(pt, exp + idx, AES_BLOCK_SIZE);
- idx += AES_BLOCK_SIZE;
+ XMEMCPY(pt, exp + idx, WC_AES_BLOCK_SIZE);
+ idx += WC_AES_BLOCK_SIZE;
}
WOLFSSL_LEAVE("ImportCipherSpecState", idx);
@@ -1853,7 +1897,7 @@ int wolfSSL_session_import_internal(WOLFSSL* ssl, const unsigned char* buf,
optSz = DTLS_EXPORT_OPT_SZ_4;
}
else {
- optSz = TLS_EXPORT_OPT_SZ;
+ optSz = TLS_EXPORT_OPT_SZ_4;
}
break;
@@ -2046,9 +2090,9 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz,
/* possible AES state needed */
if (type == WOLFSSL_EXPORT_TLS) {
- *sz += AES_BLOCK_SIZE*2;
+ *sz += WC_AES_BLOCK_SIZE*2;
}
- ret = LENGTH_ONLY_E;
+ ret = WC_NO_ERR_TRACE(LENGTH_ONLY_E);
}
if (ret == 0) {
@@ -2108,7 +2152,7 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz,
}
}
- if (ret != 0 && ret != LENGTH_ONLY_E && buf != NULL) {
+ if (ret != 0 && ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E) && buf != NULL) {
/*in a fail case clear the buffer which could contain partial key info*/
XMEMSET(buf, 0, *sz);
}
@@ -2169,7 +2213,6 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side)
ssl->options.haveECC = 1; /* server turns on with ECC key cert */
}
#endif
-#ifdef HAVE_PQC
#ifdef HAVE_FALCON
if (ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.haveFalconSig = 1; /* always on client side */
@@ -2180,7 +2223,6 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side)
ssl->options.haveDilithiumSig = 1; /* always on client side */
}
#endif /* HAVE_DILITHIUM */
-#endif /* HAVE_PQC */
#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT)
if (ssl->options.side == WOLFSSL_CLIENT_END) {
@@ -2208,7 +2250,227 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side)
return InitSSL_Suites(ssl);
}
-#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE ||
+ * WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+/* Check the wolfssl method meets minimum requirements for
+ * the given security level.
+ *
+ * Returns 0 if method meets security level.
+ * Returns CRYPTO_POLICY_FORBIDDEN otherwise.
+ * */
+static int wolfSSL_crypto_policy_method_allowed(WOLFSSL_METHOD * method,
+ int level)
+{
+ if (level == 0) {
+ /* permissive, no restrictions. */
+ return 0;
+ }
+
+ #ifdef WOLFSSL_DTLS
+ if (method->version.major == DTLS_MAJOR) {
+ if (method->version.minor == DTLS_MINOR) {
+ /* sec level must be 1 or lower. */
+ if (level > 1) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+ }
+ else
+ #endif /* WOLFSSL_DTLS */
+ {
+ if (method->version.minor == SSLv3_MINOR) {
+ /* sec level must be 0. */
+ if (level > 0) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+ else if (method->version.minor == TLSv1_MINOR ||
+ method->version.minor == TLSv1_1_MINOR) {
+ /* sec level must be 1 or lower. */
+ if (level > 1) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+ }
+
+ /* nothing else to check, all other combinations ok. */
+
+ return 0;
+}
+
+/* Configure the CTX to conform to the security policy.
+ *
+ * Also, check the WOLFSSL_METHOD against the supplied security
+ * level.
+ *
+ * Returns CRYPTO_POLICY_FORBIDDEN if not allowed per policy.
+ * Returns BAD_FUNC_ARG on null args.
+ * Returns 0 if ok.
+ * */
+int wolfSSL_crypto_policy_init_ctx(WOLFSSL_CTX * ctx,
+ WOLFSSL_METHOD * method)
+{
+ byte minDowngrade = 0x00;
+ #ifdef WOLFSSL_DTLS
+ int dtls = 0;
+ #endif /* WOLFSSL_DTLS */
+ int level = 0;
+ #if !defined(NO_DH) || !defined(NO_RSA)
+ word16 minKeySz = 0; /* minimum DH or RSA key size */
+ #endif /* !NO_DH || !NO_RSA*/
+ #ifdef HAVE_ECC
+ short minEccKeySz = 0; /* minimum allowed ECC key size */
+ #endif /* HAVE_ECC */
+
+
+ if (ctx == NULL || method == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ #ifdef WOLFSSL_DTLS
+ dtls = (method->version.major == DTLS_MAJOR);
+ #endif /* WOLFSSL_DTLS */
+
+ /* get the crypto policy security level. */
+ level = wolfSSL_crypto_policy_get_level();
+
+ if (level < 0 || level > 5) {
+ WOLFSSL_MSG_EX("crypto_policy_init_ctx: invalid level: %d", level);
+ return BAD_FUNC_ARG;
+ }
+
+ /* Check requested method per security level. */
+ if (wolfSSL_crypto_policy_method_allowed(method, level) != 0) {
+ WOLFSSL_MSG_EX("crypto_policy_init_ctx: "
+ "method=%d, SECLEVEL=%d combination not allowed",
+ method->version.minor, level);
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+
+ /* Set appropriate min downgrade per security level. */
+ #ifdef WOLFSSL_DTLS
+ if (dtls) {
+ switch (level) {
+ case 1:
+ minDowngrade = DTLS_MINOR;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ minDowngrade = DTLSv1_2_MINOR;
+ break;
+ case 0:
+ default:
+ /* Permissive, no restrictions. Allow defaults. */
+ minDowngrade = WOLFSSL_MIN_DTLS_DOWNGRADE;
+ break;
+ }
+ }
+ else
+ #endif /* WOLFSSL_DTLS */
+ {
+ switch (level) {
+ case 1:
+ /* prohibit SSLv3 and lower. */
+ minDowngrade = TLSv1_MINOR;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ /* prohibit TLSv1_1 and lower. */
+ minDowngrade = TLSv1_2_MINOR;
+ break;
+ case 0:
+ default:
+ ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE;
+ break;
+ }
+ }
+
+ /* Set min RSA and DH key size. */
+ #if !defined(NO_DH) || !defined(NO_RSA)
+ switch (level) {
+ case 1:
+ minKeySz = 128; /* 1024 bits / 8 */
+ break;
+ case 2:
+ minKeySz = 256; /* 2048 bits / 8 */
+ break;
+ case 3:
+ minKeySz = 384; /* 3072 bits / 8 */
+ break;
+ case 4:
+ minKeySz = 960; /* 7680 bits / 8 */
+ break;
+ case 5:
+ minKeySz = 1920; /* 15360 bits / 8 */
+ break;
+ case 0:
+ default:
+ break;
+ }
+ #endif /* !NO_DH || !NO_RSA*/
+
+ /* Set min ECC key size. */
+ #ifdef HAVE_ECC
+ switch (level) {
+ case 1:
+ minEccKeySz = 20; /* 160 bits / 8 */
+ break;
+ case 2:
+ minEccKeySz = 28; /* 224 bits / 8 */
+ break;
+ case 3:
+ minEccKeySz = 32; /* 256 bits / 8 */
+ break;
+ case 4:
+ minEccKeySz = 48; /* 384 bits / 8 */
+ break;
+ case 5:
+ minEccKeySz = 64; /* 512 bits / 8 */
+ break;
+ default:
+ case 0:
+ break;
+ }
+ #endif /* HAVE_ECC */
+
+ /* Finally set the ctx values. */
+ ctx->minDowngrade = minDowngrade;
+ ctx->secLevel = level;
+ ctx->method = method;
+
+ #if !defined(NO_DH) || !defined(NO_RSA)
+ if (minKeySz > 0) {
+ #ifndef NO_DH
+ if (minKeySz > MAX_DHKEY_SZ) {
+ WOLFSSL_MSG_EX("crypto_policy_init_ctx: minKeySz=%d, "
+ "but MAX_DHKEY_SZ=%d",
+ minKeySz, MAX_DHKEY_SZ);
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ ctx->minDhKeySz = minKeySz;
+ ctx->maxDhKeySz = MAX_DHKEY_SZ;
+ #endif /* NO_DH */
+ #ifndef NO_RSA
+ ctx->minRsaKeySz = minKeySz;
+ #endif /* NO_RSA */
+ }
+ #endif /* !NO_DH || !NO_RSA*/
+
+ #ifdef HAVE_ECC
+ if (minEccKeySz > 0) {
+ ctx->minEccKeySz = minEccKeySz;
+ }
+ #endif /* HAVE_ECC */
+
+ return 0;
+}
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
/* Initialize SSL context, return 0 on success */
int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
@@ -2237,7 +2499,7 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE;
}
- wolfSSL_RefInit(&ctx->ref, &ret);
+ wolfSSL_RefWithMutexInit(&ctx->ref, &ret);
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
if (ret < 0) {
WOLFSSL_MSG("Mutex error on CTX init");
@@ -2251,6 +2513,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
@@ -2260,18 +2525,17 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
#ifndef NO_RSA
ctx->minRsaKeySz = MIN_RSAKEY_SZ;
#endif
+
#ifdef HAVE_ECC
ctx->minEccKeySz = MIN_ECCKEY_SZ;
ctx->eccTempKeySz = ECDHE_SIZE;
#endif
-#ifdef HAVE_PQC
#ifdef HAVE_FALCON
ctx->minFalconKeySz = MIN_FALCONKEY_SZ;
#endif /* HAVE_FALCON */
#ifdef HAVE_DILITHIUM
ctx->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ;
#endif /* HAVE_DILITHIUM */
-#endif /* HAVE_PQC */
ctx->verifyDepth = MAX_CHAIN_DEPTH;
#ifdef OPENSSL_EXTRA
ctx->cbioFlag = WOLFSSL_CBIO_NONE;
@@ -2335,7 +2599,6 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
wolfSSL_CTX_set_server_cert_type(ctx, NULL, 0); /* set to default */
#endif /* HAVE_RPK */
-#ifdef HAVE_PQC
#ifdef HAVE_FALCON
if (method->side == WOLFSSL_CLIENT_END)
ctx->haveFalconSig = 1; /* always on client side */
@@ -2346,7 +2609,6 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
ctx->haveDilithiumSig = 1; /* always on client side */
/* server can turn on by loading key */
#endif /* HAVE_DILITHIUM */
-#endif /* HAVE_PQC */
#ifdef HAVE_ECC
if (method->side == WOLFSSL_CLIENT_END) {
ctx->haveECDSAsig = 1; /* always on client side */
@@ -2398,22 +2660,27 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
return MEMORY_E;
}
XMEMSET(ctx->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
+
/* WOLFSSL_X509_LOOKUP */
- if ((ctx->x509_store.lookup.dirs =
- (WOLFSSL_BY_DIR*)XMALLOC(sizeof(WOLFSSL_BY_DIR),
- heap, DYNAMIC_TYPE_OPENSSL)) == NULL) {
- WOLFSSL_MSG("ctx-x509_store.lookup.dir memory allocation error");
- XFREE(ctx->param, heap, DYNAMIC_TYPE_OPENSSL);
- ctx->param = NULL;
+ if ((ctx->x509_store.lookup.dirs = (WOLFSSL_BY_DIR*)XMALLOC(
+ sizeof(WOLFSSL_BY_DIR),
+ heap, DYNAMIC_TYPE_OPENSSL)) == NULL) {
+ WOLFSSL_MSG("ctx->x509_store.lookup.dirs: allocation error");
return MEMORY_E;
}
XMEMSET(ctx->x509_store.lookup.dirs, 0, sizeof(WOLFSSL_BY_DIR));
+
+ /* param */
+ if ((ctx->x509_store.param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
+ sizeof(WOLFSSL_X509_VERIFY_PARAM),
+ heap, DYNAMIC_TYPE_OPENSSL)) == NULL) {
+ WOLFSSL_MSG("ctx->x509_store.param: allocation error");
+ return MEMORY_E;
+ }
+ XMEMSET(ctx->x509_store.param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
+
if (wc_InitMutex(&ctx->x509_store.lookup.dirs->lock) != 0) {
WOLFSSL_MSG("Bad mutex init");
- XFREE(ctx->param, heap, DYNAMIC_TYPE_OPENSSL);
- ctx->param = NULL;
- XFREE(ctx->x509_store.lookup.dirs, heap, DYNAMIC_TYPE_OPENSSL);
- ctx->x509_store.lookup.dirs = NULL;
WOLFSSL_ERROR_VERBOSE(BAD_MUTEX_E);
return BAD_MUTEX_E;
}
@@ -2435,7 +2702,7 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
-#ifndef WOLFSSL_NO_DEF_TICKET_ENC_CB
+#if !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && !defined(NO_TLS)
ret = TicketEncCbCtx_Init(ctx, &ctx->ticketKeyCtx);
if (ret != 0) return ret;
ctx->ticketEncCb = DefTicketEncCb;
@@ -2483,6 +2750,14 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
ctx->doAppleNativeCertValidationFlag = 0;
#endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ ret = wolfSSL_crypto_policy_init_ctx(ctx, method);
+ if (ret != 0) {
+ WOLFSSL_MSG_EX("crypto_policy_init_ctx returned %d", ret);
+ return ret;
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
return ret;
}
@@ -2501,7 +2776,7 @@ void wolfSSL_CRYPTO_cleanup_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data)
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
/* free all ech configs in the list */
-static void FreeEchConfigs(WOLFSSL_EchConfig* configs, void* heap)
+void FreeEchConfigs(WOLFSSL_EchConfig* configs, void* heap)
{
WOLFSSL_EchConfig* working_config = configs;
WOLFSSL_EchConfig* next_config;
@@ -2512,8 +2787,7 @@ static void FreeEchConfigs(WOLFSSL_EchConfig* configs, void* heap)
XFREE(working_config->cipherSuites, heap, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(working_config->publicName, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (working_config->raw != NULL)
- XFREE(working_config->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(working_config->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
if (working_config->receiverPrivkey != NULL) {
wc_HpkeFreeKey(NULL, working_config->kemId,
@@ -2527,7 +2801,7 @@ static void FreeEchConfigs(WOLFSSL_EchConfig* configs, void* heap)
(void)heap;
}
-#endif
+#endif /* WOLFSSL_TLS13 && HAVE_ECH */
/* In case contexts are held in array and don't want to free actual ctx. */
@@ -2557,13 +2831,13 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
wolfEventQueue_Free(&ctx->event_queue);
#endif /* HAVE_WOLF_EVENT */
+#ifndef NO_TLS /* its a static global see ssl.c "gNoTlsMethod" */
XFREE(ctx->method, heapAtCTXInit, DYNAMIC_TYPE_METHOD);
+#endif
ctx->method = NULL;
- if (ctx->suites) {
- XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES);
- ctx->suites = NULL;
- }
+ XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES);
+ ctx->suites = NULL;
#ifndef NO_DH
XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
@@ -2585,11 +2859,17 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
ForceZero(ctx->privateKey->buffer, ctx->privateKey->length);
}
FreeDer(&ctx->privateKey);
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ FreeDer(&ctx->privateKeyMask);
+#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ctx->altPrivateKey != NULL && ctx->altPrivateKey->buffer != NULL) {
ForceZero(ctx->altPrivateKey->buffer, ctx->altPrivateKey->length);
}
FreeDer(&ctx->altPrivateKey);
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ FreeDer(&ctx->altPrivateKeyMask);
+#endif
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifdef OPENSSL_ALL
wolfSSL_EVP_PKEY_free(ctx->privateKeyPKey);
@@ -2614,9 +2894,11 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
defined(WOLFSSL_WPAS_SMALL)
wolfSSL_X509_STORE_free(ctx->x509_store_pt);
#endif
- #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY)
+ #ifndef WOLFSSL_NO_CA_NAMES
wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL);
ctx->client_ca_names = NULL;
+ wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL);
+ ctx->ca_names = NULL;
#endif
#ifdef OPENSSL_EXTRA
if (ctx->x509Chain) {
@@ -2624,6 +2906,12 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
ctx->x509Chain = NULL;
}
#endif
+ #ifdef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION
+ if (ctx->testTrustedCAs != NULL) {
+ CFRelease(ctx->testTrustedCAs);
+ ctx->testTrustedCAs = NULL;
+ }
+ #endif /* WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION */
#endif /* !NO_CERTS */
#ifdef HAVE_TLS_EXTENSIONS
@@ -2656,9 +2944,12 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
XFREE((void*)ctx->alpn_cli_protos, ctx->heap, DYNAMIC_TYPE_OPENSSL);
ctx->alpn_cli_protos = NULL;
}
- if (ctx->param) {
- XFREE(ctx->param, heapAtCTXInit, DYNAMIC_TYPE_OPENSSL);
- ctx->param = NULL;
+ XFREE(ctx->param, heapAtCTXInit, DYNAMIC_TYPE_OPENSSL);
+ ctx->param = NULL;
+
+ if (ctx->x509_store.param) {
+ XFREE(ctx->x509_store.param, heapAtCTXInit, DYNAMIC_TYPE_OPENSSL);
+ ctx->x509_store.param = NULL;
}
if (ctx->x509_store.lookup.dirs) {
@@ -2699,21 +2990,6 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
(void)heapAtCTXInit;
}
-#ifdef WOLFSSL_STATIC_MEMORY
-static void SSL_CtxResourceFreeStaticMem(void* heap)
-{
- if (heap != NULL
- #ifdef WOLFSSL_HEAP_TEST
- /* avoid dereferencing a test value */
- && heap != (void*)WOLFSSL_HEAP_TEST
- #endif
- ) {
- WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap;
- WOLFSSL_HEAP* mem = hint->memory;
- wc_FreeMutex(&mem->memory_mutex);
- }
-}
-#endif /* WOLFSSL_STATIC_MEMORY */
void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
{
@@ -2727,17 +3003,14 @@ void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
#endif
/* decrement CTX reference count */
- wolfSSL_RefDec(&ctx->ref, &isZero, &ret);
+ wolfSSL_RefWithMutexDec(&ctx->ref, &isZero, &ret);
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
if (ret < 0) {
/* check error state, if mutex error code then mutex init failed but
* CTX was still malloc'd */
- if (ctx->err == CTX_INIT_MUTEX_E) {
+ if (ctx->err == WC_NO_ERR_TRACE(CTX_INIT_MUTEX_E)) {
SSL_CtxResourceFree(ctx);
XFREE(ctx, heap, DYNAMIC_TYPE_CTX);
- #ifdef WOLFSSL_STATIC_MEMORY
- SSL_CtxResourceFreeStaticMem(heap);
- #endif
}
return;
}
@@ -2747,17 +3020,23 @@ void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
if (isZero) {
WOLFSSL_MSG("CTX ref count down to 0, doing full free");
-
+#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && \
+ !defined(NO_SHA256) && !defined(WC_NO_RNG)
+ if (ctx->srp != NULL) {
+ XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
+ ctx->srp_password = NULL;
+ wc_SrpTerm(ctx->srp);
+ XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
+ ctx->srp = NULL;
+ }
+#endif
SSL_CtxResourceFree(ctx);
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) && \
- !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB)
+ !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && !defined(NO_TLS)
TicketEncCbCtx_Free(&ctx->ticketKeyCtx);
#endif
wolfSSL_RefFree(&ctx->ref);
XFREE(ctx, heap, DYNAMIC_TYPE_CTX);
- #ifdef WOLFSSL_STATIC_MEMORY
- SSL_CtxResourceFreeStaticMem(heap);
- #endif
}
else {
WOLFSSL_MSG("CTX ref count not 0 yet, no free");
@@ -2811,100 +3090,92 @@ void InitCiphers(WOLFSSL* ssl)
}
-
-/* Free ciphers */
-void FreeCiphers(WOLFSSL* ssl)
+static void FreeCiphersSide(Ciphers *cipher, void* heap)
{
- (void)ssl;
#ifdef BUILD_ARC4
- wc_Arc4Free(ssl->encrypt.arc4);
- wc_Arc4Free(ssl->decrypt.arc4);
- XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ wc_Arc4Free(cipher->arc4);
+ XFREE(cipher->arc4, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->arc4 = NULL;
#endif
#ifdef BUILD_DES3
- wc_Des3Free(ssl->encrypt.des3);
- wc_Des3Free(ssl->decrypt.des3);
- XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ wc_Des3Free(cipher->des3);
+ XFREE(cipher->des3, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->des3 = NULL;
#endif
#if defined(BUILD_AES) || defined(BUILD_AESGCM) || defined(HAVE_ARIA)
- /* See: InitKeys() in keys.c on addition of BUILD_AESGCM check (enc->aes, dec->aes) */
- wc_AesFree(ssl->encrypt.aes);
- wc_AesFree(ssl->decrypt.aes);
- XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ /* See: InitKeys() in keys.c on addition of BUILD_AESGCM check (enc->aes,
+ * dec->aes) */
+ wc_AesFree(cipher->aes);
+ XFREE(cipher->aes, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->aes = NULL;
#endif
#if defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)
- wc_Sm4Free(ssl->encrypt.sm4);
- wc_Sm4Free(ssl->decrypt.sm4);
- XFREE(ssl->encrypt.sm4, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->decrypt.sm4, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ wc_Sm4Free(cipher->sm4);
+ XFREE(cipher->sm4, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->sm4 = NULL;
#endif
#if (defined(BUILD_AESGCM) || defined(BUILD_AESCCM) || defined(HAVE_ARIA)) && \
!defined(WOLFSSL_NO_TLS12)
- XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ XFREE(cipher->additional, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->additional = NULL;
#endif
#ifdef CIPHER_NONCE
- XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ XFREE(cipher->nonce, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->nonce = NULL;
#endif
#ifdef HAVE_ARIA
- wc_AriaFreeCrypt(ssl->encrypt.aria);
- wc_AriaFreeCrypt(ssl->decrypt.aria);
- XFREE(ssl->encrypt.aria, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->decrypt.aria, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ wc_AriaFreeCrypt(cipher->aria);
+ XFREE(cipher->aria, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->aria = NULL;
#endif
#ifdef HAVE_CAMELLIA
- XFREE(ssl->encrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ XFREE(cipher->cam, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->cam = NULL;
#endif
#ifdef HAVE_CHACHA
- if (ssl->encrypt.chacha)
- ForceZero(ssl->encrypt.chacha, sizeof(ChaCha));
- if (ssl->decrypt.chacha)
- ForceZero(ssl->decrypt.chacha, sizeof(ChaCha));
- XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ if (cipher->chacha)
+ ForceZero(cipher->chacha, sizeof(ChaCha));
+ XFREE(cipher->chacha, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->chacha = NULL;
#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER)
+ wc_HmacFree(cipher->hmac);
+ XFREE(cipher->hmac, heap, DYNAMIC_TYPE_CIPHER);
+ cipher->hmac = NULL;
+#endif
+}
+
+/* Free ciphers */
+void FreeCiphers(WOLFSSL* ssl)
+{
+ FreeCiphersSide(&ssl->encrypt, ssl->heap);
+ FreeCiphersSide(&ssl->decrypt, ssl->heap);
+
#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH)
if (ssl->auth.poly1305)
ForceZero(ssl->auth.poly1305, sizeof(Poly1305));
XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER);
-#endif
-#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER)
- wc_HmacFree(ssl->encrypt.hmac);
- wc_HmacFree(ssl->decrypt.hmac);
- XFREE(ssl->encrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ ssl->auth.poly1305 = NULL;
#endif
#ifdef WOLFSSL_DTLS13
#ifdef BUILD_AES
- if (ssl->dtlsRecordNumberEncrypt.aes != NULL) {
- wc_AesFree(ssl->dtlsRecordNumberEncrypt.aes);
- XFREE(ssl->dtlsRecordNumberEncrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
- ssl->dtlsRecordNumberEncrypt.aes = NULL;
- }
- if (ssl->dtlsRecordNumberDecrypt.aes != NULL) {
- wc_AesFree(ssl->dtlsRecordNumberDecrypt.aes);
- XFREE(ssl->dtlsRecordNumberDecrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
- ssl->dtlsRecordNumberDecrypt.aes = NULL;
- }
+ wc_AesFree(ssl->dtlsRecordNumberEncrypt.aes);
+ wc_AesFree(ssl->dtlsRecordNumberDecrypt.aes);
+ XFREE(ssl->dtlsRecordNumberEncrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ XFREE(ssl->dtlsRecordNumberDecrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ ssl->dtlsRecordNumberEncrypt.aes = NULL;
+ ssl->dtlsRecordNumberDecrypt.aes = NULL;
#endif /* BUILD_AES */
#ifdef HAVE_CHACHA
- XFREE(ssl->dtlsRecordNumberEncrypt.chacha,
- ssl->heap, DYNAMIC_TYPE_CIPHER);
- XFREE(ssl->dtlsRecordNumberDecrypt.chacha,
- ssl->heap, DYNAMIC_TYPE_CIPHER);
+ XFREE(ssl->dtlsRecordNumberEncrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
+ XFREE(ssl->dtlsRecordNumberDecrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
ssl->dtlsRecordNumberEncrypt.chacha = NULL;
ssl->dtlsRecordNumberDecrypt.chacha = NULL;
#endif /* HAVE_CHACHA */
#endif /* WOLFSSL_DTLS13 */
}
-
void InitCipherSpecs(CipherSpecs* cs)
{
XMEMSET(cs, 0, sizeof(CipherSpecs));
@@ -2996,7 +3267,6 @@ static WC_INLINE void AddSuiteHashSigAlgo(byte* hashSigAlgo, byte macAlgo,
}
else
#endif
- #ifdef HAVE_PQC
#ifdef HAVE_FALCON
if (sigAlgo == falcon_level1_sa_algo) {
ADD_HASH_SIG_ALGO(hashSigAlgo, inOutIdx,
@@ -3026,7 +3296,6 @@ static WC_INLINE void AddSuiteHashSigAlgo(byte* hashSigAlgo, byte macAlgo,
}
else
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
#ifdef WC_RSA_PSS
if (sigAlgo == rsa_pss_sa_algo) {
/* RSA PSS is sig then mac */
@@ -3045,7 +3314,7 @@ static WC_INLINE void AddSuiteHashSigAlgo(byte* hashSigAlgo, byte macAlgo,
}
}
-void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int haveSig, int tls1_2,
+void InitSuitesHashSigAlgo(byte* hashSigAlgo, int haveSig, int tls1_2,
int keySz, word16* len)
{
word16 idx = 0;
@@ -3087,7 +3356,6 @@ void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int haveSig, int tls1_2,
&idx);
}
#endif
-#if defined(HAVE_PQC)
#ifdef HAVE_FALCON
if (haveSig & SIG_FALCON) {
AddSuiteHashSigAlgo(hashSigAlgo, no_mac, falcon_level1_sa_algo, keySz,
@@ -3106,7 +3374,6 @@ void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int haveSig, int tls1_2,
keySz, &idx);
}
#endif /* HAVE_DILITHIUM */
-#endif /* HAVE_PQC */
if (haveSig & SIG_RSA) {
#ifdef WC_RSA_PSS
if (tls1_2) {
@@ -3152,30 +3419,6 @@ void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int haveSig, int tls1_2,
*len = idx;
}
-void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig,
- int haveFalconSig, int haveDilithiumSig, int haveAnon, int tls1_2,
- int keySz)
-{
- InitSuitesHashSigAlgo_ex(suites->hashSigAlgo, haveECDSAsig, haveRSAsig,
- haveFalconSig, haveDilithiumSig, haveAnon, tls1_2, keySz,
- &suites->hashSigAlgoSz);
-}
-
-void InitSuitesHashSigAlgo_ex(byte* hashSigAlgo, int haveECDSAsig,
- int haveRSAsig, int haveFalconSig, int haveDilithiumSig, int haveAnon,
- int tls1_2, int keySz, word16* len)
-{
- int have = 0;
-
- if (haveECDSAsig) have |= SIG_ECDSA;
- if (haveRSAsig) have |= SIG_RSA;
- if (haveFalconSig) have |= SIG_FALCON;
- if (haveDilithiumSig) have |= SIG_DILITHIUM;
- if (haveAnon) have |= SIG_ANON;
-
- InitSuitesHashSigAlgo_ex2(hashSigAlgo, have, tls1_2, keySz, len);
-}
-
int AllocateCtxSuites(WOLFSSL_CTX* ctx)
{
if (ctx->suites == NULL) {
@@ -3211,8 +3454,8 @@ int AllocateSuites(WOLFSSL* ssl)
void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
word16 havePSK, word16 haveDH, word16 haveECDSAsig,
word16 haveECC, word16 haveStaticRSA, word16 haveStaticECC,
- word16 haveFalconSig, word16 haveDilithiumSig, word16 haveAnon,
- word16 haveNull, int side)
+ word16 haveAnon, word16 haveNull, word16 haveAES128,
+ word16 haveSHA1, word16 haveRC4, int side)
{
word16 idx = 0;
int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR;
@@ -3224,11 +3467,15 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
int haveRSAsig = 1;
#ifdef WOLFSSL_DTLS
- /* If DTLS v1.2 or later than set tls1_2 flag */
- if (pv.major == DTLS_MAJOR && pv.minor <= DTLSv1_2_MINOR) {
- tls1_2 = 1;
+ if (pv.major == DTLS_MAJOR) {
+ dtls = 1;
+ tls = 1;
+ /* May be dead assignments dependent upon configuration */
+ (void) dtls;
+ (void) tls;
+ tls1_2 = pv.minor <= DTLSv1_2_MINOR;
}
-#endif
+#endif /* WOLFSSL_DTLS */
(void)tls; /* shut up compiler */
(void)tls1_2;
@@ -3238,13 +3485,15 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
(void)haveStaticRSA;
(void)haveStaticECC;
(void)haveECC;
+ (void)haveECDSAsig;
(void)side;
(void)haveRSA; /* some builds won't read */
(void)haveRSAsig; /* non ecc builds won't read */
(void)haveAnon; /* anon ciphers optional */
(void)haveNull;
- (void)haveFalconSig;
- (void)haveDilithiumSig;
+ (void)haveAES128;
+ (void)haveSHA1;
+ (void)haveRC4;
if (suites == NULL) {
WOLFSSL_MSG("InitSuites pointer error");
@@ -3255,17 +3504,17 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
return; /* trust user settings, don't override */
#ifdef WOLFSSL_TLS13
-#ifdef BUILD_TLS_AES_128_GCM_SHA256
+#ifdef BUILD_TLS_AES_256_GCM_SHA384
if (tls1_3) {
suites->suites[idx++] = TLS13_BYTE;
- suites->suites[idx++] = TLS_AES_128_GCM_SHA256;
+ suites->suites[idx++] = TLS_AES_256_GCM_SHA384;
}
#endif
-#ifdef BUILD_TLS_AES_256_GCM_SHA384
- if (tls1_3) {
+#ifdef BUILD_TLS_AES_128_GCM_SHA256
+ if (tls1_3 && haveAES128) {
suites->suites[idx++] = TLS13_BYTE;
- suites->suites[idx++] = TLS_AES_256_GCM_SHA384;
+ suites->suites[idx++] = TLS_AES_128_GCM_SHA256;
}
#endif
@@ -3277,14 +3526,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_AES_128_CCM_SHA256
- if (tls1_3) {
+ if (tls1_3 && haveAES128) {
suites->suites[idx++] = TLS13_BYTE;
suites->suites[idx++] = TLS_AES_128_CCM_SHA256;
}
#endif
#ifdef BUILD_TLS_AES_128_CCM_8_SHA256
- if (tls1_3) {
+ if (tls1_3 && haveAES128) {
suites->suites[idx++] = TLS13_BYTE;
suites->suites[idx++] = TLS_AES_128_CCM_8_SHA256;
}
@@ -3296,6 +3545,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = TLS_SM4_GCM_SM3;
}
#endif
+
#ifdef BUILD_TLS_SM4_CCM_SM3
if (tls1_3) {
suites->suites[idx++] = CIPHER_BYTE;
@@ -3336,17 +3586,6 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
haveRSAsig = 0; /* can't have RSA sig if don't have RSA */
#endif
-#ifdef WOLFSSL_DTLS
- if (pv.major == DTLS_MAJOR) {
- dtls = 1;
- tls = 1;
- /* May be dead assignments dependent upon configuration */
- (void) dtls;
- (void) tls;
- tls1_2 = pv.minor <= DTLSv1_2_MINOR;
- }
-#endif
-
#ifdef HAVE_RENEGOTIATION_INDICATION
if (side == WOLFSSL_CLIENT_END) {
suites->suites[idx++] = CIPHER_BYTE;
@@ -3362,7 +3601,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- if (tls1_2 && haveECC) {
+ if (tls1_2 && haveECC && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
}
@@ -3382,9 +3621,10 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
#ifdef OPENSSL_EXTRA
- if ((tls1_2 && haveRSA) || (tls1_2 && haveECDSAsig)) {
+ if ((tls1_2 && haveRSA && haveAES128) ||
+ (tls1_2 && haveECDSAsig && haveAES128)) {
#else
- if (tls1_2 && haveRSA) {
+ if (tls1_2 && haveRSA && haveAES128) {
#endif
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
@@ -3399,7 +3639,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- if (tls1_2 && haveDH && haveRSA) {
+ if (tls1_2 && haveDH && haveRSA && haveAES128) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
}
@@ -3413,7 +3653,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256
- if (tls1_2 && haveRSA && haveStaticRSA) {
+ if (tls1_2 && haveRSA && haveStaticRSA && haveAES128) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256;
}
@@ -3427,7 +3667,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
- if (tls1_2 && haveECC && haveStaticECC) {
+ if (tls1_2 && haveECC && haveStaticECC && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
}
@@ -3441,7 +3681,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
- if (tls1_2 && haveRSAsig && haveStaticECC) {
+ if (tls1_2 && haveRSAsig && haveStaticECC && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
}
@@ -3455,7 +3695,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256
- if (tls1_2 && haveECC) {
+ if (tls1_2 && haveECC && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256;
}
@@ -3469,7 +3709,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
- if (tls1_2 && haveDH && haveAnon) {
+ if (tls1_2 && haveDH && haveAnon && haveAES128 && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
}
@@ -3483,7 +3723,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
- if (tls1_2 && haveDH && havePSK) {
+ if (tls1_2 && haveDH && havePSK && haveAES128) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
}
@@ -3497,7 +3737,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256
- if (tls1_2 && havePSK) {
+ if (tls1_2 && havePSK && haveAES128) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_GCM_SHA256;
}
@@ -3531,18 +3771,19 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
/* Place as higher priority for MYSQL */
#if defined(WOLFSSL_MYSQL_COMPATIBLE)
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- if (tls && haveDH && haveRSA) {
+ if (tls && haveDH && haveRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
}
#endif
-#endif
+#endif /* WOLFSSL_MYSQL_COMPATIBLE */
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
#ifdef OPENSSL_EXTRA
- if ((tls1_2 && haveRSA) || (tls1_2 && haveECDSAsig)) {
+ if ((tls1_2 && haveRSA && haveAES128) ||
+ (tls1_2 && haveECDSAsig && haveAES128)) {
#else
- if (tls1_2 && haveRSA) {
+ if (tls1_2 && haveRSA && haveAES128) {
#endif
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
@@ -3550,21 +3791,21 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveECC) {
+ if (tls1_2 && haveECC && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveRSAsig && haveStaticECC) {
+ if (tls1_2 && haveRSAsig && haveStaticECC && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
- if (tls1_2 && haveECC && haveStaticECC) {
+ if (tls1_2 && haveECC && haveStaticECC && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
}
@@ -3603,56 +3844,56 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- if (tls && haveECC) {
+ if (tls && haveECC && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
- if (tls && haveECC && haveStaticECC) {
+ if (tls && haveECC && haveStaticECC && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- if (tls && haveECC) {
+ if (tls && haveECC && haveAES128 && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
- if (tls && haveECC && haveStaticECC) {
+ if (tls && haveECC && haveStaticECC && haveAES128 && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- if (!dtls && tls && haveECC) {
+ if (!dtls && tls && haveECC && haveSHA1 && haveRC4) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
- if (!dtls && tls && haveECC && haveStaticECC) {
+ if (!dtls && tls && haveECC && haveStaticECC && haveSHA1 && haveRC4) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- if (tls && haveECC) {
+ if (tls && haveECC && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
- if (tls && haveECC && haveStaticECC) {
+ if (tls && haveECC && haveStaticECC && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
}
@@ -3660,9 +3901,9 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
#ifdef OPENSSL_EXTRA
- if ((tls && haveRSA) || (tls && haveECDSAsig)) {
+ if ((tls && haveRSA && haveSHA1) || (tls && haveECDSAsig && haveSHA1)) {
#else
- if (tls && haveRSA) {
+ if (tls && haveRSA && haveSHA1) {
#endif
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
@@ -3670,7 +3911,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
- if (tls && haveRSAsig && haveStaticECC) {
+ if (tls && haveRSAsig && haveStaticECC && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
}
@@ -3678,9 +3919,10 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
#ifdef OPENSSL_EXTRA
- if ((tls && haveRSA) || (tls && haveECDSAsig)) {
+ if ((tls && haveRSA && haveAES128 && haveSHA1) ||
+ (tls && haveECDSAsig && haveAES128 && haveSHA1)) {
#else
- if (tls && haveRSA) {
+ if (tls && haveRSA && haveAES128 && haveSHA1) {
#endif
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
@@ -3688,21 +3930,21 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
- if (tls && haveRSAsig && haveStaticECC) {
+ if (tls && haveRSAsig && haveStaticECC && haveAES128 && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA
- if (!dtls && tls && haveRSA) {
+ if (!dtls && tls && haveRSA && haveSHA1 && haveRC4) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA
- if (!dtls && tls && haveRSAsig && haveStaticECC) {
+ if (!dtls && tls && haveRSAsig && haveStaticECC && haveSHA1 && haveRC4) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA;
}
@@ -3710,9 +3952,9 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
#ifdef OPENSSL_EXTRA
- if ((tls && haveRSA) || (tls && haveECDSAsig)) {
+ if ((tls && haveRSA && haveSHA1) || (tls && haveECDSAsig && haveSHA1)) {
#else
- if (tls && haveRSA) {
+ if (tls && haveRSA && haveSHA1) {
#endif
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
@@ -3720,21 +3962,21 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
- if (tls && haveRSAsig && haveStaticECC) {
+ if (tls && haveRSAsig && haveStaticECC && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM
- if (tls1_2 && haveECC) {
+ if (tls1_2 && haveECC && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
- if (tls1_2 && haveECC) {
+ if (tls1_2 && haveECC && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
}
@@ -3748,7 +3990,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8
- if (tls1_2 && haveRSA && haveStaticRSA) {
+ if (tls1_2 && haveRSA && haveStaticRSA && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CCM_8;
}
@@ -3771,39 +4013,39 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
}
-#endif
+#endif /* BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
- if (tls1_2 && haveDH && haveRSA)
+ if (tls1_2 && haveDH && haveRSA && haveAES128)
#else
- if (tls && haveDH && haveRSA)
+ if (tls && haveDH && haveRSA && haveAES128)
#endif
{
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
}
-#endif
+#endif /* BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */
/* Place as higher priority for MYSQL testing */
#if !defined(WOLFSSL_MYSQL_COMPATIBLE)
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- if (tls && haveDH && haveRSA) {
+ if (tls && haveDH && haveRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
}
#endif
-#endif
+#endif /* !WOLFSSL_MYSQL_COMPATIBLE */
#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- if (tls && haveDH && haveRSA) {
+ if (tls && haveDH && haveRSA && haveAES128 && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
- if (tls && haveDH && haveRSA) {
+ if (tls && haveDH && haveRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
}
@@ -3823,9 +4065,9 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
- if (tls1_2 && haveRSA && haveStaticRSA)
+ if (tls1_2 && haveRSA && haveStaticRSA && haveAES128)
#else
- if (tls && haveRSA && haveStaticRSA)
+ if (tls && haveRSA && haveStaticRSA && haveAES128)
#endif
{
suites->suites[idx++] = CIPHER_BYTE;
@@ -3834,14 +4076,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
- if (tls && haveRSA && haveStaticRSA) {
+ if (tls && haveRSA && haveStaticRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
- if (tls && haveRSA && haveStaticRSA) {
+ if (tls && haveRSA && haveStaticRSA && haveAES128 && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
}
@@ -3875,10 +4117,10 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
}
-#endif
+#endif /* BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 */
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA
- if (tls && haveECC && haveNull) {
+ if (tls && haveECC && haveNull && haveSHA1) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_NULL_SHA;
}
@@ -3892,7 +4134,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
- if (tls && haveRSA && haveNull && haveStaticRSA) {
+ if (tls && haveRSA && haveNull && haveStaticRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA;
}
@@ -3908,10 +4150,10 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256;
}
-#endif
+#endif /* BUILD_TLS_RSA_WITH_NULL_SHA256 */
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
- if (tls && havePSK) {
+ if (tls && havePSK && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
}
@@ -3927,7 +4169,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
}
-#endif
+#endif /* BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 */
#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -3939,25 +4181,25 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA384;
}
-#endif
+#endif /* BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 */
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
- if (tls1_2 && haveDH && havePSK)
+ if (tls1_2 && haveDH && havePSK && haveAES128)
#else
- if (tls && haveDH && havePSK)
+ if (tls && haveDH && havePSK && haveAES128)
#endif
{
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
}
-#endif
+#endif /* BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 */
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
- if (tls1_2 && havePSK)
+ if (tls1_2 && havePSK && haveAES128)
#else
- if (tls1 && havePSK)
+ if (tls1 && havePSK && haveAES128)
#endif
{
suites->suites[idx++] = CIPHER_BYTE;
@@ -3966,14 +4208,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
- if (tls && havePSK) {
+ if (tls && havePSK && haveAES128 && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM
- if (tls && haveDH && havePSK) {
+ if (tls && haveDH && havePSK && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CCM;
}
@@ -3996,7 +4238,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_CHACHA20_POLY1305_SHA256;
}
-#endif
+#endif /* BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 */
#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -4008,7 +4250,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
}
-#endif
+#endif /* BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 */
#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -4020,34 +4262,34 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256;
}
-#endif
+#endif /* BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 */
#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
- if (tls1_2 && havePSK)
+ if (tls1_2 && havePSK && haveAES128)
#else
- if (tls && havePSK)
+ if (tls && havePSK && haveAES128)
#endif
{
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
}
-#endif
+#endif /* BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 */
#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
- if (tls1_2 && havePSK)
+ if (tls1_2 && havePSK && haveAES128)
#else
- if (tls && havePSK)
+ if (tls && havePSK && haveAES128)
#endif
{
suites->suites[idx++] = ECDHE_PSK_BYTE;
suites->suites[idx++] = TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256;
}
-#endif
+#endif /* BUILD_TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 */
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM
- if (tls && havePSK) {
+ if (tls && havePSK && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM;
}
@@ -4061,7 +4303,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8
- if (tls && havePSK) {
+ if (tls && havePSK && haveAES128) {
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM_8;
}
@@ -4084,7 +4326,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384;
}
-#endif
+#endif /* BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 */
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -4096,7 +4338,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA384;
}
-#endif
+#endif /* BUILD_TLS_PSK_WITH_NULL_SHA384 */
#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -4108,7 +4350,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = ECC_BYTE;
suites->suites[idx++] = TLS_ECDHE_PSK_WITH_NULL_SHA256;
}
-#endif
+#endif /* BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 */
#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -4120,7 +4362,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256;
}
-#endif
+#endif /* BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 */
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -4132,7 +4374,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256;
}
-#endif
+#endif /* BUILD_TLS_PSK_WITH_NULL_SHA256 */
#ifdef BUILD_TLS_PSK_WITH_NULL_SHA
if (tls && havePSK && haveNull) {
@@ -4142,49 +4384,49 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
- if (!dtls && haveRSA && haveStaticRSA) {
+ if (!dtls && haveRSA && haveStaticRSA && haveSHA1 && haveRC4) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
- if (!dtls && haveRSA && haveStaticRSA) {
+ if (!dtls && haveRSA && haveStaticRSA && haveRC4) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
}
#endif
#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
- if (haveRSA && haveStaticRSA) {
+ if (haveRSA && haveStaticRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
- if (tls && haveRSA && haveStaticRSA) {
+ if (tls && haveRSA && haveStaticRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
- if (tls && haveDH && haveRSA && haveStaticRSA) {
+ if (tls && haveDH && haveRSA && haveStaticRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
- if (tls && haveRSA && haveStaticRSA) {
+ if (tls && haveRSA && haveStaticRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
- if (tls && haveDH && haveRSA && haveStaticRSA) {
+ if (tls && haveDH && haveRSA && haveStaticRSA && haveSHA1) {
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA;
}
@@ -4200,7 +4442,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256;
}
-#endif
+#endif /* BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 */
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -4212,7 +4454,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256;
}
-#endif
+#endif /* BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 */
#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -4224,7 +4466,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256;
}
-#endif
+#endif /* BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 */
#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
#ifndef WOLFSSL_OLDTLS_SHA2_CIPHERSUITES
@@ -4236,7 +4478,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = CIPHER_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256;
}
-#endif
+#endif /* BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 */
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
if (tls && haveECC) {
@@ -4244,12 +4486,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3;
}
#endif
+
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3
if (tls && haveECC) {
suites->suites[idx++] = SM_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3;
}
#endif
+
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CCM_SM3
if (tls && haveECC) {
suites->suites[idx++] = SM_BYTE;
@@ -4262,18 +4506,25 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
suites->suiteSz = idx;
if (suites->hashSigAlgoSz == 0) {
- int haveSig = 0;
- haveSig |= (haveRSAsig | haveRSA) ? SIG_RSA : 0;
- haveSig |= (haveECDSAsig | haveECC) ? SIG_ECDSA : 0;
- #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
- haveSig |= (haveECDSAsig | haveECC) ? SIG_SM2 : 0;
- #endif
- haveSig |= haveFalconSig ? SIG_FALCON : 0;
- haveSig |= haveDilithiumSig ? SIG_DILITHIUM : 0;
- haveSig &= ~SIG_ANON;
- InitSuitesHashSigAlgo_ex2(suites->hashSigAlgo, haveSig, tls1_2, keySz,
+ InitSuitesHashSigAlgo(suites->hashSigAlgo, SIG_ALL, tls1_2, keySz,
&suites->hashSigAlgoSz);
}
+
+ /* Moved to the end as we set some of the vars but never use them */
+ (void)tls; /* shut up compiler */
+ (void)tls1_2;
+ (void)dtls;
+ (void)haveDH;
+ (void)havePSK;
+ (void)haveStaticRSA;
+ (void)haveStaticECC;
+ (void)haveECC;
+ (void)haveECDSAsig;
+ (void)side;
+ (void)haveRSA; /* some builds won't read */
+ (void)haveRSAsig; /* non ecc builds won't read */
+ (void)haveAnon; /* anon ciphers optional */
+ (void)haveNull;
}
#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) || \
@@ -4331,42 +4582,45 @@ void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
}
break;
#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
+ case FALCON_SA_MAJOR:
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;
*hashAlgo = sha512_mac;
}
+ break;
#endif /* HAVE_FALCON */
#ifdef HAVE_DILITHIUM
+ case DILITHIUM_SA_MAJOR:
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;
*hashAlgo = sha512_mac;
}
- #endif /* HAVE_DILITHIUM */
break;
-#endif
+ #endif /* HAVE_DILITHIUM */
default:
*hashAlgo = input[0];
*hsType = input[1];
break;
}
}
-#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */
+#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS ||
+ * ( !NO_WOLFSSL_CLIENT && (!NO_DH || HAVE_ECC) ) */
#ifndef WOLFSSL_NO_TLS12
#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
@@ -4510,23 +4764,17 @@ void FreeX509(WOLFSSL_X509* x509)
x509->authKeyId = NULL;
XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
x509->subjKeyId = NULL;
- if (x509->authInfo != NULL) {
- XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
- x509->authInfo = NULL;
- }
- if (x509->rawCRLInfo != NULL) {
- XFREE(x509->rawCRLInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
- x509->rawCRLInfo = NULL;
- }
- if (x509->CRLInfo != NULL) {
- XFREE(x509->CRLInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
- x509->CRLInfo = NULL;
- }
+ wolfSSL_ASN1_STRING_free(x509->subjKeyIdStr);
+ x509->subjKeyIdStr = NULL;
+ XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ x509->authInfo = NULL;
+ XFREE(x509->rawCRLInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ x509->rawCRLInfo = NULL;
+ XFREE(x509->CRLInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ x509->CRLInfo = NULL;
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
defined(WOLFSSL_QT)
- if (x509->authInfoCaIssuer != NULL) {
- XFREE(x509->authInfoCaIssuer, x509->heap, DYNAMIC_TYPE_X509_EXT);
- }
+ XFREE(x509->authInfoCaIssuer, x509->heap, DYNAMIC_TYPE_X509_EXT);
if (x509->ext_sk != NULL) {
wolfSSL_sk_X509_EXTENSION_pop_free(x509->ext_sk, NULL);
}
@@ -4581,13 +4829,18 @@ void FreeX509(WOLFSSL_X509* x509)
x509->altNames = NULL;
}
-#ifdef WOLFSSL_DUAL_ALG_CERTS
+ #ifdef WOLFSSL_DUAL_ALG_CERTS
XFREE(x509->sapkiDer, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ x509->sapkiDer = NULL;
XFREE(x509->altSigAlgDer, x509->heap, DYNAMIC_TYPE_X509_EXT);
- XFREE(x509->altSigValDer, x509->heap, DYNAMIC_TYPE_X509_EXT);
-#endif /* WOLFSSL_DUAL_ALG_CERTS */
+ x509->altSigAlgDer = NULL;
+ if (x509->altSigValDer) {
+ XFREE(x509->altSigValDer, x509->heap, DYNAMIC_TYPE_X509_EXT);
+ x509->altSigValDer= NULL;
+ }
+ #endif /* WOLFSSL_DUAL_ALG_CERTS */
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
+ #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA)
wolfSSL_RefFree(&x509->ref);
#endif
}
@@ -4652,7 +4905,8 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
}
#endif
-#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+#if !defined(NO_TLS) && !defined(WOLFSSL_NO_TLS12) && \
+ !defined(WOLFSSL_NO_CLIENT_AUTH)
static void SetDigest(WOLFSSL* ssl, int hashAlgo)
{
switch (hashAlgo) {
@@ -4700,8 +4954,7 @@ static void SetDigest(WOLFSSL* ssl, int hashAlgo)
#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */
#endif /* !NO_CERTS */
-#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
-static word32 MacSize(const WOLFSSL* ssl)
+word32 MacSize(const WOLFSSL* ssl)
{
#ifdef HAVE_TRUNCATED_HMAC
word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
@@ -4712,10 +4965,9 @@ static word32 MacSize(const WOLFSSL* ssl)
return digestSz;
}
-#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
#ifndef NO_RSA
-#if !defined(WOLFSSL_NO_TLS12) || \
+#if (!defined(NO_TLS) && !defined(WOLFSSL_NO_TLS12)) || \
(defined(WC_RSA_PSS) && defined(HAVE_PK_CALLBACKS))
#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)
static int TypeHash(int hashAlgo)
@@ -4783,7 +5035,8 @@ int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf)
}
#endif
-#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+#if (!defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)) && \
+ (!defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY))
int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key,
DerBuffer* keyBufInfo)
@@ -4852,14 +5105,14 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (key && ret == WC_PENDING_E) {
+ if (key && ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
/* For positive response return in outSz */
if (ret > 0) {
- *outSz = ret;
+ *outSz = (word32)ret;
ret = 0;
}
@@ -4872,7 +5125,7 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
int hashAlgo, RsaKey* key, buffer* keyBufInfo)
{
- int ret = SIG_VERIFY_E;
+ int ret = WC_NO_ERR_TRACE(SIG_VERIFY_E);
#ifdef HAVE_PK_CALLBACKS
const byte* keyBuf = NULL;
@@ -4899,7 +5152,7 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
#endif
#if defined(WC_RSA_PSS)
- if (sigAlgo == rsa_pss_sa_algo) {
+ if (sigAlgo == rsa_pss_sa_algo || sigAlgo == rsa_pss_pss_algo) {
enum wc_HashType hashType = WC_HASH_TYPE_NONE;
int mgf = 0;
@@ -4928,7 +5181,7 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
!defined(WOLFSSL_RENESAS_TSIP_TLS)
else
#else
- if (!ssl->ctx->RsaVerifyCb || ret == CRYPTOCB_UNAVAILABLE)
+ if (!ssl->ctx->RsaVerifyCb || ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
#endif
#endif /*HAVE_PK_CALLBACKS */
{
@@ -4937,7 +5190,7 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5010,7 +5263,7 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz,
TypeHash(hashAlgo), mgf,
keyBuf, keySz, ctx);
if (ret > 0) {
- ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret,
+ ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, (word32)ret,
hashType);
if (ret != 0) {
ret = VERIFY_CERT_ERROR;
@@ -5028,7 +5281,7 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz,
ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret,
hashType);
#else
- ret = wc_RsaPSS_CheckPadding_ex(plain, plainSz, out, ret,
+ ret = wc_RsaPSS_CheckPadding_ex(plain, plainSz, out, (word32)ret,
hashType, -1,
mp_count_bits(&key->n));
#endif
@@ -5075,7 +5328,7 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (key && ret == WC_PENDING_E) {
+ if (key && ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5087,7 +5340,8 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz,
#ifndef WOLFSSL_NO_TLS12
-#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+#if (!defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)) && \
+ !defined(WOLFSSL_RSA_PUBLIC_ONLY)
int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz,
RsaKey* key, DerBuffer* keyBufInfo)
{
@@ -5135,7 +5389,7 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5152,10 +5406,11 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz,
}
#endif /* !NO_WOLFSSL_SERVER) || !WOLFSSL_NO_CLIENT_AUTH */
+#ifndef WOLFSSL_RSA_VERIFY_ONLY
int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz,
RsaKey* key, buffer* keyBufInfo)
{
- int ret = BAD_FUNC_ARG;
+ int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
#ifdef HAVE_PK_CALLBACKS
const byte* keyBuf = NULL;
word32 keySz = 0;
@@ -5187,7 +5442,7 @@ int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz,
!defined(WOLFSSL_RENESAS_TSIP_TLS)
else
#else
- if (!ssl->ctx->RsaEncCb || ret == CRYPTOCB_UNAVAILABLE)
+ if (!ssl->ctx->RsaEncCb || ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
#endif
#endif /* HAVE_PK_CALLBACKS */
{
@@ -5196,14 +5451,14 @@ int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
/* For positive response return in outSz */
if (ret > 0) {
- *outSz = ret;
+ *outSz = (word32)ret;
ret = 0;
}
@@ -5211,6 +5466,7 @@ int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz,
return ret;
}
+#endif
#endif /* !WOLFSSL_NO_TLS12 */
@@ -5256,7 +5512,7 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
ret = ssl->ctx->EccSignCb(ssl, in, inSz, out, outSz, keyBuf,
keySz, ctx);
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
- if (ret == CRYPTOCB_UNAVAILABLE) {
+ if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
ret = wc_ecc_sign_hash(in, inSz, out, outSz, ssl->rng, key);
}
#endif /* WOLFSSL_RENESAS_TSIP_TLS */
@@ -5269,7 +5525,7 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (key && ret == WC_PENDING_E) {
+ if (key && ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5282,7 +5538,7 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
word32 outSz, ecc_key* key, buffer* keyBufInfo)
{
- int ret = SIG_VERIFY_E;
+ int ret = WC_NO_ERR_TRACE(SIG_VERIFY_E);
#ifdef HAVE_PK_CALLBACKS
const byte* keyBuf = NULL;
word32 keySz = 0;
@@ -5316,7 +5572,7 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
!defined(WOLFSSL_MAXQ108X)
else
#else
- if (!ssl->ctx->EccVerifyCb || ret == CRYPTOCB_UNAVAILABLE)
+ if (!ssl->ctx->EccVerifyCb || ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
#endif
#endif /* HAVE_PK_CALLBACKS */
{
@@ -5325,7 +5581,7 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
else
@@ -5398,7 +5654,7 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5428,9 +5684,7 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
keySz = ssl->eccTempKeySz;
/* get curve type */
if (ssl->ecdhCurveOID > 0) {
- WOLFSSL_MSG("calling ecc_cuve"); /* TODO; review */
ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL);
- WOLFSSL_MSG("ecc_curve done");
}
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) && \
(defined(WOLFSSL_SM4_CBC) || defined(WOLFSSL_SM4_GCM) || \
@@ -5459,14 +5713,12 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
#ifdef HAVE_PK_CALLBACKS
if (ssl->ctx->EccKeyGenCb) {
void* ctx = wolfSSL_GetEccKeyGenCtx(ssl);
- ret = ssl->ctx->EccKeyGenCb(ssl, key, keySz, ecc_curve, ctx);
+ ret = ssl->ctx->EccKeyGenCb(ssl, key, (unsigned int)keySz, ecc_curve, ctx);
}
else
#endif
{
- WOLFSSL_MSG("make key"); /* TODO review */
ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, ecc_curve);
- WOLFSSL_MSG("make key done");
}
/* make sure the curve is set for TLS */
@@ -5479,7 +5731,7 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5519,7 +5771,7 @@ int Sm2wSm3Verify(WOLFSSL* ssl, const byte* id, word32 idSz, const byte* sig,
word32 sigSz, const byte* msg, word32 msgSz, ecc_key* key,
buffer* keyBufInfo)
{
- int ret = SIG_VERIFY_E;
+ int ret = WC_NO_ERR_TRACE(SIG_VERIFY_E);
byte hash[WC_SM3_DIGEST_SIZE];
(void)ssl;
@@ -5545,7 +5797,7 @@ int Sm2wSm3Verify(WOLFSSL* ssl, const byte* id, word32 idSz, const byte* sig,
return ret;
}
-#endif /* WOLFSSL_SM2 */
+#endif /* WOLFSSL_SM2 && WOLFSSL_SM3 */
#ifdef HAVE_ED25519
/* Check whether the key contains a public key.
@@ -5642,7 +5894,7 @@ int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5716,7 +5968,7 @@ int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
else
@@ -5732,7 +5984,7 @@ int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
}
#endif /* HAVE_ED25519 */
-#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_TLS) && !defined(WOLFSSL_NO_TLS12)
#ifdef HAVE_CURVE25519
#ifdef HAVE_PK_CALLBACKS
@@ -5742,7 +5994,6 @@ int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
*/
static int X25519GetKey(WOLFSSL* ssl, curve25519_key** otherKey)
{
- int ret = NO_PEER_KEY;
struct curve25519_key* tmpKey = NULL;
if (ssl == NULL || otherKey == NULL) {
@@ -5765,10 +6016,11 @@ int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
if (tmpKey) {
*otherKey = (curve25519_key *)tmpKey;
- ret = 0;
+ return 0;
+ }
+ else {
+ return NO_PEER_KEY;
}
-
- return ret;
}
#endif /* HAVE_PK_CALLBACKS */
@@ -5806,13 +6058,19 @@ static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key,
else
#endif
{
- ret = wc_curve25519_shared_secret_ex(priv_key, pub_key, out, outlen,
- EC25519_LITTLE_ENDIAN);
+ #ifdef WOLFSSL_CURVE25519_BLINDING
+ ret = wc_curve25519_set_rng(priv_key, ssl->rng);
+ if (ret == 0)
+ #endif
+ {
+ ret = wc_curve25519_shared_secret_ex(priv_key, pub_key, out, outlen,
+ EC25519_LITTLE_ENDIAN);
+ }
}
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5858,7 +6116,7 @@ static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -5869,7 +6127,7 @@ static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key,
}
#endif /* HAVE_CURVE25519 */
-#endif /* !WOLFSSL_NO_TLS12 */
+#endif /* !NO_TLS && !WOLFSSL_NO_TLS12 */
#ifdef HAVE_ED448
/* Check whether the key contains a public key.
@@ -5966,7 +6224,7 @@ int Ed448Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -6040,7 +6298,7 @@ int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
else
@@ -6066,7 +6324,6 @@ int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
*/
static int X448GetKey(WOLFSSL* ssl, curve448_key** otherKey)
{
- int ret = NO_PEER_KEY;
struct curve448_key* tmpKey = NULL;
if (ssl == NULL || otherKey == NULL) {
@@ -6088,10 +6345,11 @@ int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg,
if (tmpKey) {
*otherKey = (curve448_key *)tmpKey;
- ret = 0;
+ return 0;
+ }
+ else {
+ return NO_PEER_KEY;
}
-
- return ret;
}
#endif /* HAVE_PK_CALLBACKS */
@@ -6136,7 +6394,7 @@ static int X448SharedSecret(WOLFSSL* ssl, curve448_key* priv_key,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -6181,7 +6439,7 @@ static int X448MakeKey(WOLFSSL* ssl, curve448_key* key, curve448_key* peer)
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -6205,6 +6463,10 @@ int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
WOLFSSL_ENTER("DhGenKeyPair");
+ if (ssl == NULL || dhKey == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
#ifdef WOLFSSL_ASYNC_CRYPT
/* initialize event */
ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
@@ -6218,7 +6480,7 @@ int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
ret = ssl->ctx->DhGenerateKeyPairCb(dhKey, ssl->rng, priv, privSz,
pub, pubSz);
}
- if (ret == NOT_COMPILED_IN)
+ if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN))
#endif
{
PRIVATE_KEY_UNLOCK();
@@ -6228,7 +6490,7 @@ int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -6298,7 +6560,7 @@ int DhAgree(WOLFSSL* ssl, DhKey* dhKey,
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -6384,19 +6646,19 @@ int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx)
static void InitSuites_EitherSide(Suites* suites, ProtocolVersion pv, int keySz,
word16 haveRSA, word16 havePSK, word16 haveDH, word16 haveECDSAsig,
word16 haveECC, word16 haveStaticECC,
- word16 haveFalconSig, word16 haveDilithiumSig, word16 haveAnon,
+ word16 haveAnon,
int side)
{
/* make sure server has DH params, and add PSK if there */
if (side == WOLFSSL_SERVER_END) {
InitSuites(suites, pv, keySz, haveRSA, havePSK, haveDH, haveECDSAsig,
- haveECC, TRUE, haveStaticECC, haveFalconSig,
- haveDilithiumSig, haveAnon, TRUE, side);
+ haveECC, TRUE, haveStaticECC,
+ haveAnon, TRUE, TRUE, TRUE, TRUE, side);
}
else {
InitSuites(suites, pv, keySz, haveRSA, havePSK, TRUE, haveECDSAsig,
- haveECC, TRUE, haveStaticECC, haveFalconSig,
- haveDilithiumSig, haveAnon, TRUE, side);
+ haveECC, TRUE, haveStaticECC,
+ haveAnon, TRUE, TRUE, TRUE, TRUE, side);
}
}
@@ -6420,7 +6682,7 @@ void InitSSL_CTX_Suites(WOLFSSL_CTX* ctx)
#endif
InitSuites_EitherSide(ctx->suites, ctx->method->version, keySz,
haveRSA, havePSK, ctx->haveDH, ctx->haveECDSAsig, ctx->haveECC,
- ctx->haveStaticECC, ctx->haveFalconSig, ctx->haveDilithiumSig,
+ ctx->haveStaticECC,
haveAnon, ctx->method->side);
}
@@ -6431,9 +6693,11 @@ int InitSSL_Suites(WOLFSSL* ssl)
byte haveAnon = 0;
byte haveRSA = 0;
byte haveMcast = 0;
+ byte haveCertSetupCb = 0;
(void)haveAnon; /* Squash unused var warnings */
(void)haveMcast;
+ (void)haveCertSetupCb;
if (!ssl)
return BAD_FUNC_ARG;
@@ -6452,6 +6716,10 @@ int InitSSL_Suites(WOLFSSL* ssl)
haveMcast = (byte)ssl->options.haveMcast;
#endif /* WOLFSSL_MULTICAST */
#endif /* !NO_CERTS && !WOLFSSL_SESSION_EXPORT */
+#if defined(WOLFSSL_TLS13) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
+ if (ssl->ctx->certSetupCb != NULL)
+ haveCertSetupCb = 1;
+#endif /* WOLFSSL_TLS13 && !NO_CERTS && OPENSSL_EXTRA */
#ifdef WOLFSSL_EARLY_DATA
if (ssl->options.side == WOLFSSL_SERVER_END)
@@ -6475,24 +6743,32 @@ int InitSSL_Suites(WOLFSSL* ssl)
InitSuites_EitherSide(ssl->suites, ssl->version, keySz, haveRSA,
havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig,
ssl->options.haveECC, ssl->options.haveStaticECC,
- ssl->options.haveFalconSig, ssl->options.haveDilithiumSig,
ssl->options.useAnon, ssl->options.side);
}
#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT)
- /* make sure server has cert and key unless using PSK, Anon, or
- * Multicast. This should be true even if just switching ssl ctx */
+ /* make sure server has cert and key unless using PSK, Anon,
+ * Multicast or cert setup callback. This should be true even if just
+ * switching ssl ctx */
if (ssl->options.side == WOLFSSL_SERVER_END &&
- !havePSK && !haveAnon && !haveMcast) {
+ !havePSK && !haveAnon && !haveMcast && !haveCertSetupCb) {
/* server certificate must be loaded */
- if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) {
+ if ((!ssl->buffers.certificate || !ssl->buffers.certificate->buffer)
+#ifdef WOLFSSL_CERT_SETUP_CB
+ && ssl->ctx->certSetupCb == NULL
+#endif
+ ) {
WOLFSSL_MSG("Server missing certificate");
WOLFSSL_ERROR_VERBOSE(NO_PRIVATE_KEY);
return NO_PRIVATE_KEY;
}
- if (!ssl->buffers.key || !ssl->buffers.key->buffer) {
+ if ((!ssl->buffers.key || !ssl->buffers.key->buffer)
+#ifdef WOLFSSL_CERT_SETUP_CB
+ && ssl->ctx->certSetupCb == NULL
+#endif
+ ) {
/* allow no private key if using existing key */
#ifdef WOLF_PRIVATE_KEY_ID
if (ssl->devId != INVALID_DEVID
@@ -6589,7 +6865,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#ifdef OPENSSL_EXTRA
#ifdef WOLFSSL_TLS13
if (ssl->version.minor == TLSv1_3_MINOR &&
- (ssl->options.mask & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) {
+ (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3) == WOLFSSL_OP_NO_TLSv1_3) {
if (!ctx->method->downgrade) {
WOLFSSL_MSG("\tInconsistent protocol options. TLS 1.3 set but not "
"allowed and downgrading disabled.");
@@ -6601,7 +6877,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
}
#endif
if (ssl->version.minor == TLSv1_2_MINOR &&
- (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) {
+ (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) {
if (!ctx->method->downgrade) {
WOLFSSL_MSG("\tInconsistent protocol options. TLS 1.2 set but not "
"allowed and downgrading disabled.");
@@ -6612,7 +6888,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->version.minor = TLSv1_1_MINOR;
}
if (ssl->version.minor == TLSv1_1_MINOR &&
- (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) {
+ (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) {
if (!ctx->method->downgrade) {
WOLFSSL_MSG("\tInconsistent protocol options. TLS 1.1 set but not "
"allowed and downgrading disabled.");
@@ -6624,7 +6900,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->version.minor = TLSv1_MINOR;
}
if (ssl->version.minor == TLSv1_MINOR &&
- (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) {
+ (ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) {
if (!ctx->method->downgrade) {
WOLFSSL_MSG("\tInconsistent protocol options. TLS 1 set but not "
"allowed and downgrading disabled.");
@@ -6637,7 +6913,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->version.minor = SSLv3_MINOR;
}
if (ssl->version.minor == SSLv3_MINOR &&
- (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) {
+ (ssl->options.mask & WOLFSSL_OP_NO_SSLv3) == WOLFSSL_OP_NO_SSLv3) {
WOLFSSL_MSG("\tError, option set to not allow SSLv3");
WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
return VERSION_ERROR;
@@ -6666,13 +6942,36 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
/* If we are setting the ctx on an already initialized SSL object
* then we possibly already have a side defined. Don't overwrite unless
* the context has a well defined role. */
- if (newSSL || ctx->method->side != WOLFSSL_NEITHER_END)
- ssl->options.side = ctx->method->side;
- ssl->options.downgrade = ctx->method->downgrade;
- ssl->options.minDowngrade = ctx->minDowngrade;
-
+ if (newSSL || ctx->method->side != WOLFSSL_NEITHER_END) {
+ ssl->options.side = (word16)(ctx->method->side);
+ }
+ ssl->options.downgrade = (word16)(ctx->method->downgrade);
+ ssl->options.minDowngrade = ctx->minDowngrade;
ssl->options.haveRSA = ctx->haveRSA;
ssl->options.haveDH = ctx->haveDH;
+#if !defined(NO_CERTS) && !defined(NO_DH)
+ /* Its possible that DH algorithm parameters were set in the ctx, recalc
+ * cipher suites. */
+ if (ssl->options.haveDH && ctx->serverDH_P.buffer != NULL &&
+ ctx->serverDH_G.buffer != NULL) {
+ if (ssl->suites == NULL) {
+ if (AllocateSuites(ssl) != 0) {
+ return MEMORY_E;
+ }
+ }
+ InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz,
+ ssl->options.haveRSA,
+#ifdef NO_PSK
+ 0,
+#else
+ ctx->havePSK,
+#endif
+ ssl->options.haveDH,
+ ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE,
+ ssl->options.haveStaticECC, ssl->options.useAnon,
+ TRUE, TRUE, TRUE, TRUE, ssl->options.side);
+ }
+#endif /* !NO_CERTS && !NO_DH */
ssl->options.haveECDSAsig = ctx->haveECDSAsig;
ssl->options.haveECC = ctx->haveECC;
ssl->options.haveStaticECC = ctx->haveStaticECC;
@@ -6680,7 +6979,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->options.haveDilithiumSig = ctx->haveDilithiumSig;
#ifndef NO_PSK
- ssl->options.havePSK = ctx->havePSK;
+ ssl->options.havePSK = (word16)(ctx->havePSK);
ssl->options.client_psk_cb = ctx->client_psk_cb;
ssl->options.server_psk_cb = ctx->server_psk_cb;
ssl->options.psk_ctx = ctx->psk_ctx;
@@ -6708,14 +7007,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#ifdef HAVE_ECC
ssl->options.minEccKeySz = ctx->minEccKeySz;
#endif
-#ifdef HAVE_PQC
#ifdef HAVE_FALCON
ssl->options.minFalconKeySz = ctx->minFalconKeySz;
#endif /* HAVE_FALCON */
#ifdef HAVE_DILITHIUM
ssl->options.minDilithiumKeySz = ctx->minDilithiumKeySz;
#endif /* HAVE_DILITHIUM */
-#endif /* HAVE_PQC */
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
ssl->options.verifyDepth = ctx->verifyDepth;
#endif
@@ -6752,22 +7049,107 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#endif /* HAVE_RPK */
#ifndef NO_CERTS
+#ifdef WOLFSSL_COPY_CERT
+ /* If WOLFSSL_COPY_CERT is defined, always copy the cert */
+ if (ctx->certificate != NULL) {
+ ret = AllocCopyDer(&ssl->buffers.certificate, ctx->certificate->buffer,
+ ctx->certificate->length, ctx->certificate->type,
+ ctx->certificate->heap);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ssl->buffers.weOwnCert = 1;
+ ret = WOLFSSL_SUCCESS;
+ }
+ if (ctx->certChain != NULL) {
+ ret = AllocCopyDer(&ssl->buffers.certChain, ctx->certChain->buffer,
+ ctx->certChain->length, ctx->certChain->type,
+ ctx->certChain->heap);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ssl->buffers.weOwnCertChain = 1;
+ ret = WOLFSSL_SUCCESS;
+ }
+#else
/* ctx still owns certificate, certChain, key, dh, and cm */
ssl->buffers.certificate = ctx->certificate;
ssl->buffers.certChain = ctx->certChain;
-#ifdef WOLFSSL_TLS13
- ssl->buffers.certChainCnt = ctx->certChainCnt;
#endif
+ ssl->buffers.certChainCnt = ctx->certChainCnt;
+#ifndef WOLFSSL_BLIND_PRIVATE_KEY
+#ifdef WOLFSSL_COPY_KEY
+ if (ctx->privateKey != NULL) {
+ if (ssl->buffers.key != NULL) {
+ FreeDer(&ssl->buffers.key);
+ }
+ ret = AllocCopyDer(&ssl->buffers.key, ctx->privateKey->buffer,
+ ctx->privateKey->length, ctx->privateKey->type,
+ ctx->privateKey->heap);
+ if (ret != 0) {
+ return ret;
+ }
+ ssl->buffers.weOwnKey = 1;
+ ret = WOLFSSL_SUCCESS;
+ }
+ else {
+ ssl->buffers.key = ctx->privateKey;
+ }
+#else
ssl->buffers.key = ctx->privateKey;
+#endif
+#else
+ if (ctx->privateKey != NULL) {
+ ret = AllocCopyDer(&ssl->buffers.key, ctx->privateKey->buffer,
+ ctx->privateKey->length, ctx->privateKey->type,
+ ctx->privateKey->heap);
+ if (ret != 0) {
+ return ret;
+ }
+ ssl->buffers.weOwnKey = 1;
+ /* Blind the private key for the SSL with new random mask. */
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key, ctx->privateKeyMask);
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key,
+ &ssl->buffers.keyMask);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+#endif
ssl->buffers.keyType = ctx->privateKeyType;
ssl->buffers.keyId = ctx->privateKeyId;
ssl->buffers.keyLabel = ctx->privateKeyLabel;
ssl->buffers.keySz = ctx->privateKeySz;
ssl->buffers.keyDevId = ctx->privateKeyDevId;
#ifdef WOLFSSL_DUAL_ALG_CERTS
- ssl->buffers.altKey = ctx->altPrivateKey;
- ssl->buffers.altKeySz = ctx->altPrivateKeySz;
- ssl->buffers.altKeyType = ctx->altPrivateKeyType;
+#ifndef WOLFSSL_BLIND_PRIVATE_KEY
+ ssl->buffers.altKey = ctx->altPrivateKey;
+#else
+ if (ctx->altPrivateKey != NULL) {
+ ret = AllocCopyDer(&ssl->buffers.altkey, ctx->altPrivateKey->buffer,
+ ctx->altPrivateKey->length, ctx->altPrivateKey->type,
+ ctx->altPrivateKey->heap);
+ if (ret != 0) {
+ return ret;
+ }
+ /* Blind the private key for the SSL with new random mask. */
+ wolfssl_priv_der_blind_toggle(ssl->buffers.altKey,
+ ctx->altPrivateKeyMask);
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey,
+ &ssl->buffers.altKeyMask);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = WOLFSSL_SUCCESS;
+ }
+#endif
+ ssl->buffers.altKeyType = ctx->altPrivateKeyType;
+ ssl->buffers.altKeyId = ctx->altPrivateKeyId;
+ ssl->buffers.altKeyLabel = ctx->altPrivateKeyLabel;
+ ssl->buffers.altKeySz = ctx->altPrivateKeySz;
+ ssl->buffers.altKeyDevId = ctx->altPrivateKeyDevId;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#endif
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
@@ -6807,7 +7189,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
}
} /* writeDup check */
- if (ctx->mask != 0 && wolfSSL_set_options(ssl, ctx->mask) == 0) {
+ if (ctx->mask != 0 && wolfSSL_set_options(ssl, (long)ctx->mask) == 0) {
WOLFSSL_MSG("wolfSSL_set_options error");
return BAD_FUNC_ARG;
}
@@ -6830,12 +7212,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#endif
#if defined(OPENSSL_EXTRA) && !defined(NO_BIO)
/* Don't change recv callback if currently using BIO's */
- if (ssl->CBIORecv != BioReceive)
+ if (ssl->CBIORecv != SslBioReceive)
#endif
ssl->CBIORecv = ctx->CBIORecv;
#if defined(OPENSSL_EXTRA) && !defined(NO_BIO)
/* Don't change send callback if currently using BIO's */
- if (ssl->CBIOSend != BioSend)
+ if (ssl->CBIOSend != SslBioSend)
#endif
ssl->CBIOSend = ctx->CBIOSend;
ssl->verifyDepth = ctx->verifyDepth;
@@ -6940,7 +7322,7 @@ void FreeHandshakeHashes(WOLFSSL* ssl)
(defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3))) && \
!defined(WOLFSSL_NO_CLIENT_AUTH)
if (ssl->hsHashes->messages != NULL) {
- ForceZero(ssl->hsHashes->messages, ssl->hsHashes->length);
+ ForceZero(ssl->hsHashes->messages, (word32)ssl->hsHashes->length);
XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES);
ssl->hsHashes->messages = NULL;
}
@@ -6955,7 +7337,7 @@ void FreeHandshakeHashes(WOLFSSL* ssl)
int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source,
HS_Hashes** destination)
{
- int ret = 0;
+ int ret;
HS_Hashes* tmpHashes;
if (source == NULL)
@@ -6963,9 +7345,15 @@ int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source,
/* save the original so we can put it back afterward */
tmpHashes = ssl->hsHashes;
- ssl->hsHashes = NULL;
+ ssl->hsHashes = *destination;
- InitHandshakeHashes(ssl);
+ ret = InitHandshakeHashes(ssl);
+ if (ret != 0) {
+ WOLFSSL_MSG_EX("InitHandshakeHashes failed. err = %d", ret);
+ ssl->hsHashes = tmpHashes; /* restore hsHashes pointer to original
+ * before returning */
+ return ret;
+ }
*destination = ssl->hsHashes;
ssl->hsHashes = tmpHashes;
@@ -6973,50 +7361,51 @@ int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source,
/* now copy the source contents to the destination */
#ifndef NO_OLD_TLS
#ifndef NO_SHA
- ret = wc_ShaCopy(&source->hashSha, &(*destination)->hashSha);
+ ret = wc_ShaCopy(&source->hashSha, &(*destination)->hashSha);
#endif
#ifndef NO_MD5
- if (ret == 0)
- ret = wc_Md5Copy(&source->hashMd5, &(*destination)->hashMd5);
+ if (ret == 0)
+ ret = wc_Md5Copy(&source->hashMd5, &(*destination)->hashMd5);
#endif
#endif /* !NO_OLD_TLS */
#ifndef NO_SHA256
- if (ret == 0)
- ret = wc_Sha256Copy(&source->hashSha256,
- &(*destination)->hashSha256);
+ if (ret == 0)
+ ret = wc_Sha256Copy(&source->hashSha256,
+ &(*destination)->hashSha256);
#endif
#ifdef WOLFSSL_SHA384
- if (ret == 0)
- ret = wc_Sha384Copy(&source->hashSha384,
- &(*destination)->hashSha384);
+ if (ret == 0)
+ ret = wc_Sha384Copy(&source->hashSha384,
+ &(*destination)->hashSha384);
#endif
#ifdef WOLFSSL_SHA512
- if (ret == 0)
- ret = wc_Sha512Copy(&source->hashSha512,
- &(*destination)->hashSha512);
+ if (ret == 0)
+ ret = wc_Sha512Copy(&source->hashSha512,
+ &(*destination)->hashSha512);
#endif
#ifdef WOLFSSL_SM3
- if (ret == 0)
- ret = wc_Sm3Copy(&source->hashSm3,
- &(*destination)->hashSm3);
+ if (ret == 0)
+ ret = wc_Sm3Copy(&source->hashSm3,
+ &(*destination)->hashSm3);
#endif
#if (defined(HAVE_ED25519) || defined(HAVE_ED448) || \
(defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3))) && \
!defined(WOLFSSL_NO_CLIENT_AUTH)
- if (ret == 0 && source->messages != NULL) {
- (*destination)->messages = (byte*)XMALLOC(source->length, ssl->heap,
- DYNAMIC_TYPE_HASHES);
- (*destination)->length = source->length;
- (*destination)->prevLen = source->prevLen;
-
- if ((*destination)->messages == NULL) {
- ret = MEMORY_E;
- }
- else {
- XMEMCPY((*destination)->messages, source->messages,
- source->length);
- }
+ if (ret == 0 && source->messages != NULL) {
+ (*destination)->messages = (byte*)XMALLOC((size_t)source->length,
+ ssl->heap,
+ (int)DYNAMIC_TYPE_HASHES);
+ (*destination)->length = source->length;
+ (*destination)->prevLen = source->prevLen;
+
+ if ((*destination)->messages == NULL) {
+ ret = MEMORY_E;
+ }
+ else {
+ XMEMCPY((*destination)->messages, source->messages,
+ (size_t)source->length);
}
+ }
#endif
return ret;
@@ -7047,6 +7436,7 @@ int ReinitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap,
DYNAMIC_TYPE_SECRET);
if (ssl->arrays->preMasterSecret == NULL) {
+ WOLFSSL_MSG("preMasterSecret Memory error");
return MEMORY_E;
}
#ifdef WOLFSSL_CHECK_MEM_ZERO
@@ -7120,7 +7510,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
wc_MemZero_Add("ServerFinished hash", &ssl->serverFinished,
TLS_FINISHED_SZ_MAX);
#endif
-#endif
+#endif /* WOLFSSL_CHECK_MEM_ZERO */
#if defined(WOLFSSL_STATIC_MEMORY)
if (ctx->heap != NULL) {
@@ -7143,6 +7533,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl_hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
ctx_hint = ((WOLFSSL_HEAP_HINT*)(ctx->heap));
+ ssl_hint->memory = ctx_hint->memory;
+ #ifndef WOLFSSL_STATIC_MEMORY_LEAN
+ #ifndef SINGLE_THREADED
/* lock and check IO count / handshake count */
if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
@@ -7151,10 +7544,13 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
WOLFSSL_ERROR_VERBOSE(BAD_MUTEX_E);
return BAD_MUTEX_E;
}
+ #endif
if (ctx_hint->memory->maxHa > 0 &&
ctx_hint->memory->maxHa <= ctx_hint->memory->curHa) {
WOLFSSL_MSG("At max number of handshakes for static memory");
+ #ifndef SINGLE_THREADED
wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ #endif
XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
ssl->heap = NULL; /* free and set to NULL for IO counter */
return MEMORY_E;
@@ -7163,16 +7559,19 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
if (ctx_hint->memory->maxIO > 0 &&
ctx_hint->memory->maxIO <= ctx_hint->memory->curIO) {
WOLFSSL_MSG("At max number of IO allowed for static memory");
+ #ifndef SINGLE_THREADED
wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ #endif
XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL);
ssl->heap = NULL; /* free and set to NULL for IO counter */
return MEMORY_E;
}
ctx_hint->memory->curIO++;
ctx_hint->memory->curHa++;
- ssl_hint->memory = ctx_hint->memory;
ssl_hint->haFlag = 1;
+ #ifndef SINGLE_THREADED
wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ #endif
/* check if tracking stats */
if (ctx_hint->memory->flag & WOLFMEM_TRACK_STATS) {
@@ -7186,26 +7585,37 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
/* check if using fixed IO buffers */
if (ctx_hint->memory->flag & WOLFMEM_IO_POOL_FIXED) {
+ #ifndef SINGLE_THREADED
if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
WOLFSSL_ERROR_VERBOSE(BAD_MUTEX_E);
return BAD_MUTEX_E;
}
+ #endif
if (SetFixedIO(ctx_hint->memory, &(ssl_hint->inBuf)) != 1) {
+ #ifndef SINGLE_THREADED
wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ #endif
return MEMORY_E;
}
if (SetFixedIO(ctx_hint->memory, &(ssl_hint->outBuf)) != 1) {
+ #ifndef SINGLE_THREADED
wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ #endif
return MEMORY_E;
}
if (ssl_hint->outBuf == NULL || ssl_hint->inBuf == NULL) {
WOLFSSL_MSG("Not enough memory to create fixed IO buffers");
+ #ifndef SINGLE_THREADED
wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ #endif
return MEMORY_E;
}
+ #ifndef SINGLE_THREADED
wc_UnLockMutex(&(ctx_hint->memory->memory_mutex));
+ #endif
}
+ #endif /* !WOLFSSL_STATIC_MEMORY_LEAN */
#ifdef WOLFSSL_HEAP_TEST
}
#endif
@@ -7223,6 +7633,15 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
+#ifdef WOLFSSL_THREADED_CRYPT
+ {
+ int i;
+ for (i = 0; i < WOLFSSL_THREADED_CRYPT_CNT; i++) {
+ ssl->buffers.encrypt[i].avail = 1;
+ }
+ }
+#endif
+
#ifdef KEEP_PEER_CERT
InitX509(&ssl->peerCert, 0, ssl->heap);
#endif
@@ -7247,7 +7666,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
!defined(HAVE_SELFTEST)
ssl->options.dhDoKeyTest = 1;
#endif
-#endif
+#endif /* !NO_DH */
#ifdef WOLFSSL_DTLS
#ifdef WOLFSSL_SCTP
@@ -7266,6 +7685,11 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->buffers.dtlsCtx.rfd = -1;
ssl->buffers.dtlsCtx.wfd = -1;
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_InitRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
+ return BAD_MUTEX_E;
+#endif
+
ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; /* prevent invalid pointer access if not */
ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx; /* correctly set */
#else
@@ -7286,7 +7710,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */
ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */
#endif
-#endif
+#endif /* WOLFSSL_DTLS */
#ifndef WOLFSSL_AEAD_ONLY
@@ -7300,7 +7724,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->hmac = Renesas_cmn_TLS_hmac;
#endif
#endif
-#endif
+#endif /* WOLFSSL_AEAD_ONLY */
#if defined(WOLFSSL_OPENVPN) && defined(HAVE_KEYING_MATERIAL)
/* Save arrays by default for OpenVPN */
@@ -7341,7 +7765,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT
ssl->options.tls13MiddleBoxCompat = 1;
#endif
-#endif
+#endif /* WOLFSSL_TLS13 */
#ifdef HAVE_TLS_EXTENSIONS
#ifdef HAVE_MAX_FRAGMENT
@@ -7377,6 +7801,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
ssl->options.disallowEncThenMac = ctx->disallowEncThenMac;
#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
+ ssl->options.disableECH = ctx->disableECH;
+#endif
/* default alert state (none) */
ssl->alert_history.last_rx.code = -1;
@@ -7422,6 +7849,14 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
return MEMORY_E;
}
XMEMSET(ssl->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
+
+ /* pass on PARAM flags value from ctx to ssl */
+ if (wolfSSL_X509_VERIFY_PARAM_set_flags(wolfSSL_get0_param(ssl),
+ (unsigned long)wolfSSL_X509_VERIFY_PARAM_get_flags(
+ wolfSSL_CTX_get0_param(ctx))) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("ssl->param set flags error");
+ return WOLFSSL_FAILURE;
+ }
#endif
if (ctx->suites == NULL) {
@@ -7440,7 +7875,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
/* requires valid arrays and suites unless writeDup ing */
if ((ret = SetSSL_CTX(ssl, ctx, writeDup)) != WOLFSSL_SUCCESS
#ifdef WOLFSSL_NO_INIT_CTX_KEY
- && ret != NO_PRIVATE_KEY
+ && ret != WC_NO_ERR_TRACE(NO_PRIVATE_KEY)
#endif
) {
WOLFSSL_MSG_EX("SetSSL_CTX failed. err = %d", ret);
@@ -7557,6 +7992,13 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->dtls13DecryptEpoch = &ssl->dtls13Epochs[0];
ssl->options.dtls13SendMoreAcks = WOLFSSL_DTLS13_SEND_MOREACK_DEFAULT;
ssl->dtls13Rtx.rtxRecordTailPtr = &ssl->dtls13Rtx.rtxRecords;
+
+#ifdef WOLFSSL_RW_THREADED
+ ret = wc_InitMutex(&ssl->dtls13Rtx.mutex);
+ if (ret < 0) {
+ return ret;
+ }
+#endif
#endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_QUIC
@@ -7577,12 +8019,23 @@ 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;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
+#ifdef HAVE_OCSP
+#if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
+ ssl->response_idx = 0;
+#endif
+#endif
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ ssl->secLevel = ctx->secLevel;
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
/* Returns 0 on success, not WOLFSSL_SUCCESS (1) */
- WOLFSSL_MSG_EX("InitSSL done. return 0 (success)");
+ WOLFSSL_MSG("InitSSL done. return 0 (success)");
return 0;
}
@@ -7651,7 +8104,6 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey)
wc_curve448_free((curve448_key*)*pKey);
break;
#endif /* HAVE_CURVE448 */
- #if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
case DYNAMIC_TYPE_FALCON:
wc_falcon_free((falcon_key*)*pKey);
@@ -7662,7 +8114,6 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey)
wc_dilithium_free((dilithium_key*)*pKey);
break;
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
#ifndef NO_DH
case DYNAMIC_TYPE_DH:
wc_FreeDhKey((DhKey*)*pKey);
@@ -7680,8 +8131,8 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey)
int AllocKey(WOLFSSL* ssl, int type, void** pKey)
{
- int ret = BAD_FUNC_ARG;
- int sz = 0;
+ int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
+ size_t sz = 0;
#ifdef HAVE_ECC
ecc_key* eccKey;
#endif /* HAVE_ECC */
@@ -7699,7 +8150,7 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
WOLFSSL_MSG("Key already present!");
#ifdef WOLFSSL_ASYNC_CRYPT
/* allow calling this again for async reentry */
- if (ssl->error == WC_PENDING_E) {
+ if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return 0;
}
#endif
@@ -7738,7 +8189,6 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
sz = sizeof(curve448_key);
break;
#endif /* HAVE_CURVE448 */
- #if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
case DYNAMIC_TYPE_FALCON:
sz = sizeof(falcon_key);
@@ -7749,7 +8199,6 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
sz = sizeof(dilithium_key);
break;
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
#ifndef NO_DH
case DYNAMIC_TYPE_DH:
sz = sizeof(DhKey);
@@ -7813,7 +8262,6 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
ret = 0;
break;
#endif /* HAVE_CURVE448 */
- #if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
case DYNAMIC_TYPE_FALCON:
wc_falcon_init_ex((falcon_key*)*pKey, ssl->heap, ssl->devId);
@@ -7826,7 +8274,6 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
ret = 0;
break;
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
#ifdef HAVE_CURVE448
case DYNAMIC_TYPE_CURVE448:
wc_curve448_init((curve448_key*)*pKey);
@@ -7852,8 +8299,7 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
defined(HAVE_CURVE25519) || defined(HAVE_ED448) || \
- defined(HAVE_CURVE448) || (defined(HAVE_PQC) && defined(HAVE_FALCON)) || \
- (defined(HAVE_PQC) && defined(HAVE_DILITHIUM))
+ defined(HAVE_CURVE448) || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)
static int ReuseKey(WOLFSSL* ssl, int type, void* pKey)
{
int ret = 0;
@@ -7899,12 +8345,18 @@ static int ReuseKey(WOLFSSL* ssl, int type, void* pKey)
ret = wc_curve448_init((curve448_key*)pKey);
break;
#endif /* HAVE_CURVE448 */
- #if defined(HAVE_PQC) && defined(HAVE_FALCON)
+ #if defined(HAVE_FALCON)
case DYNAMIC_TYPE_FALCON:
wc_falcon_free((falcon_key*)pKey);
ret = wc_falcon_init((falcon_key*)pKey);
break;
- #endif /* HAVE_PQC && HAVE_FALCON */
+ #endif /* HAVE_FALCON */
+ #if defined(HAVE_DILITHIUM)
+ case DYNAMIC_TYPE_DILITHIUM:
+ wc_dilithium_free((dilithium_key*)pKey);
+ ret = wc_dilithium_init((dilithium_key*)pKey);
+ break;
+ #endif /* HAVE_DILITHIUM */
#ifndef NO_DH
case DYNAMIC_TYPE_DH:
wc_FreeDhKey((DhKey*)pKey);
@@ -7962,7 +8414,7 @@ void FreeKeyExchange(WOLFSSL* ssl)
}
/* Free handshake key */
- FreeKey(ssl, ssl->hsType, &ssl->hsKey);
+ FreeKey(ssl, (int)ssl->hsType, &ssl->hsKey);
#ifdef WOLFSSL_DUAL_ALG_CERTS
FreeKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
#endif /* WOLFSSL_DUAL_ALG_CERTS */
@@ -7977,13 +8429,21 @@ void FreeKeyExchange(WOLFSSL* ssl)
/* Free up all memory used by Suites structure from WOLFSSL */
void FreeSuites(WOLFSSL* ssl)
{
-#ifdef OPENSSL_ALL
+#ifdef OPENSSL_EXTRA
if (ssl->suitesStack != NULL) {
/* Enough to free stack structure since WOLFSSL_CIPHER
* isn't allocated separately. */
wolfSSL_sk_SSL_CIPHER_free(ssl->suitesStack);
ssl->suitesStack = NULL;
}
+ if (ssl->clSuitesStack != NULL) {
+ /* Enough to free stack structure since WOLFSSL_CIPHER
+ * isn't allocated separately. */
+ wolfSSL_sk_SSL_CIPHER_free(ssl->clSuitesStack);
+ ssl->clSuitesStack = NULL;
+ }
+ XFREE(ssl->clSuites, ssl->heap, DYNAMIC_TYPE_SUITES);
+ ssl->clSuites = NULL;
#endif
XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
ssl->suites = NULL;
@@ -7991,7 +8451,7 @@ void FreeSuites(WOLFSSL* ssl)
/* In case holding SSL object in array and don't want to free actual ssl */
-void SSL_ResourceFree(WOLFSSL* ssl)
+void wolfSSL_ResourceFree(WOLFSSL* ssl)
{
/* Note: any resources used during the handshake should be released in the
* function FreeHandshakeResources(). Be careful with the special cases
@@ -8025,6 +8485,13 @@ void SSL_ResourceFree(WOLFSSL* ssl)
}
FreeSuites(ssl);
FreeHandshakeHashes(ssl);
+#ifdef HAVE_ECH
+ /* try to free the ech hashes in case we errored out */
+ ssl->hsHashes = ssl->hsHashesEch;
+ FreeHandshakeHashes(ssl);
+ ssl->hsHashes = ssl->hsHashesEchInner;
+ FreeHandshakeHashes(ssl);
+#endif
XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
/* clear keys struct after session */
@@ -8038,9 +8505,6 @@ void SSL_ResourceFree(WOLFSSL* ssl)
if (ssl->options.useEch == 1) {
FreeEchConfigs(ssl->echConfigs, ssl->heap);
ssl->echConfigs = NULL;
- /* free the ech specific hashes */
- ssl->hsHashes = ssl->hsHashesEch;
- FreeHandshakeHashes(ssl);
ssl->options.useEch = 0;
}
#endif /* HAVE_ECH */
@@ -8076,10 +8540,31 @@ void SSL_ResourceFree(WOLFSSL* ssl)
XFREE(ssl->peerSceTsipEncRsaKeyIndex, ssl->heap, DYNAMIC_TYPE_RSA);
Renesas_cmn_Cleanup(ssl);
#endif
+#ifndef NO_TLS
if (ssl->buffers.inputBuffer.dynamicFlag)
ShrinkInputBuffer(ssl, FORCED_FREE);
if (ssl->buffers.outputBuffer.dynamicFlag)
ShrinkOutputBuffer(ssl);
+#endif
+#ifdef WOLFSSL_THREADED_CRYPT
+ {
+ int i;
+ for (i = 0; i < WOLFSSL_THREADED_CRYPT_CNT; i++) {
+ bufferStatic* buff = &ssl->buffers.encrypt[i].buffer;
+
+ ssl->buffers.encrypt[i].stop = 1;
+ FreeCiphersSide(&ssl->buffers.encrypt[i].encrypt, ssl->heap);
+ if (buff->dynamicFlag) {
+ XFREE(buff->buffer - buff->offset, ssl->heap,
+ DYNAMIC_TYPE_OUT_BUFFER);
+ buff->buffer = buff->staticBuffer;
+ buff->bufferSize = STATIC_BUFFER_LEN;
+ buff->offset = 0;
+ buff->dynamicFlag = 0;
+ }
+ }
+ }
+#endif
#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
if (ssl->buffers.tls13CookieSecret.buffer != NULL) {
ForceZero(ssl->buffers.tls13CookieSecret.buffer,
@@ -8097,6 +8582,14 @@ void SSL_ResourceFree(WOLFSSL* ssl)
}
XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
ssl->buffers.dtlsCtx.peer.sa = NULL;
+#ifdef WOLFSSL_RW_THREADED
+ wc_FreeRwLock(&ssl->buffers.dtlsCtx.peerLock);
+#endif
+#ifdef WOLFSSL_DTLS_CID
+ XFREE(ssl->buffers.dtlsCtx.pendingPeer.sa, ssl->heap,
+ DYNAMIC_TYPE_SOCKADDR);
+ ssl->buffers.dtlsCtx.pendingPeer.sa = NULL;
+#endif
#ifndef NO_WOLFSSL_SERVER
if (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
ForceZero(ssl->buffers.dtlsCookieSecret.buffer,
@@ -8198,7 +8691,7 @@ void SSL_ResourceFree(WOLFSSL* ssl)
}
#endif
#endif
-#if defined(HAVE_PQC) && defined(HAVE_FALCON)
+#if defined(HAVE_FALCON)
FreeKey(ssl, DYNAMIC_TYPE_FALCON, (void**)&ssl->peerFalconKey);
ssl->peerFalconKeyPresent = 0;
#endif
@@ -8248,10 +8741,16 @@ void SSL_ResourceFree(WOLFSSL* ssl)
}
#endif
#ifdef OPENSSL_EXTRA
- if (ssl->param) {
- XFREE(ssl->param, ssl->heap, DYNAMIC_TYPE_OPENSSL);
- }
+ XFREE(ssl->param, ssl->heap, DYNAMIC_TYPE_OPENSSL);
#endif
+#if defined(HAVE_OCSP)
+ {
+ size_t i;
+ for (i = 0; i < XELEM_CNT(ssl->ocspCsrResp); i++)
+ XFREE(ssl->ocspCsrResp[i].buffer, NULL, 0);
+ XMEMSET(ssl->ocspCsrResp, 0, sizeof(ssl->ocspCsrResp));
+ }
+#endif /* defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) */
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
while (ssl->certReqCtx != NULL) {
CertReqCtx* curr = ssl->certReqCtx;
@@ -8281,14 +8780,17 @@ void SSL_ResourceFree(WOLFSSL* ssl)
/* avoid dereferencing a test value */
if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) {
#endif
+ void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap;
+ #ifndef WOLFSSL_STATIC_MEMORY_LEAN
WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap;
WOLFSSL_HEAP* ctx_heap;
- void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap;
ctx_heap = ssl_hint->memory;
+ #ifndef SINGLE_THREADED
if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
}
+ #endif
ctx_heap->curIO--;
if (FreeFixedIO(ctx_heap, &(ssl_hint->outBuf)) != 1) {
WOLFSSL_MSG("Error freeing fixed output buffer");
@@ -8296,15 +8798,20 @@ void SSL_ResourceFree(WOLFSSL* ssl)
if (FreeFixedIO(ctx_heap, &(ssl_hint->inBuf)) != 1) {
WOLFSSL_MSG("Error freeing fixed output buffer");
}
- if (ssl_hint->haFlag && ctx_heap->curHa > 0) { /* check if handshake count has been decreased*/
+
+ /* check if handshake count has been decreased*/
+ if (ssl_hint->haFlag && ctx_heap->curHa > 0) {
ctx_heap->curHa--;
}
+ #ifndef SINGLE_THREADED
wc_UnLockMutex(&(ctx_heap->memory_mutex));
+ #endif
/* check if tracking stats */
if (ctx_heap->flag & WOLFMEM_TRACK_STATS) {
XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL);
}
+ #endif /* !WOLFSSL_STATIC_MEMORY_LEAN */
XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL);
#ifdef WOLFSSL_HEAP_TEST
}
@@ -8316,16 +8823,25 @@ void SSL_ResourceFree(WOLFSSL* ssl)
* isn't allocated separately. */
wolfSSL_sk_CIPHER_free(ssl->supportedCiphers);
wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL);
+ wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL);
#ifdef KEEP_OUR_CERT
wolfSSL_sk_X509_pop_free(ssl->ourCertChain, NULL);
#endif
#endif
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_LIGHTY)
+#ifndef WOLFSSL_NO_CA_NAMES
wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
ssl->client_ca_names = NULL;
+ wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL);
+ ssl->ca_names = NULL;
+ wolfSSL_sk_X509_NAME_pop_free(ssl->peer_ca_names, NULL);
+ ssl->peer_ca_names = NULL;
#endif
#ifdef WOLFSSL_DTLS13
Dtls13FreeFsmResources(ssl);
+
+#ifdef WOLFSSL_RW_THREADED
+ wc_FreeMutex(&ssl->dtls13Rtx.mutex);
+#endif
#endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_QUIC
wolfSSL_quic_free(ssl);
@@ -8370,9 +8886,11 @@ void FreeHandshakeResources(WOLFSSL* ssl)
}
#endif
+#ifndef NO_TLS
/* input buffer */
if (ssl->buffers.inputBuffer.dynamicFlag)
ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
if (!ssl->options.tls1_3)
@@ -8441,10 +8959,14 @@ void FreeHandshakeResources(WOLFSSL* ssl)
FreeKey(ssl, DYNAMIC_TYPE_ED448, (void**)&ssl->peerEd448Key);
ssl->peerEd448KeyPresent = 0;
#endif /* HAVE_ED448 */
-#if defined(HAVE_PQC) && defined(HAVE_FALCON)
+#if defined(HAVE_FALCON)
FreeKey(ssl, DYNAMIC_TYPE_FALCON, (void**)&ssl->peerFalconKey);
ssl->peerFalconKeyPresent = 0;
-#endif /* HAVE_PQC */
+#endif /* HAVE_FALCON */
+#if defined(HAVE_DILITHIUM)
+ FreeKey(ssl, DYNAMIC_TYPE_DILITHIUM, (void**)&ssl->peerDilithiumKey);
+ ssl->peerDilithiumKeyPresent = 0;
+#endif /* HAVE_DILITHIUM */
}
#ifdef HAVE_ECC
@@ -8507,8 +9029,14 @@ void FreeHandshakeResources(WOLFSSL* ssl)
}
#endif /* !NO_DH */
-#ifndef NO_CERTS
- wolfSSL_UnloadCertsKeys(ssl);
+#if !defined(NO_CERTS) && !defined(OPENSSL_EXTRA) && \
+ !defined(WOLFSSL_WPAS_SMALL)
+#ifndef WOLFSSL_POST_HANDSHAKE_AUTH
+ if (ssl->options.side != WOLFSSL_CLIENT_END)
+#endif
+ {
+ wolfSSL_UnloadCertsKeys(ssl);
+ }
#endif
#ifdef HAVE_PK_CALLBACKS
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
@@ -8555,6 +9083,15 @@ void FreeHandshakeResources(WOLFSSL* ssl)
* !WOLFSSL_POST_HANDSHAKE_AUTH */
#endif /* HAVE_TLS_EXTENSIONS && !NO_TLS */
+#if defined(HAVE_OCSP)
+ {
+ size_t i;
+ for (i = 0; i < XELEM_CNT(ssl->ocspCsrResp); i++)
+ XFREE(ssl->ocspCsrResp[i].buffer, NULL, 0);
+ XMEMSET(ssl->ocspCsrResp, 0, sizeof(ssl->ocspCsrResp));
+ }
+#endif /* defined(HAVE_OCSP) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) */
+
#ifdef WOLFSSL_STATIC_MEMORY
/* when done with handshake decrement current handshake count */
if (ssl->heap != NULL) {
@@ -8566,14 +9103,20 @@ void FreeHandshakeResources(WOLFSSL* ssl)
WOLFSSL_HEAP* ctx_heap;
ctx_heap = ssl_hint->memory;
+ #ifndef SINGLE_THREADED
if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
}
+ #endif
+ #ifndef WOLFSSL_STATIC_MEMORY_LEAN
if (ctx_heap->curHa > 0) {
ctx_heap->curHa--;
}
ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */
+ #endif
+ #ifndef SINGLE_THREADED
wc_UnLockMutex(&(ctx_heap->memory_mutex));
+ #endif
#ifdef WOLFSSL_HEAP_TEST
}
#endif
@@ -8586,7 +9129,7 @@ void FreeHandshakeResources(WOLFSSL* ssl)
void FreeSSL(WOLFSSL* ssl, void* heap)
{
WOLFSSL_CTX* ctx = ssl->ctx;
- SSL_ResourceFree(ssl);
+ wolfSSL_ResourceFree(ssl);
XFREE(ssl, heap, DYNAMIC_TYPE_SSL);
if (ctx)
FreeSSL_Ctx(ctx); /* will decrement and free underlying CTX if 0 */
@@ -8773,8 +9316,7 @@ void DtlsMsgDelete(DtlsMsg* item, void* heap)
DtlsMsgDestroyFragBucket(item->fragBucketList, heap);
item->fragBucketList = next;
}
- if (item->raw != NULL)
- XFREE(item->raw, heap, DYNAMIC_TYPE_DTLS_FRAG);
+ XFREE(item->raw, heap, DYNAMIC_TYPE_DTLS_FRAG);
XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG);
}
}
@@ -8992,7 +9534,7 @@ static void DtlsMsgAssembleCompleteMessage(DtlsMsg* msg)
* alignment of char.
*/
dtls = (DtlsHandShakeHeader*)(void *)((char *)msg->fragBucketList
- + OFFSETOF(DtlsFragBucket,buf)
+ + WC_OFFSETOF(DtlsFragBucket,buf)
- DTLS_HANDSHAKE_HEADER_SZ);
msg->fragBucketList = NULL;
@@ -9411,7 +9953,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket)
WriteSEQ(ssl, epochOrder, dtls->sequence_number);
DtlsSEQIncrement(ssl, epochOrder);
- if ((ret = CheckAvailableSize(ssl, pool->sz)) != 0) {
+ if ((ret = CheckAvailableSize(ssl, (int)pool->sz)) != 0) {
WOLFSSL_ERROR(ret);
return ret;
}
@@ -9426,7 +9968,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket)
int inputSz, sendSz;
input = pool->raw;
- inputSz = pool->sz;
+ inputSz = (int)pool->sz;
sendSz = inputSz + cipherExtraData(ssl);
#ifdef HAVE_SECURE_RENEGOTIATION
@@ -9690,7 +10232,12 @@ ProtocolVersion MakeDTLSv1_3(void)
#elif defined(FREERTOS)
- #include "task.h"
+ #ifdef PLATFORMIO
+ #include
+ #include
+ #else
+ #include "task.h"
+ #endif
unsigned int LowResTimer(void)
{
@@ -9772,7 +10319,12 @@ ProtocolVersion MakeDTLSv1_3(void)
word32 LowResTimer(void)
{
- return k_uptime_get() / 1000;
+ int64_t t;
+ #if defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_BOARD_NATIVE_POSIX)
+ k_cpu_idle();
+ #endif
+ t = k_uptime_get(); /* returns current uptime in milliseconds */
+ return (word32)(t / 1000);
}
#elif defined(WOLFSSL_LINUXKM)
@@ -9802,6 +10354,8 @@ ProtocolVersion MakeDTLSv1_3(void)
*/
#endif /* !NO_ASN_TIME */
+
+#ifndef NO_TLS
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
((defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)) || \
(defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
@@ -9865,22 +10419,22 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz)
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
ret = tsip_StoreMessage(ssl, data, sz);
- if (ret != 0 && ret != CRYPTOCB_UNAVAILABLE) {
+ if (ret != 0 && ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
return ret;
}
#endif /* WOLFSSL_RENESAS_TSIP_TLS */
#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \
defined(WOLFSSL_ALLOW_TLS_SHA1))
- wc_ShaUpdate(&ssl->hsHashes->hashSha, data, sz);
+ wc_ShaUpdate(&ssl->hsHashes->hashSha, data, (word32)(sz));
#endif
#if !defined(NO_MD5) && !defined(NO_OLD_TLS)
- wc_Md5Update(&ssl->hsHashes->hashMd5, data, sz);
+ wc_Md5Update(&ssl->hsHashes->hashMd5, data, (word32)(sz));
#endif
if (IsAtLeastTLSv1_2(ssl)) {
#ifndef NO_SHA256
- ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, data, sz);
+ ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, data, (word32)sz);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
@@ -9890,7 +10444,7 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz)
#endif
#endif
#ifdef WOLFSSL_SHA384
- ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, data, sz);
+ ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, data, (word32)sz);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
@@ -9900,7 +10454,7 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz)
#endif
#endif
#ifdef WOLFSSL_SHA512
- ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, data, sz);
+ ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, data, (word32)sz);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
@@ -9937,7 +10491,7 @@ int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
{
const byte* adj;
- if (ssl->hsHashes == NULL)
+ if ((ssl->hsHashes == NULL) || (output == NULL))
return BAD_FUNC_ARG;
adj = output + RECORD_HEADER_SZ + ivSz;
@@ -9959,6 +10513,13 @@ int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz)
sz -= dtls_record_extra;
#endif /* WOLFSSL_DTLS13 */
} else {
+#ifdef WOLFSSL_DTLS_CID
+ byte cidSz = DtlsGetCidTxSize(ssl);
+ if (IsEncryptionOn(ssl, 1) && cidSz > 0) {
+ adj += cidSz;
+ sz -= cidSz + 1; /* +1 to not hash the real content type */
+ }
+#endif
adj += DTLS_RECORD_EXTRA;
sz -= DTLS_RECORD_EXTRA;
}
@@ -9999,7 +10560,8 @@ int HashInput(WOLFSSL* ssl, const byte* input, int sz)
/* add record layer header for message */
-static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl, int epochOrder)
+static void AddRecordHeader(byte* output, word32 length, byte type,
+ WOLFSSL* ssl, int epochOrder)
{
RecordLayerHeader* rl;
@@ -10038,12 +10600,18 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl
}
else {
#ifdef WOLFSSL_DTLS
- DtlsRecordLayerHeader* dtls;
-
/* dtls record layer header extensions */
- dtls = (DtlsRecordLayerHeader*)output;
+ DtlsRecordLayerHeader* dtls = (DtlsRecordLayerHeader*)output;
+#ifdef WOLFSSL_DTLS_CID
+ byte cidSz = 0;
+ if (type == dtls12_cid && (cidSz = DtlsGetCidTxSize(ssl)) > 0) {
+ wolfSSL_dtls_cid_get_tx(ssl, output + DTLS12_CID_OFFSET, cidSz);
+ c16toa((word16)length, output + DTLS12_CID_OFFSET + cidSz);
+ }
+ else
+#endif
+ c16toa((word16)length, dtls->length);
WriteSEQ(ssl, epochOrder, dtls->sequence_number);
- c16toa((word16)length, dtls->length);
#endif
}
}
@@ -10066,8 +10634,11 @@ static void AddHandShakeHeader(byte* output, word32 length,
if (hs == NULL)
return;
+ PRAGMA_GCC_DIAG_PUSH;
+ PRAGMA_GCC("GCC diagnostic ignored \"-Wnull-dereference\"");
hs->type = type;
c32to24(length, hs->length); /* type and length same for each */
+ PRAGMA_GCC_DIAG_POP;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
DtlsHandShakeHeader* dtls;
@@ -10145,6 +10716,8 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
int maxFrag;
int ret = 0;
int headerSz;
+ int rHdrSz = 0; /* record header size */
+ int hsHdrSz = 0; /* handshake header size */
WOLFSSL_ENTER("SendHandshakeMsg");
(void)type;
@@ -10153,8 +10726,10 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
if (ssl == NULL || input == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls)
- headerSz = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
+ if (ssl->options.dtls) {
+ rHdrSz = DTLS_RECORD_HEADER_SZ;
+ hsHdrSz = DTLS_HANDSHAKE_HEADER_SZ;
+ }
else
#endif
{
@@ -10162,7 +10737,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
* per fragment like in DTLS. The handshake header should
* already be in the input buffer. */
inputSz += HANDSHAKE_HEADER_SZ;
- headerSz = RECORD_HEADER_SZ;
+ rHdrSz = RECORD_HEADER_SZ;
}
maxFrag = wolfSSL_GetMaxFragSize(ssl, (int)inputSz);
@@ -10177,7 +10752,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
if (!ssl->options.buildingMsg) {
/* Hash it before the loop as we modify the input with
* encryption on */
- ret = HashOutput(ssl, input, headerSz + (int)inputSz, 0);
+ ret = HashRaw(ssl, input + rHdrSz, (int)(inputSz) + hsHdrSz);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DTLS
@@ -10187,6 +10762,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
ssl->keys.dtls_handshake_number--;
#endif
}
+ headerSz = rHdrSz + hsHdrSz;
while (ssl->fragOffset < inputSz) {
byte* output;
int outputSz;
@@ -10199,7 +10775,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
fragSz = inputSz - ssl->fragOffset;
/* check for available size */
- outputSz = headerSz + fragSz;
+ outputSz = headerSz + (int)fragSz;
if (IsEncryptionOn(ssl, 1))
outputSz += cipherExtraData(ssl);
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
@@ -10257,7 +10833,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
}
#endif
}
- ssl->buffers.outputBuffer.length += outputSz;
+ ssl->buffers.outputBuffer.length += (word32)outputSz;
#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
if (ssl->hsInfoOn) {
AddPacketName(ssl, packetName);
@@ -10290,12 +10866,16 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
#endif /* !WOLFSSL_NO_TLS12 */
-/* return bytes received, -1 on error */
+/* return bytes received, WOLFSSL_FATAL_ERROR on error,
+ * or BAD_FUNC_ARG if ssl is null */
static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
{
int recvd;
int retryLimit = WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS;
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
#ifdef WOLFSSL_QUIC
if (WOLFSSL_IS_QUIC(ssl)) {
/* QUIC only "reads" from data provided by the application
@@ -10307,14 +10887,14 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
if (ssl->CBIORecv == NULL) {
WOLFSSL_MSG("Your IO Recv callback is null, please set");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
retry:
recvd = ssl->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx);
if (recvd < 0) {
switch (recvd) {
- case WOLFSSL_CBIO_ERR_GENERAL: /* general/unknown error */
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_GENERAL):
#ifdef WOLFSSL_APACHE_HTTPD
#ifndef NO_BIO
if (ssl->biord) {
@@ -10326,26 +10906,26 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
}
#endif
#endif
- return -1;
+ return WOLFSSL_FATAL_ERROR;
- case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ):
if (retryLimit > 0 && ssl->ctx->autoRetry &&
!ssl->options.handShakeDone && !ssl->options.dtls) {
retryLimit--;
goto retry;
}
- return WANT_READ;
+ return WC_NO_ERR_TRACE(WANT_READ);
- case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_CONN_RST):
#ifdef USE_WINDOWS_API
if (ssl->options.dtls) {
goto retry;
}
#endif
ssl->options.connReset = 1;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
- case WOLFSSL_CBIO_ERR_ISR: /* interrupt */
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_ISR): /* interrupt */
/* see if we got our timeout */
#ifdef WOLFSSL_CALLBACKS
if (ssl->toInfoOn) {
@@ -10363,13 +10943,13 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
}
}
#endif
- goto retry;
+ return WOLFSSL_FATAL_ERROR;
- case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* peer closed connection */
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_CONN_CLOSE):
ssl->options.isClosed = 1;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
- case WOLFSSL_CBIO_ERR_TIMEOUT:
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_TIMEOUT):
#ifdef WOLFSSL_DTLS
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
@@ -10377,7 +10957,7 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
if (Dtls13RtxTimeout(ssl) < 0) {
WOLFSSL_MSG(
"Error trying to retransmit DTLS buffered message");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
goto retry;
}
@@ -10392,7 +10972,7 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz)
goto retry;
}
#endif
- return -1;
+ return WOLFSSL_FATAL_ERROR;
default:
WOLFSSL_MSG("Unexpected recv return code");
@@ -10425,8 +11005,8 @@ void ShrinkOutputBuffer(WOLFSSL* ssl)
* calls ShrinkInputBuffer itself when it is safe to do so. Don't overuse it. */
void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
{
- int usedLength = ssl->buffers.inputBuffer.length -
- ssl->buffers.inputBuffer.idx;
+ int usedLength = (int)(ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx);
if (!forcedFree && (usedLength > STATIC_BUFFER_LEN ||
ssl->buffers.clearOutputBuffer.length > 0))
return;
@@ -10436,11 +11016,11 @@ void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
if (!forcedFree && usedLength > 0) {
XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
- usedLength);
+ (size_t)(usedLength));
}
ForceZero(ssl->buffers.inputBuffer.buffer,
- ssl->buffers.inputBuffer.length);
+ ssl->buffers.inputBuffer.bufferSize);
XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset,
ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
@@ -10448,13 +11028,18 @@ void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree)
ssl->buffers.inputBuffer.dynamicFlag = 0;
ssl->buffers.inputBuffer.offset = 0;
ssl->buffers.inputBuffer.idx = 0;
- ssl->buffers.inputBuffer.length = usedLength;
+ ssl->buffers.inputBuffer.length = (word32)usedLength;
}
int SendBuffered(WOLFSSL* ssl)
{
int retryLimit = WOLFSSL_MODE_AUTO_RETRY_ATTEMPTS;
+ if (ssl == NULL) {
+ WOLFSSL_MSG("ssl is null");
+ return BAD_FUNC_ARG;
+ }
+
if (ssl->CBIOSend == NULL && !WOLFSSL_IS_QUIC(ssl)) {
WOLFSSL_MSG("Your IO Send callback is null, please set");
return SOCKET_ERROR_E;
@@ -10485,19 +11070,19 @@ int SendBuffered(WOLFSSL* ssl)
if (sent < 0) {
switch (sent) {
- case WOLFSSL_CBIO_ERR_WANT_WRITE: /* would block */
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_WRITE):
if (retryLimit > 0 && ssl->ctx->autoRetry &&
!ssl->options.handShakeDone && !ssl->options.dtls) {
retryLimit--;
goto retry;
}
- return WANT_WRITE;
+ return WC_NO_ERR_TRACE(WANT_WRITE);
- case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_CONN_RST):
ssl->options.connReset = 1;
break;
- case WOLFSSL_CBIO_ERR_ISR: /* interrupt */
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_ISR): /* interrupt */
/* see if we got our timeout */
#ifdef WOLFSSL_CALLBACKS
if (ssl->toInfoOn) {
@@ -10517,7 +11102,7 @@ int SendBuffered(WOLFSSL* ssl)
#endif
continue;
- case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* epipe / conn closed */
+ case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_CONN_CLOSE): /* epipe */
ssl->options.connReset = 1; /* treat same as reset */
break;
@@ -10533,8 +11118,8 @@ int SendBuffered(WOLFSSL* ssl)
return SEND_OOB_READ_E;
}
- ssl->buffers.outputBuffer.idx += sent;
- ssl->buffers.outputBuffer.length -= sent;
+ ssl->buffers.outputBuffer.idx += (word32)sent;
+ ssl->buffers.outputBuffer.length -= (word32)sent;
}
ssl->buffers.outputBuffer.idx = 0;
@@ -10545,6 +11130,69 @@ int SendBuffered(WOLFSSL* ssl)
return 0;
}
+#ifdef WOLFSSL_THREADED_CRYPT
+static WC_INLINE int GrowAnOutputBuffer(WOLFSSL* ssl,
+ bufferStatic* outputBuffer, int size)
+{
+ byte* tmp;
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+ byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ :
+ RECORD_HEADER_SZ;
+ byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#else
+ const byte align = WOLFSSL_GENERAL_ALIGNMENT;
+#endif
+
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+ /* the encrypted data will be offset from the front of the buffer by
+ the header, if the user wants encrypted alignment they need
+ to define their alignment requirement */
+
+ while (align < hdrSz)
+ align *= 2;
+#endif
+
+ tmp = (byte*)XMALLOC(size + outputBuffer->length + align,
+ ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+ WOLFSSL_MSG("growing output buffer");
+
+ if (tmp == NULL)
+ return MEMORY_E;
+
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+ if (align)
+ tmp += align - hdrSz;
+#endif
+
+#ifdef WOLFSSL_STATIC_MEMORY
+ /* can be from IO memory pool which does not need copy if same buffer */
+ if (outputBuffer->length && tmp == outputBuffer->buffer) {
+ outputBuffer->bufferSize = size + outputBuffer->length;
+ return 0;
+ }
+#endif
+
+ if (outputBuffer->length)
+ XMEMCPY(tmp, outputBuffer->buffer, outputBuffer->length);
+
+ if (outputBuffer->dynamicFlag) {
+ XFREE(outputBuffer->buffer - outputBuffer->offset, ssl->heap,
+ DYNAMIC_TYPE_OUT_BUFFER);
+ }
+
+#if WOLFSSL_GENERAL_ALIGNMENT > 0
+ if (align)
+ outputBuffer->offset = align - hdrSz;
+ else
+#endif
+ outputBuffer->offset = 0;
+
+ outputBuffer->buffer = tmp;
+ outputBuffer->dynamicFlag = 1;
+ outputBuffer->bufferSize = size + outputBuffer->length;
+ return 0;
+}
+#endif
/* returns the current location in the output buffer to start writing to */
byte* GetOutputBuffer(WOLFSSL* ssl)
@@ -10565,8 +11213,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 = 0;
#if WOLFSSL_GENERAL_ALIGNMENT > 0
/* the encrypted data will be offset from the front of the buffer by
@@ -10577,7 +11224,17 @@ 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 WOLFSSL_GENERAL_ALIGNMENT > 0
+ if (! WC_SAFE_SUM_WORD32(newSz, align, newSz))
+ return BUFFER_E;
+#endif
+ tmp = (byte*)XMALLOC(newSz, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+ newSz -= align;
WOLFSSL_MSG("growing output buffer");
if (tmp == NULL)
@@ -10650,7 +11307,7 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
return BAD_FUNC_ARG;
}
- tmp = (byte*)XMALLOC(size + usedLength + align,
+ tmp = (byte*)XMALLOC((size_t)(size + usedLength + align),
ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
WOLFSSL_MSG("growing input buffer");
@@ -10674,7 +11331,7 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
if (usedLength)
XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
- ssl->buffers.inputBuffer.idx, usedLength);
+ ssl->buffers.inputBuffer.idx, (size_t)(usedLength));
if (ssl->buffers.inputBuffer.dynamicFlag) {
if (IsEncryptionOn(ssl, 1)) {
@@ -10694,9 +11351,9 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength)
ssl->buffers.inputBuffer.offset = 0;
ssl->buffers.inputBuffer.buffer = tmp;
- ssl->buffers.inputBuffer.bufferSize = size + usedLength;
+ ssl->buffers.inputBuffer.bufferSize = (word32)(size + usedLength);
ssl->buffers.inputBuffer.idx = 0;
- ssl->buffers.inputBuffer.length = usedLength;
+ ssl->buffers.inputBuffer.length = (word32)usedLength;
return 0;
}
@@ -10755,6 +11412,10 @@ int CheckAvailableSize(WOLFSSL *ssl, int size)
int MsgCheckEncryption(WOLFSSL* ssl, byte type, byte encrypted)
{
+ if (ssl == NULL) {
+ WOLFSSL_MSG("ssl is null");
+ return BAD_FUNC_ARG;
+ }
#ifdef WOLFSSL_QUIC
/* QUIC protects messages outside of the TLS scope */
if (WOLFSSL_IS_QUIC(ssl) && IsAtLeastTLSv1_3(ssl->version))
@@ -10861,13 +11522,8 @@ int MsgCheckEncryption(WOLFSSL* ssl, byte type, byte encrypted)
static WC_INLINE int isLastMsg(const WOLFSSL* ssl, word32 msgSz)
{
word32 extra = 0;
- if (IsEncryptionOn(ssl, 0)) {
+ if (IsEncryptionOn(ssl, 0))
extra = ssl->keys.padSz;
-#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- extra += MacSize(ssl);
-#endif
- }
return (ssl->buffers.inputBuffer.idx - ssl->curStartIdx) + msgSz + extra
== ssl->curSize;
}
@@ -10989,6 +11645,33 @@ static int MsgCheckBoundary(const WOLFSSL* ssl, byte type,
#endif /* WOLFSSL_DISABLE_EARLY_SANITY_CHECKS */
+/* Extract the handshake header information.
+ *
+ * ssl The SSL/TLS object.
+ * input The buffer holding the message data.
+ * inOutIdx On entry, the index into the buffer of the handshake data.
+ * On exit, the start of the handshake data.
+ * type Type of handshake message.
+ * size The length of the handshake message data.
+ * totalSz The total size of data in the buffer.
+ * returns BUFFER_E if there is not enough input data and 0 on success.
+ */
+int GetHandshakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
+ byte* type, word32* size, word32 totalSz)
+{
+ const byte* ptr = input + *inOutIdx;
+ (void)ssl;
+
+ *inOutIdx += HANDSHAKE_HEADER_SZ;
+ if (*inOutIdx > totalSz)
+ return BUFFER_E;
+
+ *type = ptr[0];
+ c24to32(&ptr[1], size);
+
+ return 0;
+}
+
/**
* This check is performed as soon as the handshake message type becomes known.
* These checks can not be delayed and need to be performed when the msg is
@@ -11000,7 +11683,7 @@ static int MsgCheckBoundary(const WOLFSSL* ssl, byte type,
* @param ssl The current connection
* @param type The enum HandShakeType of the current message
* @param msgSz Size of the current message
- * @return
+ * @return int (less than 0 on fail, 0 on success)
*/
int EarlySanityCheckMsgReceived(WOLFSSL* ssl, byte type, word32 msgSz)
{
@@ -11035,6 +11718,18 @@ int EarlySanityCheckMsgReceived(WOLFSSL* ssl, byte type, word32 msgSz)
return ret;
}
+static int RecordsCanSpanReads(WOLFSSL *ssl)
+{
+#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS)
+ /* Only case where we return 0: DTLS mode (not SCTP) and can't span datagrams */
+ if (IsDtlsNotSctpMode(ssl)) {
+ return 0;
+ }
+#endif
+ (void)ssl;
+ return 1;
+}
+
#ifdef WOLFSSL_DTLS13
static int GetInputData(WOLFSSL *ssl, word32 size);
static int GetDtls13RecordHeader(WOLFSSL* ssl, word32* inOutIdx,
@@ -11088,7 +11783,16 @@ static int GetDtls13RecordHeader(WOLFSSL* ssl, word32* inOutIdx,
if (ret != 0)
return ret;
+ if (ssl->dtls13CurRlLength > sizeof(ssl->dtls13CurRL)) {
+ WOLFSSL_MSG("Record header too long");
+ return SEQUENCE_ERROR;
+ }
+
if (readSize < ssl->dtls13CurRlLength + DTLS13_RN_MASK_SIZE) {
+ if (!RecordsCanSpanReads(ssl)) {
+ WOLFSSL_MSG("Partial record received");
+ return DTLS_PARTIAL_RECORD_READ;
+ }
/* when using DTLS over a medium that does not guarantee that a full
* message is received in a single read, we may end up without the full
* header and minimum ciphertext to decrypt record sequence numbers */
@@ -11140,6 +11844,9 @@ static int GetDtls13RecordHeader(WOLFSSL* ssl, word32* inOutIdx,
static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
RecordLayerHeader* rh, word16* size)
{
+#ifdef WOLFSSL_DTLS_CID
+ byte cidSz = 0;
+#endif
#ifdef HAVE_FUZZER
if (ssl->fuzzerCb)
@@ -11156,7 +11863,9 @@ static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
/* version 1.3 already negotiated */
if (ssl->options.tls1_3) {
ret = GetDtls13RecordHeader(ssl, inOutIdx, rh, size);
- if (ret == 0 || ret != SEQUENCE_ERROR || ret != DTLS_CID_ERROR)
+ if (ret == 0 ||
+ ((ret != WC_NO_ERR_TRACE(SEQUENCE_ERROR)) &&
+ (ret != WC_NO_ERR_TRACE(DTLS_CID_ERROR))))
return ret;
}
@@ -11176,9 +11885,13 @@ static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
/* not a unified header, check that we have at least
* DTLS_RECORD_HEADER_SZ */
if (ssl->buffers.inputBuffer.length - *inOutIdx < DTLS_RECORD_HEADER_SZ) {
+ if (!RecordsCanSpanReads(ssl)) {
+ WOLFSSL_MSG("Partial record received");
+ return DTLS_PARTIAL_RECORD_READ;
+ }
ret = GetInputData(ssl, DTLS_RECORD_HEADER_SZ);
/* Check if Dtls13RtxTimeout(ssl) returned socket error */
- if (ret == SOCKET_ERROR_E)
+ if (ret == WC_NO_ERR_TRACE(SOCKET_ERROR_E))
return ret;
if (ret != 0)
return LENGTH_ERROR;
@@ -11191,6 +11904,15 @@ static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
*inOutIdx += ENUM_LEN + VERSION_SZ;
ato16(ssl->buffers.inputBuffer.buffer + *inOutIdx, &ssl->keys.curEpoch);
+ if (rh->pvMajor == DTLS_MAJOR && rh->pvMinor == DTLS_BOGUS_MINOR) {
+ return SEQUENCE_ERROR;
+ }
+
+#ifdef WOLFSSL_DTLS_CID
+ if (rh->type == dtls12_cid && (cidSz = DtlsGetCidRxSize(ssl)) == 0)
+ return DTLS_CID_ERROR;
+#endif
+
#ifdef WOLFSSL_DTLS13
/* only non protected message can use the DTLSPlaintext record header */
if (IsAtLeastTLSv1_3(ssl->version)) {
@@ -11222,6 +11944,20 @@ static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
ssl->keys.curSeq = w64From32(ssl->keys.curSeq_hi, ssl->keys.curSeq_lo);
#endif /* WOLFSSL_DTLS13 */
+#ifdef WOLFSSL_DTLS_CID
+ if (rh->type == dtls12_cid) {
+ byte* ourCid = NULL;
+ if (ssl->buffers.inputBuffer.length - *inOutIdx <
+ (word32)cidSz + LENGTH_SZ)
+ return LENGTH_ERROR;
+ if (wolfSSL_dtls_cid_get0_rx(ssl, &ourCid) != WOLFSSL_SUCCESS)
+ return DTLS_CID_ERROR;
+ if (XMEMCMP(ssl->buffers.inputBuffer.buffer + *inOutIdx, ourCid, cidSz)
+ != 0)
+ return DTLS_CID_ERROR;
+ *inOutIdx += cidSz;
+ }
+#endif
ato16(ssl->buffers.inputBuffer.buffer + *inOutIdx, size);
*inOutIdx += LENGTH_SZ;
@@ -11247,7 +11983,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);
}
@@ -11263,8 +12005,12 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
/* DTLSv1.3 MUST check window after deprotecting to avoid timing channel
(RFC9147 Section 4.5.1) */
if (IsDtlsNotSctpMode(ssl) && !IsAtLeastTLSv1_3(ssl->version)) {
+ byte needsEnc = rh->type == application_data; /* can't be epoch 0 */
+#ifdef WOLFSSL_DTLS_CID
+ needsEnc = needsEnc || rh->type == dtls12_cid;
+#endif
if (!_DtlsCheckWindow(ssl) ||
- (rh->type == application_data && ssl->keys.curEpoch == 0) ||
+ (needsEnc && ssl->keys.curEpoch == 0) ||
(rh->type == alert && ssl->options.handShakeDone &&
ssl->keys.curEpoch == 0 && ssl->keys.dtls_epoch != 0)) {
WOLFSSL_LEAVE("GetRecordHeader()", SEQUENCE_ERROR);
@@ -11310,7 +12056,20 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
}
}
#endif /* WOLFSSL_DTLS13 */
- else {
+ /* Don't care about protocol version being lower than expected on alerts
+ * sent back before version negotiation. */
+ else if (!(ssl->options.side == WOLFSSL_CLIENT_END &&
+ ssl->options.connectState == CLIENT_HELLO_SENT &&
+ rh->type == alert &&
+ rh->pvMajor == ssl->version.major &&
+ #ifdef WOLFSSL_DTLS
+ ((ssl->options.dtls && rh->pvMinor == DTLS_MINOR) ||
+ (!ssl->options.dtls &&
+ rh->pvMinor < ssl->version.minor))
+ #else
+ (rh->pvMinor < ssl->version.minor)
+ #endif
+ )) {
WOLFSSL_MSG("SSL version error");
WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
return VERSION_ERROR; /* only use requested version */
@@ -11342,6 +12101,9 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
case change_cipher_spec:
case application_data:
case alert:
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ case dtls12_cid:
+#endif
#ifdef WOLFSSL_DTLS13
case ack:
#endif /* WOLFSSL_DTLS13 */
@@ -11375,24 +12137,6 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
return 0;
}
-#ifndef WOLFSSL_NO_TLS12
-static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
- byte *type, word32 *size, word32 totalSz)
-{
- const byte *ptr = input + *inOutIdx;
- (void)ssl;
-
- *inOutIdx += HANDSHAKE_HEADER_SZ;
- if (*inOutIdx > totalSz)
- return BUFFER_E;
-
- *type = ptr[0];
- c24to32(&ptr[1], size);
-
- return 0;
-}
-#endif
-
#ifdef WOLFSSL_DTLS
int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, byte *type, word32 *size,
@@ -11401,7 +12145,7 @@ int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
{
word32 idx = *inOutIdx;
- *inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA;
+ *inOutIdx += DTLS_HANDSHAKE_HEADER_SZ;
if (*inOutIdx > totalSz) {
WOLFSSL_ERROR(BUFFER_E);
return BUFFER_E;
@@ -11501,9 +12245,7 @@ static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
}
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#endif
+ WC_FREE_VAR_EX(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
return ret;
}
@@ -11547,9 +12289,7 @@ static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
}
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#endif
+ WC_FREE_VAR_EX(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
return ret;
}
@@ -11565,14 +12305,9 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (ssl == NULL)
return BAD_FUNC_ARG;
-#ifndef NO_TLS
if (ssl->options.tls) {
ret = BuildTlsFinished(ssl, hashes, sender);
}
-#else
- (void)hashes;
- (void)sender;
-#endif
#ifndef NO_OLD_TLS
if (!ssl->options.tls) {
ret = BuildMD5(ssl, hashes, sender);
@@ -11596,6 +12331,8 @@ int CipherRequires(byte first, byte second, int requirement)
{
(void)requirement;
+ (void)first;
+ (void)second;
#ifndef WOLFSSL_NO_TLS12
@@ -12237,63 +12974,141 @@ int CipherRequires(byte first, byte second, int requirement)
}
#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */
-
+#endif /* !NO_TLS */
#ifndef NO_CERTS
+#if defined(WOLFSSL_IP_ALT_NAME) && !defined(WOLFSSL_USER_IO)
+static int MatchIPv6(const char* pattern, int patternLen,
+ const char* str, word32 strLen)
+{
+ WOLFSSL_SOCKADDR_IN6 addr1, addr2;
+ char patBuf[WOLFSSL_MAX_IPSTR];
+ char strBuf[WOLFSSL_MAX_IPSTR];
+
+ if ((word32)patternLen >= sizeof(patBuf) || strLen >= sizeof(strBuf))
+ return 0;
+
+ /* Make sure strings are null-terminated and safely copied */
+ XMEMCPY(patBuf, pattern, patternLen);
+ patBuf[patternLen] = '\0';
+ XMEMCPY(strBuf, str, strLen);
+ strBuf[strLen] = '\0';
+
+ XMEMSET(&addr1, 0, sizeof(addr1));
+ XMEMSET(&addr2, 0, sizeof(addr2));
+ /* Try parsing both as IPv6 */
+ if (XINET_PTON(WOLFSSL_IP6, patBuf, &addr1) != 1)
+ return 0;
+ if (XINET_PTON(WOLFSSL_IP6, strBuf, &addr2) != 1)
+ return 0;
+
+ /* Compare raw address bytes */
+ return XMEMCMP(&addr1, &addr2, sizeof(WOLFSSL_SOCKADDR_IN6)) == 0;
+}
+#endif /* WOLFSSL_IP_ALT_NAME && !WOLFSSL_USER_IO */
/* Match names with wildcards, each wildcard can represent a single name
component or fragment but not multiple names, i.e.,
*.z.com matches y.z.com but not x.y.z.com
+ If flags contains WOLFSSL_LEFT_MOST_WILDCARD_ONLY, wildcard only applies
+ to left-most name component, compatible with RFC 2830 identity checking.
+
return 1 on success */
-int MatchDomainName(const char* pattern, int len, const char* str)
+int MatchDomainName(const char* pattern, int patternLen, const char* str,
+ word32 strLen, unsigned int flags)
{
int ret = 0;
+ byte wildcardEligible = 1;
+ byte leftWildcardOnly = flags & WOLFSSL_LEFT_MOST_WILDCARD_ONLY;
- if (pattern == NULL || str == NULL || len <= 0)
+ if (pattern == NULL || str == NULL || patternLen <= 0 || strLen == 0)
return 0;
- while (len > 0) {
+#if defined(WOLFSSL_IP_ALT_NAME) && !defined(WOLFSSL_USER_IO)
+ /* First try to match IPv6 addresses */
+ if (MatchIPv6(pattern, patternLen, str, strLen))
+ return 1;
+#endif
- char p = (char)XTOLOWER((unsigned char)*pattern++);
+ while (patternLen > 0) {
+ /* Get the next pattern char to evaluate */
+ char p = (char)XTOLOWER((unsigned char)*pattern);
if (p == '\0')
break;
- if (p == '*') {
+ pattern++;
+
+ if ((p == '*') && wildcardEligible) {
char s;
+ /* We will always match '*' */
+ patternLen--;
- while (--len > 0) {
+ /* Only single wildcard allowed with strict left only */
+ if (leftWildcardOnly) {
+ wildcardEligible = 0;
+ }
+
+ /* Consume any extra '*' chars until the next non '*' char. */
+ while (patternLen > 0) {
p = (char)XTOLOWER((unsigned char)*pattern);
pattern++;
+ if (p == '\0' && patternLen > 0)
+ return 0;
if (p != '*')
break;
+ if (leftWildcardOnly && (p == '*')) {
+ /* RFC2830 only allows single left-most wildcard */
+ return 0;
+ }
+
+ patternLen--;
}
- if (len == 0)
- p = '\0';
+ /* Consume str until we reach next char in pattern after '*' or
+ * end of string */
+ while (strLen > 0) {
+ s = (char)XTOLOWER((unsigned char) *str);
+ str++;
+ strLen--;
+
+ /* p is next char in pattern after '*', or '*' if '*' is the
+ * last char in the pattern (in which case patternLen is 1) */
+ if ( ((s == p) && (patternLen > 0))) {
+ /* We had already counted the '*' as matched, this means
+ * we also matched the next non '*' char in pattern */
+ patternLen--;
+ break;
+ }
- while ( (s = (char)XTOLOWER((unsigned char) *str)) != '\0') {
- if (s == p)
+ /* If strlen is 0, we have consumed the entire string. Count that
+ * as a match of '*' */
+ if (strLen == 0) {
break;
+ }
+
if (s == '.')
return 0;
- str++;
}
}
else {
+ /* Past left-most wildcard location, not eligible if flag set*/
+ if (leftWildcardOnly && wildcardEligible) {
+ wildcardEligible = 0;
+ }
+
+ /* Simple case, pattern match exactly */
if (p != (char)XTOLOWER((unsigned char) *str))
return 0;
- }
-
- if (len > 0) {
str++;
- len--;
+ strLen--;
+ patternLen--;
}
}
- if (*str == '\0' && len == 0) {
+ if (strLen == 0 && patternLen == 0) {
ret = 1; /* success */
}
@@ -12305,14 +13120,18 @@ int MatchDomainName(const char* pattern, int len, const char* str)
* Fail if there are wild patterns and they didn't match.
* Check the common name if no alternative names matched.
*
- * dCert Decoded cert to get the alternative names from.
- * domain Domain name to compare against.
- * checkCN Whether to check the common name.
- * returns 1 : match was found.
- * 0 : no match found.
- * -1 : No matches and wild pattern match failed.
+ * dCert Decoded cert to get the alternative names from.
+ * domain Domain name to compare against.
+ * domainLen Length of the domain name.
+ * checkCN Whether to check the common name.
+ * flags Matching flags.
+ * isIP Whether the domain is an IP address.
+ * returns 1 : match was found.
+ * 0 : no match found.
+ * -1 : No matches and wild pattern match failed.
*/
-int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN)
+int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen,
+ int* checkCN, unsigned int flags, byte isIP)
{
int match = 0;
DNS_entry* altName = NULL;
@@ -12321,29 +13140,34 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN)
WOLFSSL_MSG("Checking AltNames");
- if (dCert)
+ if (dCert != NULL)
altName = dCert->altNames;
- if (checkCN != NULL) {
+ if (checkCN != NULL)
*checkCN = (altName == NULL) ? 1 : 0;
- }
- while (altName) {
+ for (; altName != NULL; altName = altName->next) {
WOLFSSL_MSG("\tindividual AltName check");
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME)
+#ifdef WOLFSSL_IP_ALT_NAME
if (altName->type == ASN_IP_TYPE) {
buf = altName->ipString;
len = (word32)XSTRLEN(buf);
}
else
-#endif /* OPENSSL_ALL || WOLFSSL_IP_ALT_NAME */
+#endif /* WOLFSSL_IP_ALT_NAME */
{
buf = altName->name;
- len = altName->len;
+ len = (word32)altName->len;
+ }
+
+ if ((isIP && (altName->type != ASN_IP_TYPE)) ||
+ (!isIP && (altName->type == ASN_IP_TYPE))) {
+ WOLFSSL_MSG("\tAltName type mismatch, continue");
+ continue;
}
- if (MatchDomainName(buf, len, domain)) {
+ if (MatchDomainName(buf, (int)len, domain, domainLen, flags)) {
match = 1;
if (checkCN != NULL) {
*checkCN = 0;
@@ -12356,8 +13180,6 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN)
match = -1;
WOLFSSL_MSG("\twildcard match failed");
}
-
- altName = altName->next;
}
return match;
@@ -12370,17 +13192,19 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN)
* dcert Decoded certificate.
* domainName The domain name.
* domainNameLen The length of the domain name.
+ * flags Matching flags.
+ * isIP Whether the domain name is an IP address.
* returns DOMAIN_NAME_MISMATCH when no match found and 0 on success.
*/
-int CheckHostName(DecodedCert* dCert, const char *domainName, size_t domainNameLen)
+int CheckHostName(DecodedCert* dCert, const char *domainName,
+ size_t domainNameLen, unsigned int flags, byte isIP)
{
int checkCN;
- int ret = DOMAIN_NAME_MISMATCH;
-
- /* Assume name is NUL terminated. */
- (void)domainNameLen;
+ int ret = WC_NO_ERR_TRACE(DOMAIN_NAME_MISMATCH);
- if (CheckForAltNames(dCert, domainName, &checkCN) != 1) {
+ if (CheckForAltNames(dCert, domainName, (word32)domainNameLen,
+ &checkCN, flags, isIP) != 1) {
+ ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_MSG("DomainName match on alt names failed");
}
else {
@@ -12390,10 +13214,11 @@ int CheckHostName(DecodedCert* dCert, const char *domainName, size_t domainNameL
#ifndef WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY
if (checkCN == 1) {
if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen,
- domainName) == 1) {
+ domainName, (word32)domainNameLen, flags) == 1) {
ret = 0;
}
else {
+ ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_MSG("DomainName match on common name failed");
}
}
@@ -12406,7 +13231,7 @@ int CheckIPAddr(DecodedCert* dCert, const char* ipasc)
{
WOLFSSL_MSG("Checking IPAddr");
- return CheckHostName(dCert, ipasc, (size_t)XSTRLEN(ipasc));
+ return CheckHostName(dCert, ipasc, (size_t)XSTRLEN(ipasc), 0, 1);
}
@@ -12416,7 +13241,7 @@ static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
{
if (chain->count < MAX_CHAIN_DEPTH &&
certSz < MAX_X509_SIZE) {
- chain->certs[chain->count].length = certSz;
+ chain->certs[chain->count].length = (int)certSz;
XMEMCPY(chain->certs[chain->count].buffer, certBuf, certSz);
chain->count++;
}
@@ -12426,17 +13251,63 @@ static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain,
}
#endif
+#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
+ defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+ defined(WOLFSSL_ACERT)
+ static int CopyAltNames(DNS_entry** to, DNS_entry* from, int type, void* heap)
+{
+ /* Copy from to the beginning of to */
+ DNS_entry** prev_next = to;
+ DNS_entry* next;
+
+ if (to == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ next = *to;
+
+ for (; from != NULL; from = from->next) {
+ DNS_entry* dnsEntry;
+
+ if (type != -1 && from->type != type)
+ continue;
+
+ dnsEntry = AltNameDup(from, heap);
+ if (dnsEntry == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ return MEMORY_E;
+ }
+
+ dnsEntry->next = next;
+ *prev_next = dnsEntry;
+ prev_next = &dnsEntry->next;
+ }
+
+ return 0;
+}
+#endif /* KEEP_PEER_CERT || SESSION_CERTS ||
+ * OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL ||
+ * WOLFSSL_ACERT */
+
+
#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType)
{
- if (nameType == SUBJECT) {
+ if (name->dynamicName) {
+ XFREE(name->name, name->heap, DYNAMIC_TYPE_X509);
+ name->name = name->staticName;
+ name->dynamicName = 0;
+ }
+
+ if (nameType == ASN_SUBJECT) {
XSTRNCPY(name->name, dCert->subject, ASN_NAME_MAX);
name->name[ASN_NAME_MAX - 1] = '\0';
name->sz = (int)XSTRLEN(name->name) + 1;
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)
name->rawLen = min(dCert->subjectRawLen, ASN_NAME_MAX);
- XMEMCPY(name->raw, dCert->subjectRaw, name->rawLen);
+ if (name->rawLen > 0)
+ XMEMCPY(name->raw, dCert->subjectRaw, name->rawLen);
#endif
}
else {
@@ -12446,60 +13317,13 @@ void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType)
#if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) \
&& (defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT))
name->rawLen = min(dCert->issuerRawLen, ASN_NAME_MAX);
- if (name->rawLen) {
+ if (name->rawLen > 0) {
XMEMCPY(name->raw, dCert->issuerRaw, name->rawLen);
}
#endif
}
}
-
-#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
- !defined(IGNORE_NAME_CONSTRAINTS)
-/* copies over additional alt names such as dirName
- * returns 0 on success
- */
-static int CopyAdditionalAltNames(DNS_entry** to, DNS_entry* from, int type,
- void* heap)
-{
- DNS_entry* cur = from;
-
- if (to == NULL) {
- return BAD_FUNC_ARG;
- }
-
- while (cur != NULL) {
- if (cur->type == type) {
- DNS_entry* dnsEntry;
- int strLen = cur->len;
-
- dnsEntry = AltNameNew(heap);
- if (dnsEntry == NULL) {
- WOLFSSL_MSG("\tOut of Memory");
- return MEMORY_E;
- }
-
- dnsEntry->type = type;
- dnsEntry->name = (char*)XMALLOC(strLen + 1, heap,
- DYNAMIC_TYPE_ALTNAME);
- if (dnsEntry->name == NULL) {
- WOLFSSL_MSG("\tOut of Memory");
- XFREE(dnsEntry, heap, DYNAMIC_TYPE_ALTNAME);
- return MEMORY_E;
- }
- dnsEntry->len = strLen;
- XMEMCPY(dnsEntry->name, cur->name, strLen);
- dnsEntry->name[strLen] = '\0';
-
- dnsEntry->next = *to;
- *to = dnsEntry;
- }
- cur = cur->next;
- }
- return 0;
-}
-#endif /* OPENSSL_EXTRA */
-
#ifdef WOLFSSL_CERT_REQ
static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
{
@@ -12511,7 +13335,7 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
x509->challengePw[dCert->cPwdLen] = '\0';
#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN)
if (wolfSSL_X509_REQ_add1_attr_by_NID(x509,
- NID_pkcs9_challengePassword,
+ WC_NID_pkcs9_challengePassword,
MBSTRING_ASC,
(const byte*)dCert->cPwd,
dCert->cPwdLen) != WOLFSSL_SUCCESS) {
@@ -12533,7 +13357,7 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
}
#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN)
if (wolfSSL_X509_REQ_add1_attr_by_NID(x509,
- NID_pkcs9_contentType,
+ WC_NID_pkcs9_contentType,
MBSTRING_ASC,
(const byte*)dCert->contentType,
dCert->contentTypeLen) !=
@@ -12547,7 +13371,7 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN)
if (dCert->sNum) {
if (wolfSSL_X509_REQ_add1_attr_by_NID(x509,
- NID_serialNumber,
+ WC_NID_serialNumber,
MBSTRING_ASC,
(const byte*)dCert->sNum,
dCert->sNumLen) != WOLFSSL_SUCCESS) {
@@ -12557,7 +13381,7 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
}
if (dCert->unstructuredName) {
if (wolfSSL_X509_REQ_add1_attr_by_NID(x509,
- NID_pkcs9_unstructuredName,
+ WC_NID_pkcs9_unstructuredName,
MBSTRING_ASC,
(const byte*)dCert->unstructuredName,
dCert->unstructuredNameLen)
@@ -12568,7 +13392,7 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
}
if (dCert->surname) {
if (wolfSSL_X509_REQ_add1_attr_by_NID(x509,
- NID_surname,
+ WC_NID_surname,
MBSTRING_ASC,
(const byte*)dCert->surname,
dCert->surnameLen) != WOLFSSL_SUCCESS) {
@@ -12578,7 +13402,7 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
}
if (dCert->givenName) {
if (wolfSSL_X509_REQ_add1_attr_by_NID(x509,
- NID_givenName,
+ WC_NID_givenName,
MBSTRING_ASC,
(const byte*)dCert->givenName,
dCert->givenNameLen) != WOLFSSL_SUCCESS) {
@@ -12588,7 +13412,7 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
}
if (dCert->dnQualifier) {
if (wolfSSL_X509_REQ_add1_attr_by_NID(x509,
- NID_dnQualifier,
+ WC_NID_dnQualifier,
MBSTRING_ASC,
(const byte*)dCert->dnQualifier,
dCert->dnQualifierLen) != WOLFSSL_SUCCESS) {
@@ -12598,7 +13422,7 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
}
if (dCert->initials) {
if (wolfSSL_X509_REQ_add1_attr_by_NID(x509,
- NID_initials,
+ WC_NID_initials,
MBSTRING_ASC,
(const byte*)dCert->initials,
dCert->initialsLen) != WOLFSSL_SUCCESS) {
@@ -12613,11 +13437,10 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert)
#endif /* WOLFSSL_CERT_REQ */
/* Copy parts X509 needs from Decoded cert, 0 on success */
-/* The same DecodedCert cannot be copied to WOLFSSL_X509 twice otherwise the
- * altNames pointers could be free'd by second x509 still active by first */
int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
{
int ret = 0;
+ int minSz;
if (x509 == NULL || dCert == NULL ||
dCert->subjectCNLen < 0)
@@ -12631,7 +13454,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
x509->version = dCert->version + 1;
- CopyDecodedName(&x509->issuer, dCert, ISSUER);
+ CopyDecodedName(&x509->issuer, dCert, ASN_ISSUER);
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
if (dCert->issuerName != NULL) {
wolfSSL_X509_set_issuer_name(x509,
@@ -12639,7 +13462,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
x509->issuer.x509 = x509;
}
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
- CopyDecodedName(&x509->subject, dCert, SUBJECT);
+ CopyDecodedName(&x509->subject, dCert, ASN_SUBJECT);
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
if (dCert->subjectName != NULL) {
wolfSSL_X509_set_subject_name(x509,
@@ -12667,55 +13490,51 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
#endif /* WOLFSSL_CERT_REQ */
#ifdef WOLFSSL_SEP
- {
- int minSz = min(dCert->deviceTypeSz, EXTERNAL_SERIAL_SIZE);
- if (minSz > 0) {
- x509->deviceTypeSz = minSz;
- XMEMCPY(x509->deviceType, dCert->deviceType, minSz);
- }
- else
- x509->deviceTypeSz = 0;
- minSz = min(dCert->hwTypeSz, EXTERNAL_SERIAL_SIZE);
- if (minSz > 0) {
- x509->hwTypeSz = minSz;
- XMEMCPY(x509->hwType, dCert->hwType, minSz);
- }
- else
- x509->hwTypeSz = 0;
- minSz = min(dCert->hwSerialNumSz, EXTERNAL_SERIAL_SIZE);
- if (minSz > 0) {
- x509->hwSerialNumSz = minSz;
- XMEMCPY(x509->hwSerialNum, dCert->hwSerialNum, minSz);
- }
- else
- x509->hwSerialNumSz = 0;
+ minSz = min(dCert->deviceTypeSz, EXTERNAL_SERIAL_SIZE);
+ if (minSz > 0) {
+ x509->deviceTypeSz = minSz;
+ XMEMCPY(x509->deviceType, dCert->deviceType, minSz);
+ }
+ else
+ x509->deviceTypeSz = 0;
+ minSz = min(dCert->hwTypeSz, EXTERNAL_SERIAL_SIZE);
+ if (minSz > 0) {
+ x509->hwTypeSz = minSz;
+ XMEMCPY(x509->hwType, dCert->hwType, minSz);
+ }
+ else
+ x509->hwTypeSz = 0;
+ minSz = min(dCert->hwSerialNumSz, EXTERNAL_SERIAL_SIZE);
+ if (minSz > 0) {
+ x509->hwSerialNumSz = minSz;
+ XMEMCPY(x509->hwSerialNum, dCert->hwSerialNum, minSz);
}
+ else
+ x509->hwSerialNumSz = 0;
#endif /* WOLFSSL_SEP */
- {
- int minSz;
- if (dCert->beforeDateLen > 0) {
- minSz = min(dCert->beforeDate[1], MAX_DATE_SZ);
- x509->notBefore.type = dCert->beforeDate[0];
- x509->notBefore.length = minSz;
- XMEMCPY(x509->notBefore.data, &dCert->beforeDate[2], minSz);
- }
- else
- x509->notBefore.length = 0;
- if (dCert->afterDateLen > 0) {
- minSz = min(dCert->afterDate[1], MAX_DATE_SZ);
- x509->notAfter.type = dCert->afterDate[0];
- x509->notAfter.length = minSz;
- XMEMCPY(x509->notAfter.data, &dCert->afterDate[2], minSz);
- }
- else
- x509->notAfter.length = 0;
+
+ if (dCert->beforeDateLen > 0) {
+ minSz = (int)min(dCert->beforeDate[1], MAX_DATE_SZ);
+ x509->notBefore.type = dCert->beforeDate[0];
+ x509->notBefore.length = minSz;
+ XMEMCPY(x509->notBefore.data, &dCert->beforeDate[2], minSz);
}
+ else
+ x509->notBefore.length = 0;
+ if (dCert->afterDateLen > 0) {
+ minSz = (int)min(dCert->afterDate[1], MAX_DATE_SZ);
+ x509->notAfter.type = dCert->afterDate[0];
+ x509->notAfter.length = minSz;
+ XMEMCPY(x509->notAfter.data, &dCert->afterDate[2], minSz);
+ }
+ else
+ x509->notAfter.length = 0;
if (dCert->publicKey != NULL && dCert->pubKeySize != 0) {
x509->pubKey.buffer = (byte*)XMALLOC(
dCert->pubKeySize, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (x509->pubKey.buffer != NULL) {
- x509->pubKeyOID = dCert->keyOID;
+ x509->pubKeyOID = (int)dCert->keyOID;
x509->pubKey.length = dCert->pubKeySize;
XMEMCPY(x509->pubKey.buffer, dCert->publicKey, dCert->pubKeySize);
}
@@ -12723,7 +13542,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
ret = MEMORY_E;
#if defined(OPENSSL_ALL)
if (ret == 0) {
- x509->key.pubKeyOID = dCert->keyOID;
+ x509->key.pubKeyOID = (int)dCert->keyOID;
if (!x509->key.algor) {
x509->key.algor = wolfSSL_X509_ALGOR_new();
@@ -12761,7 +13580,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
else {
XMEMCPY(x509->sig.buffer, dCert->signature, dCert->sigLength);
x509->sig.length = dCert->sigLength;
- x509->sigOID = dCert->signatureOID;
+ x509->sigOID = (int)dCert->signatureOID;
}
#if defined(OPENSSL_ALL)
wolfSSL_ASN1_OBJECT_free(x509->algor.algorithm);
@@ -12785,19 +13604,21 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
}
}
- x509->altNames = dCert->altNames;
- dCert->weOwnAltNames = 0;
+ /* add alt names from dCert to X509 */
+ if (CopyAltNames(&x509->altNames, dCert->altNames, -1, x509->heap) != 0) {
+ return MEMORY_E;
+ }
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
!defined(IGNORE_NAME_CONSTRAINTS)
/* add copies of email names from dCert to X509 */
- if (CopyAdditionalAltNames(&x509->altNames, dCert->altEmailNames,
+ if (CopyAltNames(&x509->altNames, dCert->altEmailNames,
ASN_RFC822_TYPE, x509->heap) != 0) {
return MEMORY_E;
}
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS)
/* add copies of alternate directory names from dCert to X509 */
- if (CopyAdditionalAltNames(&x509->altNames, dCert->altDirNames,
+ if (CopyAltNames(&x509->altNames, dCert->altDirNames,
ASN_DIR_TYPE, x509->heap) != 0) {
return MEMORY_E;
}
@@ -12806,7 +13627,9 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
x509->isCa = dCert->isCA;
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ x509->basicConstCrit = dCert->extBasicConstCrit;
x509->pathLength = dCert->pathLength;
+ x509->pathLengthSet = dCert->pathLengthSet;
x509->keyUsage = dCert->extKeyUsage;
x509->CRLdistSet = dCert->extCRLdistSet;
@@ -12846,7 +13669,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
ret = MEMORY_E;
}
}
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ #ifdef WOLFSSL_ASN_CA_ISSUER
if (dCert->extAuthInfoCaIssuer != NULL && dCert->extAuthInfoCaIssuerSz > 0) {
x509->authInfoCaIssuer = (byte*)XMALLOC(dCert->extAuthInfoCaIssuerSz, x509->heap,
DYNAMIC_TYPE_X509_EXT);
@@ -12860,7 +13683,6 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
}
#endif
x509->basicConstSet = dCert->extBasicConstSet;
- x509->basicConstCrit = dCert->extBasicConstCrit;
x509->basicConstPlSet = dCert->pathLengthSet;
x509->subjAltNameSet = dCert->extSubjAltNameSet;
x509->subjAltNameCrit = dCert->extSubjAltNameCrit;
@@ -12932,10 +13754,10 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
#ifndef IGNORE_NETSCAPE_CERT_TYPE
x509->nsCertType = dCert->nsCertType;
#endif
- #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+ #ifdef WOLFSSL_SEP
x509->certPolicySet = dCert->extCertPolicySet;
x509->certPolicyCrit = dCert->extCertPolicyCrit;
- #endif /* WOLFSSL_SEP || WOLFSSL_QT */
+ #endif
#ifdef WOLFSSL_CERT_EXT
{
int i;
@@ -12967,23 +13789,43 @@ 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,
- DYNAMIC_TYPE_X509_EXT);
- x509->altSigValDer = (byte*)XMALLOC(dCert->altSigValLen, x509->heap,
+ if (dCert->extSapkiSet) {
+ x509->sapkiDer = (byte*)XMALLOC(dCert->sapkiLen, 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;
+ x509->sapkiCrit = dCert->extSapkiCrit;
+ }
+ 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;
+ x509->altSigAlgCrit = dCert->extAltSigAlgCrit;
+ }
+ 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;
+ x509->altSigValCrit = dCert->extAltSigValCrit;
+ }
+ else {
+ ret = MEMORY_E;
+ }
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
@@ -12992,14 +13834,156 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
#endif /* KEEP_PEER_CERT || SESSION_CERTS */
-#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
- (defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(WOLFSSL_NO_TLS12))
-static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
- word32 status_length)
+#if defined(WOLFSSL_ACERT)
+/* Copy a DecodedAcert structure to an X509_ACERT.
+ *
+ * @param [out] x509 the dst X509 acert structure
+ * @param [in] dAcert the src decoded acert structure
+ *
+ * @return 0 on success
+ * @return < 0 on error
+ * */
+int CopyDecodedAcertToX509(WOLFSSL_X509_ACERT* x509, DecodedAcert* dAcert)
{
int ret = 0;
- OcspRequest* request;
+ if (x509 == NULL || dAcert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* Copy version and serial number. */
+ x509->version = dAcert->version + 1;
+
+ XMEMCPY(x509->serial, dAcert->serial, EXTERNAL_SERIAL_SIZE);
+ x509->serialSz = dAcert->serialSz;
+
+ if (dAcert->holderSerialSz > 0) {
+ /* This ACERT Holder field had a serial number. Copy it. */
+ XMEMCPY(x509->holderSerial, dAcert->holderSerial,
+ dAcert->holderSerialSz);
+ x509->holderSerialSz = dAcert->holderSerialSz;
+ }
+
+ /* Copy before and after dates. */
+ {
+ int minSz = 0;
+
+ if (dAcert->beforeDateLen > 0) {
+ minSz = (int)min(dAcert->beforeDate[1], MAX_DATE_SZ);
+ x509->notBefore.type = dAcert->beforeDate[0];
+ x509->notBefore.length = minSz;
+ XMEMCPY(x509->notBefore.data, &dAcert->beforeDate[2], minSz);
+ }
+ else {
+ x509->notBefore.length = 0;
+ }
+
+ if (dAcert->afterDateLen > 0) {
+ minSz = (int)min(dAcert->afterDate[1], MAX_DATE_SZ);
+ x509->notAfter.type = dAcert->afterDate[0];
+ x509->notAfter.length = minSz;
+ XMEMCPY(x509->notAfter.data, &dAcert->afterDate[2], minSz);
+ }
+ else {
+ x509->notAfter.length = 0;
+ }
+ }
+
+ /* Copy the signature. */
+ if (dAcert->signature != NULL && dAcert->sigLength != 0 &&
+ dAcert->sigLength <= MAX_ENCODED_SIG_SZ) {
+ x509->sig.buffer = (byte*)XMALLOC(
+ dAcert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (x509->sig.buffer == NULL) {
+ ret = MEMORY_E;
+ }
+ else {
+ XMEMCPY(x509->sig.buffer, dAcert->signature, dAcert->sigLength);
+ x509->sig.length = dAcert->sigLength;
+ x509->sigOID = (int)dAcert->signatureOID;
+ }
+ }
+
+ /* if der contains original source buffer then store for potential
+ * retrieval */
+ if (dAcert->source != NULL && dAcert->maxIdx > 0) {
+ if (AllocDer(&x509->derCert, dAcert->maxIdx, CERT_TYPE, x509->heap)
+ == 0) {
+ XMEMCPY(x509->derCert->buffer, dAcert->source, dAcert->maxIdx);
+ }
+ else {
+ ret = MEMORY_E;
+ }
+ }
+
+ /* Copy holder and att cert issuer names if present. */
+ if (CopyAltNames(&x509->holderIssuerName, dAcert->holderIssuerName,
+ ASN_DIR_TYPE, x509->heap) != 0) {
+ return MEMORY_E;
+ }
+
+ if (CopyAltNames(&x509->holderEntityName, dAcert->holderEntityName,
+ ASN_DIR_TYPE, x509->heap) != 0) {
+ return MEMORY_E;
+ }
+
+ if (CopyAltNames(&x509->AttCertIssuerName, dAcert->AttCertIssuerName,
+ ASN_DIR_TYPE, x509->heap) != 0) {
+ return MEMORY_E;
+ }
+
+ if (dAcert->rawAttr && dAcert->rawAttrLen > 0) {
+ /* Allocate space for the raw Attributes field, then copy it in. */
+ x509->rawAttr = (byte*)XMALLOC(dAcert->rawAttrLen, x509->heap,
+ DYNAMIC_TYPE_X509_EXT);
+ if (x509->rawAttr != NULL) {
+ XMEMCPY(x509->rawAttr, dAcert->rawAttr, dAcert->rawAttrLen);
+ x509->rawAttrLen = dAcert->rawAttrLen;
+ }
+ else {
+ ret = MEMORY_E;
+ }
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_ACERT */
+
+
+#if (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+ defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) && !defined(WOLFSSL_NO_TLS12)
+static int CsrDoStatusVerifyCb(WOLFSSL* ssl, byte* input, word32 inputSz, word32 idx,
+ int ret)
+{
+ if (ssl->ctx->ocspStatusVerifyCb != NULL) {
+ int verRet;
+ WOLFSSL_MSG("Calling OCSP status verify callback");
+ verRet = ssl->ctx->ocspStatusVerifyCb(ssl, ret,
+ input, inputSz, idx, ssl->ctx->ocspStatusVerifyCbArg);
+ if (verRet > 0) {
+ WOLFSSL_MSG("\tInvalid OCSP status verify callback return");
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+ }
+ else {
+ if (ret == 0 && verRet < 0)
+ WOLFSSL_MSG("\tforcing error");
+ else if (ret < 0 && verRet == 0)
+ WOLFSSL_MSG("\toverriding error");
+ ret = verRet;
+ }
+ }
+ return ret;
+}
+
+static int ProcessCSR_ex(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+ word32 status_length, int idx)
+{
+ int ret = 0;
+ OcspRequest* request;
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
+ TLSX* ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
+ CertificateStatusRequest* csr;
+#endif
#ifdef WOLFSSL_SMALL_STACK
CertStatus* status;
OcspEntry* single;
@@ -13011,14 +13995,24 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif
WOLFSSL_ENTER("ProcessCSR");
-
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
+ if (ext) {
+ /* status request */
+ csr = (CertificateStatusRequest*)ext->data;
+ if (csr && !csr->ssl)
+ csr->ssl = ssl;
+ }
+#endif
do {
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (ssl->status_request) {
- request = (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
+ request = (OcspRequest*)TLSX_CSR_GetRequest_ex(ssl->extensions,
+ idx);
ssl->status_request = 0;
break;
}
+ #else
+ (void)idx;
#endif
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
@@ -13033,60 +14027,79 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
return BUFFER_ERROR;
} while(0);
- if (request == NULL)
- return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */
-
#ifdef WOLFSSL_SMALL_STACK
status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
- DYNAMIC_TYPE_OCSP_STATUS);
+ DYNAMIC_TYPE_OCSP_STATUS);
single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), ssl->heap,
- DYNAMIC_TYPE_OCSP_ENTRY);
+ DYNAMIC_TYPE_OCSP_ENTRY);
response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap,
- DYNAMIC_TYPE_OCSP_REQUEST);
+ DYNAMIC_TYPE_OCSP_REQUEST);
if (status == NULL || single == NULL || response == NULL) {
- if (status)
+ if (status != NULL) {
XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
- if (single)
+ }
+ if (single != NULL) {
XFREE(single, ssl->heap, DYNAMIC_TYPE_OCSP_ENTRY);
- if (response)
+ }
+ if (response != NULL) {
XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ }
return MEMORY_ERROR;
}
#endif
- InitOcspResponse(response, single, status, input +*inOutIdx, status_length, ssl->heap);
+ /* InitOcspResponse sets single and status to response struct. */
+ InitOcspResponse(response, single, status, input +*inOutIdx, status_length,
+ ssl->heap);
- if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0) != 0)
+ /* Extract producedDate */
+ if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 1, 1) != 0)
ret = BAD_CERTIFICATE_STATUS_ERROR;
- else if (CompareOcspReqResp(request, response) != 0)
- ret = BAD_CERTIFICATE_STATUS_ERROR;
- else if (response->responseStatus != OCSP_SUCCESSFUL)
- ret = BAD_CERTIFICATE_STATUS_ERROR;
- else if (response->single->status->status == CERT_REVOKED)
- ret = OCSP_CERT_REVOKED;
- else if (response->single->status->status != CERT_GOOD)
- ret = BAD_CERTIFICATE_STATUS_ERROR;
-
- else {
- XMEMCPY(ssl->ocspProducedDate, response->producedDate, sizeof ssl->ocspProducedDate);
+ if (ret == 0) {
+ XMEMCPY(ssl->ocspProducedDate, response->producedDate,
+ sizeof(ssl->ocspProducedDate));
ssl->ocspProducedDateFormat = response->producedDateFormat;
+
+ /* Reset response */
+ FreeOcspResponse(response);
+ InitOcspResponse(response, single, status, input + *inOutIdx,
+ status_length, ssl->heap);
+
+ if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0, 0) != 0)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+ else if (CompareOcspReqResp(request, response) != 0)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+ else if (response->responseStatus != OCSP_SUCCESSFUL)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+ else if (response->single->status->status == CERT_REVOKED)
+ ret = OCSP_CERT_REVOKED;
+ else if (response->single->status->status != CERT_GOOD)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+
+ ret = CsrDoStatusVerifyCb(ssl, input + *inOutIdx, status_length, idx, ret);
}
*inOutIdx += status_length;
+ /* FreeOcspResponse frees status and single only if
+ * single->isDynamic is set. */
FreeOcspResponse(response);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
- XFREE(single, ssl->heap, DYNAMIC_TYPE_OCSP_ENTRY);
- XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
- #endif
+ WC_FREE_VAR_EX(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
+ WC_FREE_VAR_EX(single, ssl->heap, DYNAMIC_TYPE_OCSP_ENTRY);
+ WC_FREE_VAR_EX(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
WOLFSSL_LEAVE("ProcessCSR", ret);
return ret;
}
+
+static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
+ word32 status_length)
+{
+ return ProcessCSR_ex(ssl, input, inOutIdx, status_length, 0);
+}
#endif
@@ -13099,7 +14112,7 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
const unsigned char* keyDer, unsigned int keySz,
int* result, void* ctx)
{
- int ret = NOT_COMPILED_IN;
+ int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
WOLFSSL* ssl = (WOLFSSL*)ctx;
if (ssl && ssl->ctx->EccVerifyCb) {
@@ -13114,7 +14127,7 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx,
unsigned char** out, const unsigned char* keyDer, unsigned int keySz,
void* ctx)
{
- int ret = NOT_COMPILED_IN;
+ int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
WOLFSSL* ssl = (WOLFSSL*)ctx;
if (ssl && ssl->ctx->RsaVerifyCb) {
@@ -13164,7 +14177,6 @@ int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx)
#endif /* HAVE_PK_CALLBACKS */
-
#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
void DoCertFatalAlert(WOLFSSL* ssl, int ret)
{
@@ -13176,24 +14188,26 @@ void DoCertFatalAlert(WOLFSSL* ssl, int ret)
/* Determine alert reason */
alertWhy = bad_certificate;
- if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) {
+ if (ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E) ||
+ ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) {
alertWhy = certificate_expired;
}
- else if (ret == ASN_NO_SIGNER_E || ret == ASN_PATHLEN_INV_E ||
- ret == ASN_PATHLEN_SIZE_E) {
+ else if (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) ||
+ ret == WC_NO_ERR_TRACE(ASN_PATHLEN_INV_E) ||
+ ret == WC_NO_ERR_TRACE(ASN_PATHLEN_SIZE_E)) {
alertWhy = unknown_ca;
}
#ifdef OPENSSL_EXTRA
- else if (ret == CRL_CERT_REVOKED) {
+ else if (ret == WC_NO_ERR_TRACE(CRL_CERT_REVOKED)) {
alertWhy = certificate_revoked;
}
#endif
#if defined(HAVE_RPK)
- else if (ret == UNSUPPORTED_CERTIFICATE) {
+ else if (ret == WC_NO_ERR_TRACE(UNSUPPORTED_CERTIFICATE)) {
alertWhy = unsupported_certificate;
}
#endif /* HAVE_RPK */
- else if (ret == NO_PEER_CERT) {
+ else if (ret == WC_NO_ERR_TRACE(NO_PEER_CERT)) {
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3) {
alertWhy = certificate_required;
@@ -13205,11 +14219,176 @@ void DoCertFatalAlert(WOLFSSL* ssl, int ret)
}
}
+#ifndef NO_TLS
/* send fatal alert and mark connection closed */
SendAlert(ssl, alert_fatal, alertWhy); /* try to send */
+#else
+ (void)alertWhy;
+#endif
ssl->options.isClosed = 1;
}
+int SetupStoreCtxCallback(WOLFSSL_X509_STORE_CTX** store_pt,
+ WOLFSSL* ssl, WOLFSSL_CERT_MANAGER* cm, ProcPeerCertArgs* args,
+ int cert_err, void* heap, int* x509Free)
+{
+ WOLFSSL_X509_STORE_CTX* store = NULL;
+ char* domain = NULL;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ WOLFSSL_X509* x509 = NULL;
+#endif
+
+ *x509Free = 0;
+
+ store = wolfSSL_X509_STORE_CTX_new_ex(heap);
+ if (store == NULL)
+ goto mem_error;
+ domain = (char*)XMALLOC(ASN_NAME_MAX, heap, DYNAMIC_TYPE_STRING);
+ if (domain == NULL)
+ goto mem_error;
+
+ domain[0] = '\0';
+
+ /* build subject CN as string to return in store */
+ if (args->dCertInit && args->dCert && args->dCert->subjectCN) {
+ int subjectCNLen = args->dCert->subjectCNLen;
+ if (subjectCNLen > ASN_NAME_MAX-1)
+ subjectCNLen = ASN_NAME_MAX-1;
+ if (subjectCNLen > 0) {
+ XMEMCPY(domain, args->dCert->subjectCN, (size_t)(subjectCNLen));
+ domain[subjectCNLen] = '\0';
+ }
+ }
+
+#ifndef OPENSSL_COMPATIBLE_DEFAULTS
+ store->error = cert_err;
+#else
+ store->error = GetX509Error(cert_err);
+#endif
+ store->error_depth = args->certIdx;
+ store->discardSessionCerts = 0;
+ store->domain = domain;
+ if (ssl != NULL) {
+ if (ssl->verifyCbCtx != NULL) {
+ /* Use the WOLFSSL user context if set */
+ store->userCtx = ssl->verifyCbCtx;
+ }
+ else {
+ /* Else use the WOLFSSL_CTX user context */
+ store->userCtx = ssl->ctx->verifyCbCtx;
+ }
+ }
+ else {
+ store->userCtx = cm;
+ }
+ store->certs = args->certs;
+ store->totalCerts = args->totalCerts;
+#if defined(HAVE_EX_DATA) && \
+ (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL))
+ if (wolfSSL_CRYPTO_set_ex_data(&store->ex_data, 0, ssl)
+ != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Failed to store ssl context in WOLFSSL_X509_STORE_CTX");
+ }
+#endif
+
+ if (ssl != NULL) {
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+ store->store = SSL_STORE(ssl);
+#if defined(OPENSSL_EXTRA)
+ store->depth = args->count;
+ /* Overwrite with non-default param values in SSL */
+ if (ssl->param) {
+ if (ssl->param->check_time)
+ store->param->check_time = ssl->param->check_time;
+
+ if (ssl->param->flags)
+ store->param->flags = ssl->param->flags;
+#ifdef WOLFSSL_LOCAL_X509_STORE
+ else if (SSL_STORE(ssl) && SSL_STORE(ssl)->param &&
+ SSL_STORE(ssl)->param->flags)
+ store->param->flags = SSL_STORE(ssl)->param->flags;
+#endif
+
+
+ if (ssl->param->hostName[0])
+ XMEMCPY(store->param->hostName, ssl->param->hostName,
+ WOLFSSL_HOST_NAME_MAX);
+
+ }
+#endif /* defined(OPENSSL_EXTRA) */
+#endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)*/
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ #ifdef KEEP_PEER_CERT
+ if (args->certIdx == 0) {
+ FreeX509(&ssl->peerCert);
+ InitX509(&ssl->peerCert, 0, ssl->heap);
+ if (CopyDecodedToX509(&ssl->peerCert, args->dCert) == 0)
+ WOLFSSL_MSG("Unable to copy to ssl->peerCert");
+ store->current_cert = &ssl->peerCert; /* use existing X509 */
+ }
+ else
+ #endif
+ {
+ x509 = wolfSSL_X509_new_ex(heap);
+ if (x509 == NULL)
+ goto mem_error;
+ if (CopyDecodedToX509(x509, args->dCert) == 0) {
+ store->current_cert = x509;
+ *x509Free = 1;
+ }
+ else {
+ goto mem_error;
+ }
+ }
+#endif
+#ifdef SESSION_CERTS
+ store->sesChain = &ssl->session->chain;
+#endif
+ }
+ *store_pt = store;
+ return 0;
+mem_error:
+ if (store != NULL)
+ wolfSSL_X509_STORE_CTX_free(store);
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ if (x509 != NULL) {
+ wolfSSL_X509_free(x509);
+ x509 = NULL;
+ }
+#endif
+ XFREE(domain, heap, DYNAMIC_TYPE_STRING);
+ return MEMORY_E;
+}
+
+void CleanupStoreCtxCallback(WOLFSSL_X509_STORE_CTX* store,
+ WOLFSSL* ssl, void* heap, int x509Free)
+{
+ (void)ssl;
+ (void)x509Free;
+
+#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+ wolfSSL_sk_X509_pop_free(store->chain, NULL);
+ store->chain = NULL;
+#endif
+#ifdef SESSION_CERTS
+ if ((ssl != NULL) && (store->discardSessionCerts)) {
+ WOLFSSL_MSG("Verify callback requested discard sess certs");
+ ssl->session->chain.count = 0;
+ #ifdef WOLFSSL_ALT_CERT_CHAINS
+ ssl->session->altChain.count = 0;
+ #endif
+ }
+#endif /* SESSION_CERTS */
+ XFREE(store->domain, heap, DYNAMIC_TYPE_STRING);
+ store->domain = NULL;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ if (x509Free)
+ wolfSSL_X509_free(store->current_cert);
+ store->current_cert = NULL;
+#endif
+ wolfSSL_X509_STORE_CTX_free(store);
+}
+
/* WOLFSSL_ALWAYS_VERIFY_CB: Use verify callback for success or failure cases */
/* WOLFSSL_VERIFY_CB_ALL_CERTS: Issue callback for all intermediate certificates */
@@ -13218,10 +14397,10 @@ void DoCertFatalAlert(WOLFSSL* ssl, int ret)
* store->error_depth member to determine index (0=peer, >1 intermediates)
*/
-int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
+int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int cert_err,
ProcPeerCertArgs* args)
{
- int verify_ok = 0, use_cb = 0;
+ int verify_ok = 0, use_cb = 0, ret = cert_err;
void *heap;
if (cm == NULL) {
@@ -13231,12 +14410,12 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
heap = (ssl != NULL) ? ssl->heap : cm->heap;
/* Determine if verify was okay */
- if (ret == 0) {
+ if (cert_err == 0) {
verify_ok = 1;
}
/* Determine if verify callback should be used */
- if (ret != 0) {
+ if (cert_err != 0) {
if ((ssl != NULL) && (!ssl->options.verifyNone)) {
use_cb = 1; /* always report errors */
}
@@ -13261,8 +14440,9 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
ssl->param && ssl->param->hostName[0]) {
/* If altNames names is present, then subject common name is ignored */
if (args->dCert->altNames != NULL) {
- if (CheckForAltNames(args->dCert, ssl->param->hostName, NULL) != 1) {
- if (ret == 0) {
+ if (CheckForAltNames(args->dCert, ssl->param->hostName,
+ (word32)XSTRLEN(ssl->param->hostName), NULL, 0, 0) != 1) {
+ if (cert_err == 0) {
ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
@@ -13271,10 +14451,12 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
#ifndef WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY
else {
if (args->dCert->subjectCN) {
- if (MatchDomainName(args->dCert->subjectCN,
- args->dCert->subjectCNLen,
- ssl->param->hostName) == 0) {
- if (ret == 0) {
+ if (MatchDomainName(
+ args->dCert->subjectCN,
+ args->dCert->subjectCNLen,
+ ssl->param->hostName,
+ (word32)XSTRLEN(ssl->param->hostName), 0) == 0) {
+ if (cert_err == 0) {
ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
@@ -13283,7 +14465,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
}
#else
else {
- if (ret == 0) {
+ if (cert_err == 0) {
ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
@@ -13295,7 +14477,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl != NULL) &&
(ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) {
if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) {
- if (ret == 0) {
+ if (cert_err == 0) {
ret = IPADDR_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
@@ -13307,6 +14489,10 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
if ((use_cb && (ssl != NULL) && ((ssl->verifyCallback != NULL)
#ifdef OPENSSL_ALL
|| (ssl->ctx->verifyCertCb != NULL)
+ #endif
+ #if defined(WOLFSSL_LOCAL_X509_STORE) && \
+ (defined(OPENSSL_ALL) || defined(WOLFSSL_QT))
+ || (SSL_STORE(ssl) != NULL && SSL_STORE(ssl)->verify_cb != NULL)
#endif
))
#ifndef NO_WOLFSSL_CM_VERIFY
@@ -13314,157 +14500,20 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
#endif
) {
int verifyFail = 0;
- #ifdef WOLFSSL_SMALL_STACK
- WOLFSSL_X509_STORE_CTX* store;
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- WOLFSSL_X509* x509;
- #endif
- char* domain = NULL;
- #else
- WOLFSSL_X509_STORE_CTX store[1];
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- WOLFSSL_X509 x509[1];
- #endif
- char domain[ASN_NAME_MAX];
- #endif
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ WOLFSSL_X509_STORE_CTX* store = NULL;
int x509Free = 0;
- #endif
-
- #ifdef WOLFSSL_SMALL_STACK
- store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(
- sizeof(WOLFSSL_X509_STORE_CTX), heap, DYNAMIC_TYPE_X509_STORE);
- if (store == NULL) {
- return MEMORY_E;
- }
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
- DYNAMIC_TYPE_X509);
- if (x509 == NULL) {
- XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
- return MEMORY_E;
- }
- #endif
- domain = (char*)XMALLOC(ASN_NAME_MAX, heap, DYNAMIC_TYPE_STRING);
- if (domain == NULL) {
- XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- XFREE(x509, heap, DYNAMIC_TYPE_X509);
- #endif
- return MEMORY_E;
- }
- #endif /* WOLFSSL_SMALL_STACK */
-
- XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX));
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- XMEMSET(x509, 0, sizeof(WOLFSSL_X509));
- #endif
- domain[0] = '\0';
-
- /* build subject CN as string to return in store */
- if (args->dCertInit && args->dCert && args->dCert->subjectCN) {
- int subjectCNLen = args->dCert->subjectCNLen;
- if (subjectCNLen > ASN_NAME_MAX-1)
- subjectCNLen = ASN_NAME_MAX-1;
- if (subjectCNLen > 0) {
- XMEMCPY(domain, args->dCert->subjectCN, subjectCNLen);
- domain[subjectCNLen] = '\0';
- }
- }
+ int setupRet = SetupStoreCtxCallback(&store, ssl, cm, args, cert_err,
+ heap, &x509Free);
-#ifndef OPENSSL_COMPATIBLE_DEFAULTS
- store->error = ret;
-#else
- store->error = GetX509Error(ret);
-#endif
- store->error_depth = args->certIdx;
- store->discardSessionCerts = 0;
- store->domain = domain;
- if (ssl != NULL) {
- if (ssl->verifyCbCtx != NULL) {
- /* Use the WOLFSSL user context if set */
- store->userCtx = ssl->verifyCbCtx;
- }
- else {
- /* Else use the WOLFSSL_CTX user context */
- store->userCtx = ssl->ctx->verifyCbCtx;
- }
- }
- else {
- store->userCtx = cm;
- }
- store->certs = args->certs;
- store->totalCerts = args->totalCerts;
- #if defined(HAVE_EX_DATA) && \
- (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL))
- if (wolfSSL_CRYPTO_set_ex_data(&store->ex_data, 0, ssl)
- != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Failed to store ssl context in WOLFSSL_X509_STORE_CTX");
- }
- #endif
+ if (setupRet != 0)
+ return setupRet;
- if (ssl != NULL) {
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- store->store = SSL_STORE(ssl);
- #if defined(OPENSSL_EXTRA)
- store->depth = args->count;
- store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
- sizeof(WOLFSSL_X509_VERIFY_PARAM),
- heap, DYNAMIC_TYPE_OPENSSL);
- if (store->param == NULL) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(domain, heap, DYNAMIC_TYPE_STRING);
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- XFREE(x509, heap, DYNAMIC_TYPE_X509);
- #endif
- XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
- #endif
- return MEMORY_E;
- }
- XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
- /* Overwrite with non-default param values in SSL */
- if (ssl->param) {
- if (ssl->param->check_time)
- store->param->check_time = ssl->param->check_time;
-
- if (ssl->param->flags)
- store->param->flags = ssl->param->flags;
-
- if (ssl->param->hostName[0])
- XMEMCPY(store->param->hostName, ssl->param->hostName,
- WOLFSSL_HOST_NAME_MAX);
-
- }
- #endif /* defined(OPENSSL_EXTRA) */
- #endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)*/
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- #ifdef KEEP_PEER_CERT
- if (args->certIdx == 0) {
- store->current_cert = &ssl->peerCert; /* use existing X509 */
- }
- else
- #endif
- {
- InitX509(x509, 0, heap);
- if (CopyDecodedToX509(x509, args->dCert) == 0) {
- store->current_cert = x509;
- x509Free = 1;
- }
- else {
- FreeX509(x509);
- }
- }
- #endif
- #ifdef SESSION_CERTS
- store->sesChain = &ssl->session->chain;
- #endif
- }
#ifndef NO_WOLFSSL_CM_VERIFY
/* non-zero return code indicates failure override */
if (cm->verifyCallback != NULL) {
store->userCtx = cm;
if (cm->verifyCallback(verify_ok, store)) {
- if (ret != 0) {
+ if (cert_err != 0) {
WOLFSSL_MSG("Verify CM callback overriding error!");
ret = 0;
}
@@ -13480,7 +14529,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
/* non-zero return code indicates failure override */
if (ssl->ctx->verifyCertCb) {
if (ssl->ctx->verifyCertCb(store, ssl->ctx->verifyCertCbArg)) {
- if (ret != 0) {
+ if (cert_err != 0) {
WOLFSSL_MSG("Verify Cert callback overriding error!");
ret = 0;
}
@@ -13490,11 +14539,10 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
}
}
#endif
-
/* non-zero return code indicates failure override */
if (ssl->verifyCallback) {
if (ssl->verifyCallback(verify_ok, store)) {
- if (ret != 0) {
+ if (cert_err != 0) {
WOLFSSL_MSG("Verify callback overriding error!");
ret = 0;
}
@@ -13503,11 +14551,25 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
verifyFail = 1;
}
}
+#if defined(WOLFSSL_LOCAL_X509_STORE) && \
+ (defined(OPENSSL_ALL) || defined(WOLFSSL_QT))
+ if (SSL_STORE(ssl) != NULL && SSL_STORE(ssl)->verify_cb != NULL) {
+ if (SSL_STORE(ssl)->verify_cb(verify_ok, store)) {
+ if (cert_err != 0) {
+ WOLFSSL_MSG("Store Verify callback overriding error!");
+ ret = 0;
+ }
+ }
+ else {
+ verifyFail = 1;
+ }
+ }
+#endif
}
if (verifyFail) {
/* induce error if one not present */
- if (ret == 0) {
+ if (cert_err == 0) {
ret = VERIFY_CERT_ERROR;
WOLFSSL_ERROR_VERBOSE(ret);
}
@@ -13515,36 +14577,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
/* mark as verify error */
args->verifyErr = 1;
}
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- if (x509Free) {
- FreeX509(x509);
- }
- #endif
- #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- wolfSSL_sk_X509_pop_free(store->chain, NULL);
- store->chain = NULL;
- #endif
- #ifdef SESSION_CERTS
- if ((ssl != NULL) && (store->discardSessionCerts)) {
- WOLFSSL_MSG("Verify callback requested discard sess certs");
- ssl->session->chain.count = 0;
- #ifdef WOLFSSL_ALT_CERT_CHAINS
- ssl->session->altChain.count = 0;
- #endif
- }
- #endif /* SESSION_CERTS */
-#ifdef OPENSSL_EXTRA
- if ((ssl != NULL) && (store->param)) {
- XFREE(store->param, heap, DYNAMIC_TYPE_OPENSSL);
- }
-#endif
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(domain, heap, DYNAMIC_TYPE_STRING);
- #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- XFREE(x509, heap, DYNAMIC_TYPE_X509);
- #endif
- XFREE(store, heap, DYNAMIC_TYPE_X509_STORE);
- #endif
+ CleanupStoreCtxCallback(store, ssl, heap, x509Free);
}
(void)heap;
@@ -13552,21 +14585,61 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret,
return ret;
}
+#ifdef HAVE_CRL
+void DoCrlCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl,
+ ProcPeerCertArgs* args, int* outRet)
+{
+#if defined(WOLFSSL_LOCAL_X509_STORE) && \
+ (defined(OPENSSL_ALL) || defined(WOLFSSL_QT))
+ int ret = 0;
+ void* heap = (ssl != NULL) ? ssl->heap : cm->heap;
+ WOLFSSL_X509_STORE* cert_store = (ssl != NULL) ? SSL_STORE(ssl) : NULL;
+
+ if (cert_store != NULL && cert_store->get_crl_cb != NULL) {
+ WOLFSSL_CRL* userCrl = NULL;
+ WOLFSSL_X509_STORE_CTX* store = NULL;
+ int x509Free = 0;
+
+ ret = SetupStoreCtxCallback(&store, ssl, cm, args, 0, heap,
+ &x509Free);
+ if (ret != 0) {
+ *outRet = ret;
+ return;
+ }
+
+ ret = cert_store->get_crl_cb(store, &userCrl, store->current_cert);
+ if (ret == 1 && userCrl != NULL) {
+ /* Point to current cm to be able to verify CRL */
+ userCrl->cm = SSL_CM(ssl);
+ *outRet = CheckCertCRL(userCrl, args->dCert);
+ }
+ else
+ *outRet = CRL_MISSING;
+
+ if (userCrl != NULL)
+ wolfSSL_X509_CRL_free(userCrl);
+ CleanupStoreCtxCallback(store, ssl, heap, x509Free);
+ }
+#else
+ (void)cm;
+ (void)ssl;
+ (void)args;
+ (void)outRet;
+#endif
+}
+#endif
+
static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs)
{
ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs;
(void)ssl;
- if (args->certs) {
- XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_DER);
- args->certs = NULL;
- }
+ XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_DER);
+ args->certs = NULL;
#ifdef WOLFSSL_TLS13
- if (args->exts) {
- XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_CERT_EXT);
- args->exts = NULL;
- }
+ XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_CERT_EXT);
+ args->exts = NULL;
#endif
if (args->dCert) {
if (args->dCertInit) {
@@ -13622,7 +14695,7 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type)
#if defined(NO_SHA) && !defined(NO_SHA256)
retHash = wc_Sha256Hash((const byte*)pbuf, len, dgt);
#elif !defined(NO_SHA)
- retHash = wc_ShaHash((const byte*)pbuf, len, dgt);
+ retHash = wc_ShaHash((const byte*)pbuf, (word32)len, dgt);
#endif
if (retHash == 0) {
/* 4 bytes in little endian as unsigned long */
@@ -13663,7 +14736,10 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type)
if (idx >= 0) {
WOLFSSL_MSG("find hashed CRL in list");
ph = wolfSSL_sk_BY_DIR_HASH_value(entry->hashes, idx);
- suffix = ph->last_suffix;
+ if (ph)
+ suffix = ph->last_suffix;
+ else
+ suffix = 0;
} else {
ph = NULL;
suffix = 0;
@@ -13676,9 +14752,7 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type)
/* / .(r)N\0 */
/*|1| 8 |1|1|1|1| => 13 */
len = (int)XSTRLEN(entry->dir_name) + 13;
- if (filename != NULL) {
- XFREE(filename, NULL, DYNAMIC_TYPE_OPENSSL);
- }
+ XFREE(filename, NULL, DYNAMIC_TYPE_OPENSSL);
filename = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
if (filename == NULL) {
@@ -13692,7 +14766,7 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type)
for (; suffix < MAX_SUFFIX; suffix++) {
/* /folder-path/.(r)N[0..9] */
- if (XSNPRINTF(filename, len, "%s/%08lx.%s%d", entry->dir_name,
+ if (XSNPRINTF(filename, (size_t)len, "%s/%08lx.%s%d", entry->dir_name,
hash, post, suffix)
>= len)
{
@@ -13709,6 +14783,7 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type)
if (x509 != NULL) {
ret = wolfSSL_X509_STORE_add_cert(store, x509);
wolfSSL_X509_free(x509);
+ x509 = NULL;
} else {
WOLFSSL_MSG("failed to load certificate");
ret = WOLFSSL_FAILURE;
@@ -13753,7 +14828,8 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type)
ph->hash_value = hash;
ph->last_suffix = suffix;
- ret = wolfSSL_sk_BY_DIR_HASH_push(entry->hashes, ph);
+ ret = wolfSSL_sk_BY_DIR_HASH_push(entry->hashes, ph) > 0
+ ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
}
}
wc_UnLockMutex(&lookup->dirs->lock);
@@ -13787,6 +14863,7 @@ static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args,
buffer* cert;
byte* subjectHash = NULL;
int alreadySigner = 0;
+ Signer *extraSigners = NULL;
#if defined(HAVE_RPK)
int cType;
#endif
@@ -13817,7 +14894,7 @@ PRAGMA_GCC_DIAG_POP
/* check if returning from non-blocking OCSP */
/* skip this section because cert is already initialized and parsed */
#ifdef WOLFSSL_NONBLOCK_OCSP
- if (args->lastErr == OCSP_WANT_READ) {
+ if (args->lastErr == WC_NO_ERR_TRACE(OCSP_WANT_READ)) {
args->lastErr = 0; /* clear error */
return 0;
}
@@ -13847,7 +14924,7 @@ PRAGMA_GCC_DIAG_POP
}
/* perform cert parsing and signature check */
- sigRet = CheckCertSignature(cert->buffer, cert->length,
+ sigRet = wc_CheckCertSignature(cert->buffer, cert->length,
ssl->heap, SSL_CM(ssl));
/* fail on errors here after the ParseCertRelative call, so dCert is populated */
@@ -13888,9 +14965,13 @@ PRAGMA_GCC_DIAG_POP
return ret;
#endif
}
-
+#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+ if (verify != NO_VERIFY && TLSX_CSR2_IsMulti(ssl->extensions)) {
+ extraSigners = TLSX_CSR2_GetPendingSigners(ssl->extensions);
+ }
+#endif
/* Parse Certificate */
- ret = ParseCertRelative(args->dCert, certType, verify, SSL_CM(ssl));
+ ret = ParseCertRelative(args->dCert, certType, verify, SSL_CM(ssl), extraSigners);
#if defined(HAVE_RPK)
/* if cert type has negotiated with peer, confirm the cert received has
@@ -13923,7 +15004,9 @@ PRAGMA_GCC_DIAG_POP
#endif /* HAVE_RPK */
/* perform below checks for date failure cases */
- if (ret == 0 || ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) {
+ if (ret == 0 ||
+ ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) ||
+ ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) {
/* get subject and determine if already loaded */
#ifndef NO_SKID
if (args->dCert->extAuthKeyIdSet)
@@ -13934,39 +15017,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)
@@ -13979,7 +15029,7 @@ PRAGMA_GCC_DIAG_POP
*pAlreadySigner = alreadySigner;
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl,
args->dCert->sigCtx.asyncDev);
}
@@ -13991,7 +15041,7 @@ PRAGMA_GCC_DIAG_POP
* original return code is returned. */
if (ssl->ctx && ssl->ctx->ProcessPeerCertCb) {
int new_ret = ssl->ctx->ProcessPeerCertCb(ssl, args->dCert);
- if (new_ret != NOT_COMPILED_IN) {
+ if (new_ret != WC_NO_ERR_TRACE(NOT_COMPILED_IN)) {
ret = new_ret;
}
}
@@ -14060,7 +15110,6 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args)
}
break;
#endif /* HAVE_ED448 */
- #if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
case FALCON_LEVEL1k:
if (ssl->options.minFalconKeySz < 0 ||
@@ -14079,8 +15128,8 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args)
}
break;
#endif /* HAVE_FALCON */
- #endif /* HAVE_PQC */
#if defined(HAVE_DILITHIUM)
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
case DILITHIUM_LEVEL2k:
if (ssl->options.minDilithiumKeySz < 0 ||
DILITHIUM_LEVEL2_KEY_SIZE
@@ -14105,6 +15154,31 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args)
ret = DILITHIUM_KEY_SIZE_E;
}
break;
+ #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
+ case ML_DSA_LEVEL2k:
+ if (ssl->options.minDilithiumKeySz < 0 ||
+ ML_DSA_LEVEL2_KEY_SIZE
+ < (word16)ssl->options.minDilithiumKeySz) {
+ WOLFSSL_MSG("Dilithium key size in cert chain error");
+ ret = DILITHIUM_KEY_SIZE_E;
+ }
+ break;
+ case ML_DSA_LEVEL3k:
+ if (ssl->options.minDilithiumKeySz < 0 ||
+ ML_DSA_LEVEL3_KEY_SIZE
+ < (word16)ssl->options.minDilithiumKeySz) {
+ WOLFSSL_MSG( "Dilithium key size in cert chain error");
+ ret = DILITHIUM_KEY_SIZE_E;
+ }
+ break;
+ case ML_DSA_LEVEL5k:
+ if (ssl->options.minDilithiumKeySz < 0 ||
+ ML_DSA_LEVEL5_KEY_SIZE
+ < (word16)ssl->options.minDilithiumKeySz) {
+ WOLFSSL_MSG("Dilithium key size in cert chain error");
+ ret = DILITHIUM_KEY_SIZE_E;
+ }
+ break;
#endif /* HAVE_DILITHIUM */
default:
WOLFSSL_MSG("Key size not checked");
@@ -14116,11 +15190,59 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args)
return ret;
}
+#if defined(HAVE_OCSP) && defined(WOLFSSL_TLS13) \
+ && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
+static int ProcessPeerCertsChainOCSPStatusCheck(WOLFSSL* ssl)
+{
+ int ret = 0;
+ word32 i;
+ word32 idx = 0;
+ TLSX* ext = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
+ CertificateStatusRequest* csr;
+
+ if (ext) {
+ csr = (CertificateStatusRequest*)ext->data;
+ if (csr == NULL) {
+ return 0;
+ }
+ } else
+ return 0;
+
+ /* error when leaf cert doesn't have certificate status */
+ if (csr->requests < 1 || csr->responses[0].length == 0) {
+ WOLFSSL_MSG("Leaf cert doesn't have certificate status.");
+ return BAD_CERTIFICATE_STATUS_ERROR;
+ }
+
+ for (i = 0; i < csr->requests; i++) {
+ if (csr->responses[i].length != 0) {
+ ssl->status_request = 1;
+ idx = 0;
+ ret = ProcessCSR_ex(ssl,
+ csr->responses[i].buffer,
+ &idx, csr->responses[i].length, i);
+ if (ret < 0) {
+ WOLFSSL_ERROR_VERBOSE(ret);
+ break;
+ }
+ }
+ else {
+ WOLFSSL_MSG("Intermediate cert doesn't have certificate status.");
+ }
+ }
+
+ return ret;
+}
+
+#endif
+
#ifdef HAVE_CRL
-static int ProcessPeerCertsChainCRLCheck(WOLFSSL_CERT_MANAGER* cm, Signer* ca)
+static int ProcessPeerCertsChainCRLCheck(WOLFSSL* ssl, ProcPeerCertArgs* args)
{
Signer* prev = NULL;
int ret = 0;
+ WOLFSSL_CERT_MANAGER* cm = SSL_CM(ssl);
+ Signer* ca = args->dCert->ca;
/* End loop if no more issuers found or if we have
* found a self signed cert (ca == prev) */
for (; ret == 0 && ca != NULL && ca != prev;
@@ -14128,12 +15250,36 @@ static int ProcessPeerCertsChainCRLCheck(WOLFSSL_CERT_MANAGER* cm, Signer* ca)
ret = CheckCertCRL_ex(cm->crl, ca->issuerNameHash, NULL, 0,
ca->serialHash, NULL, 0, NULL);
if (ret != 0)
+ DoCrlCallback(cm, ssl, args, &ret);
+ if (ret != 0){
+ WOLFSSL_ERROR_VERBOSE(ret);
+ WOLFSSL_MSG("\tCRL check not ok");
break;
+ }
}
return ret;
}
#endif
+#ifdef OPENSSL_EXTRA
+/* account for verify params flag set */
+static int AdjustCMForParams(WOLFSSL* ssl)
+{
+ int flags;
+ WOLFSSL_X509_VERIFY_PARAM* param;
+
+ param = wolfSSL_get0_param(ssl);
+ flags = wolfSSL_X509_VERIFY_PARAM_get_flags(param);
+
+ /* For now there is a possible contradiction of PARAM flags and store flags.
+ * Do not disable CRL support if it has already been enabled with store. */
+ if (flags == 0) {
+ return WOLFSSL_SUCCESS;
+ }
+ return wolfSSL_X509_STORE_set_flags(SSL_STORE(ssl), flags);
+}
+#endif
+
int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 totalSz)
{
@@ -14149,6 +15295,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
byte* subjectHash = NULL;
int alreadySigner = 0;
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ int addToPendingCAs = 0;
+#endif
WOLFSSL_ENTER("ProcessPeerCerts");
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
@@ -14162,7 +15311,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
args = (ProcPeerCertArgs*)ssl->async->args;
#ifdef WOLFSSL_ASYNC_CRYPT
ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* Check for error */
if (ret < 0)
goto exit_ppc;
@@ -14170,11 +15319,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
else
#endif /* WOLFSSL_ASYNC_CRYPT */
#ifdef WOLFSSL_NONBLOCK_OCSP
- if (ssl->error == OCSP_WANT_READ) {
+ if (ssl->error == WC_NO_ERR_TRACE(OCSP_WANT_READ)) {
/* Re-entry after non-blocking OCSP */
#ifdef WOLFSSL_ASYNC_CRYPT
- /* if async operationg not pending, reset error code */
- if (ret == WC_NO_PENDING_E)
+ /* if async operations not pending, reset error code */
+ if (ret == WC_NO_ERR_TRACE(WC_NO_PENDING_E))
ret = 0;
#endif
}
@@ -14199,6 +15348,14 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif
}
+#ifdef OPENSSL_EXTRA
+ /* account for verify params flag set */
+ if (AdjustCMForParams(ssl) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Issue with updating store flags from PARAMS set");
+ ERROR_OUT(WOLFSSL_FAILURE, exit_ppc);
+ }
+#endif
+
switch (ssl->options.asyncState)
{
case TLS_ASYNC_BEGIN:
@@ -14292,7 +15449,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);
}
@@ -14370,8 +15545,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
args->idx += extSz;
listSz -= extSz + OPAQUE16_LEN;
WOLFSSL_MSG_EX("\tParsing %d bytes of cert extensions",
- args->exts[args->totalCerts].length);
+ args->exts[args->totalCerts].length);
#if !defined(NO_TLS)
+ #if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
+ ssl->response_idx = args->totalCerts;
+ #endif
ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer,
(word16)args->exts[args->totalCerts].length,
certificate, NULL);
@@ -14492,7 +15670,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
(defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
!defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \
!defined(NO_STDIO_FILESYSTEM)
- if (ret == ASN_NO_SIGNER_E || ret == ASN_SELF_SIGNED_E) {
+ if (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) ||
+ ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)) {
WOLFSSL_MSG("try to load certificate if hash dir is set");
ret = LoadCertByIssuer(SSL_STORE(ssl),
(WOLFSSL_X509_NAME*)args->dCert->issuerName,
@@ -14512,14 +15691,15 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
goto exit_ppc;
#endif
if (ret == 0) {
ret = ProcessPeerCertCheckKey(ssl, args);
}
- else if (ret == ASN_PARSE_E || ret == BUFFER_E ||
- ret == MEMORY_E) {
+ else if (ret == WC_NO_ERR_TRACE(ASN_PARSE_E) ||
+ ret == WC_NO_ERR_TRACE(BUFFER_E) ||
+ ret == WC_NO_ERR_TRACE(MEMORY_E)) {
WOLFSSL_MSG(
"Got Peer cert ASN PARSE_E, BUFFER E, MEMORY_E");
ERROR_OUT(ret, exit_ppc);
@@ -14551,22 +15731,48 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif
}
- if (ret == 0) {
#ifdef HAVE_OCSP
+ if (ret == 0 ||
+ /* Don't enter when args->dCert is potentially in
+ * a bad state. */
+ (ret != WC_NO_ERR_TRACE(ASN_PARSE_E) &&
+ ret != WC_NO_ERR_TRACE(BUFFER_E) &&
+ ret != WC_NO_ERR_TRACE(MEMORY_E) &&
+ ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))) {
+ /* If we are processing OCSP staples then always
+ * initialize the corresponding request. */
+ int ocspRet = 0;
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
- if (ssl->status_request_v2) {
- ret = TLSX_CSR2_InitRequests(ssl->extensions,
+ addToPendingCAs = 0;
+ if (ssl->options.side == WOLFSSL_CLIENT_END &&
+ ssl->status_request_v2 &&
+ TLSX_CSR2_IsMulti(ssl->extensions)) {
+ ocspRet = TLSX_CSR2_InitRequests(ssl->extensions,
args->dCert, 0, ssl->heap);
+ addToPendingCAs = 1;
}
else /* skips OCSP and force CRL check */
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
- if (SSL_CM(ssl)->ocspEnabled &&
+ #if defined(HAVE_CERTIFICATE_STATUS_REQUEST)
+ if (IsAtLeastTLSv1_3(ssl->version) &&
+ ssl->options.side == WOLFSSL_CLIENT_END &&
+ ssl->status_request) {
+ /* We check CSR in Certificate message sent from
+ * Server. Server side will check client
+ * certificates by traditional OCSP if enabled
+ */
+ ocspRet = TLSX_CSR_InitRequest_ex(ssl->extensions,
+ args->dCert, ssl->heap, args->certIdx);
+ }
+ else
+ #endif
+ if (ret == 0 && SSL_CM(ssl)->ocspEnabled &&
SSL_CM(ssl)->ocspCheckAll) {
WOLFSSL_MSG("Doing Non Leaf OCSP check");
ret = CheckCertOCSP_ex(SSL_CM(ssl)->ocsp,
args->dCert, ssl);
#ifdef WOLFSSL_NONBLOCK_OCSP
- if (ret == OCSP_WANT_READ) {
+ if (ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) {
args->lastErr = ret;
goto exit_ppc;
}
@@ -14576,8 +15782,15 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
WOLFSSL_MSG("\tOCSP Lookup not ok");
}
}
+ if (ocspRet != 0) {
+ ret = ocspRet;
+ WOLFSSL_ERROR_VERBOSE(ret);
+ goto exit_ppc;
+ }
+ }
#endif /* HAVE_OCSP */
+ if (ret == 0) {
#ifdef HAVE_CRL
if (SSL_CM(ssl)->crlEnabled &&
SSL_CM(ssl)->crlCheckAll) {
@@ -14590,7 +15803,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
responder, do a CRL lookup. If any other
error, skip the CRL lookup and fail the
certificate. */
- doCrlLookup = (ret == OCSP_CERT_UNKNOWN);
+ doCrlLookup = (ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN));
}
#endif /* HAVE_OCSP */
@@ -14603,19 +15816,21 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
* same WOULD_BLOCK error code as OCSP's I/O
* callback, and it is enabling it using the
* same flag. */
- if (ret == OCSP_WANT_READ) {
+ if (ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) {
args->lastErr = ret;
goto exit_ppc;
}
#endif
+ if (ret != 0)
+ DoCrlCallback(SSL_CM(ssl), ssl, args, &ret);
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(ret);
WOLFSSL_MSG("\tCRL check not ok");
}
if (ret == 0 &&
args->certIdx == args->totalCerts-1) {
- ret = ProcessPeerCertsChainCRLCheck(
- SSL_CM(ssl), args->dCert->ca);
+ ret = ProcessPeerCertsChainCRLCheck(ssl,
+ args);
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(ret);
WOLFSSL_MSG("\tCRL chain check not ok");
@@ -14644,9 +15859,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
chain mode only requires that the peer certificate
validate to a trusted CA */
if (ret != 0 && args->dCert->isCA) {
- if (ret == ASN_NO_SIGNER_E || ret == ASN_SELF_SIGNED_E) {
+ if (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) ||
+ ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)) {
if (!ssl->options.usingAltCertChain) {
- WOLFSSL_MSG("Trying alternate cert chain");
+ WOLFSSL_MSG_CERT_LOG(
+ "Trying alternate cert chain");
ssl->options.usingAltCertChain = 1;
}
@@ -14658,8 +15875,25 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* do not add to certificate manager */
skipAddCA = 1;
+ } /* ASN_NO_SIGNER_E || ASN_SELF_SIGNED_E */
+ } /* ret != 0 && isCA */
+ #else
+ /* Not defined: WOLFSSL_ALT_CERT_CHAINS
+ * When WOLFSSL_DEBUG_CERTS enabled, suggest solution */
+ #ifdef WOLFSSL_DEBUG_CERTS
+ if (ret != 0 && args->dCert->isCA) {
+ if (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)) {
+ WOLFSSL_MSG_CERT(
+ "Consider enabling WOLFSSL_ALT_CERT_CHAINS"
+ " to resolve ASN_NO_SIGNER_E");
}
- }
+ if (ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)) {
+ WOLFSSL_MSG_CERT(
+ "Consider enabling WOLFSSL_ALT_CERT_CHAINS"
+ " to resolve ASN_SELF_SIGNED_E");
+ }
+ } /* check alt-cert possible fixable error codes */
+ #endif
#endif /* WOLFSSL_ALT_CERT_CHAINS */
#if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS)
@@ -14667,7 +15901,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
* for a CA cert to fail validation here, as we will verify
* the entire chain when we hit the peer (leaf) cert */
if ((ssl->ctx->doAppleNativeCertValidationFlag)
- && (ret == ASN_NO_SIGNER_E)) {
+ && (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E))) {
WOLFSSL_MSG("Bypassing errors to allow for Apple native"
" CA validation");
@@ -14685,8 +15919,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* Do verify callback */
ret = DoVerifyCallback(SSL_CM(ssl), ssl, ret, args);
if (ssl->options.verifyNone &&
- (ret == CRL_MISSING || ret == CRL_CERT_REVOKED ||
- ret == CRL_CERT_DATE_ERR)) {
+ (ret == WC_NO_ERR_TRACE(CRL_MISSING) ||
+ ret == WC_NO_ERR_TRACE(CRL_CERT_REVOKED) ||
+ ret == WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR))) {
WOLFSSL_MSG("Ignoring CRL problem based on verify setting");
ret = ssl->error = 0;
}
@@ -14697,6 +15932,58 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
skipAddCA = 1;
}
#endif
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ if (ret == 0 && addToPendingCAs && !alreadySigner) {
+ WC_DECLARE_VAR(dCertAdd, DecodedCert, 1, 0);
+ int dCertAdd_inited = 0;
+ DerBuffer *derBuffer = NULL;
+ buffer* cert = &args->certs[args->certIdx];
+ Signer *s = NULL;
+
+ WC_ALLOC_VAR_EX(dCertAdd, DecodedCert, 1, ssl->heap,
+ DYNAMIC_TYPE_TMP_BUFFER,
+ {
+ ret=MEMORY_E;
+ goto exit_req_v2;
+ });
+ InitDecodedCert(dCertAdd, cert->buffer, cert->length,
+ ssl->heap);
+ dCertAdd_inited = 1;
+ ret = ParseCert(dCertAdd, CA_TYPE, NO_VERIFY,
+ SSL_CM(ssl));
+ if (ret != 0) {
+ goto exit_req_v2;
+ }
+ ret = AllocDer(&derBuffer, cert->length, CA_TYPE, ssl->heap);
+ if (ret != 0 || derBuffer == NULL) {
+ goto exit_req_v2;
+ }
+ XMEMCPY(derBuffer->buffer, cert->buffer, cert->length);
+ s = MakeSigner(SSL_CM(ssl)->heap);
+ if (s == NULL) {
+ ret = MEMORY_E;
+ goto exit_req_v2;
+ }
+ ret = FillSigner(s, dCertAdd, CA_TYPE, derBuffer);
+ if (ret != 0) {
+ goto exit_req_v2;
+ }
+ skipAddCA = 1;
+ ret = TLSX_CSR2_AddPendingSigner(ssl->extensions, s);
+
+ exit_req_v2:
+ if (s && (ret != 0))
+ FreeSigner(s, SSL_CM(ssl)->heap);
+ if (derBuffer)
+ FreeDer(&derBuffer);
+ if (dCertAdd_inited)
+ FreeDecodedCert(dCertAdd);
+ WC_FREE_VAR_EX(dCertAdd, ssl->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (ret != 0)
+ goto exit_ppc;
+ }
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
/* If valid CA then add to Certificate Manager */
if (ret == 0 && args->dCert->isCA &&
@@ -14779,7 +16066,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
(defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
!defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \
!defined(NO_STDIO_FILESYSTEM)
- if (ret == ASN_NO_SIGNER_E || ret == ASN_SELF_SIGNED_E) {
+ if (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) ||
+ ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)) {
int lastErr = ret; /* save error from last time */
WOLFSSL_MSG("try to load certificate if hash dir is set");
ret = LoadCertByIssuer(SSL_STORE(ssl),
@@ -14800,9 +16088,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
goto exit_ppc;
#endif
+
if (ret == 0) {
WOLFSSL_MSG("Verified Peer's cert");
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
@@ -14857,8 +16146,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
args->fatal = 0;
}
}
- else if (ret == ASN_PARSE_E || ret == BUFFER_E ||
- ret == MEMORY_E || ret == BAD_FUNC_ARG) {
+ else if (ret == WC_NO_ERR_TRACE(ASN_PARSE_E) ||
+ ret == WC_NO_ERR_TRACE(BUFFER_E) ||
+ ret == WC_NO_ERR_TRACE(MEMORY_E) ||
+ ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG)) {
WOLFSSL_MSG("Got Peer cert ASN_PARSE_E, BUFFER_E, MEMORY_E,"
" BAD_FUNC_ARG");
#if defined(WOLFSSL_EXTRA_ALERTS) || defined(OPENSSL_EXTRA) || \
@@ -14876,11 +16167,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
if (ssl->peerVerifyRet == 0) { /* Return first cert error here */
- if (ret == ASN_BEFORE_DATE_E) {
+ if (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) {
ssl->peerVerifyRet =
(unsigned long)WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID;
}
- else if (ret == ASN_AFTER_DATE_E) {
+ else if (ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) {
ssl->peerVerifyRet =
(unsigned long)WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED;
}
@@ -14892,18 +16183,14 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif
- if (ssl->verifyCallback) {
- WOLFSSL_MSG(
- "\tCallback override available, will continue");
- /* check if fatal error */
- args->fatal = (args->verifyErr) ? 1 : 0;
- if (args->fatal)
- DoCertFatalAlert(ssl, ret);
- }
+ /* Do verify callback. */
+ args->leafVerifyErr = ret =
+ DoVerifyCallback(SSL_CM(ssl), ssl, ret, args);
+
#if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS)
/* Disregard failure to verify peer cert, as we will verify
* the whole chain with the native API later */
- else if (ssl->ctx->doAppleNativeCertValidationFlag) {
+ if (ssl->ctx->doAppleNativeCertValidationFlag) {
WOLFSSL_MSG("\tApple native CA validation override"
" available, will continue");
/* check if fatal error */
@@ -14911,9 +16198,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (args->fatal)
DoCertFatalAlert(ssl, ret);
}
+ else
#endif/*defined(__APPLE__)&& defined(WOLFSSL_SYS_CA_CERTS)*/
- else {
- WOLFSSL_MSG("\tNo callback override available, fatal");
+ if (ret != 0) {
+ WOLFSSL_MSG("\tfatal cert error");
args->fatal = 1;
DoCertFatalAlert(ssl, ret);
}
@@ -14973,24 +16261,17 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->options.side == WOLFSSL_CLIENT_END) {
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (ssl->status_request) {
- args->fatal = (TLSX_CSR_InitRequest(ssl->extensions,
- args->dCert, ssl->heap) != 0);
+ args->fatal = (TLSX_CSR_InitRequest_ex(
+ ssl->extensions, args->dCert,
+ ssl->heap, args->certIdx) != 0);
doLookup = 0;
WOLFSSL_MSG("\tHave status request");
#if defined(WOLFSSL_TLS13)
if (ssl->options.tls1_3) {
- TLSX* ext = TLSX_Find(ssl->extensions,
- TLSX_STATUS_REQUEST);
- if (ext != NULL) {
- word32 idx = 0;
- CertificateStatusRequest* csr =
- (CertificateStatusRequest*)ext->data;
- ret = ProcessCSR(ssl, csr->response.buffer,
- &idx, csr->response.length);
- if (ret < 0) {
- WOLFSSL_ERROR_VERBOSE(ret);
- goto exit_ppc;
- }
+ ret = ProcessPeerCertsChainOCSPStatusCheck(ssl);
+ if (ret < 0) {
+ WOLFSSL_ERROR_VERBOSE(ret);
+ goto exit_ppc;
}
}
#endif
@@ -15018,11 +16299,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = CheckCertOCSP_ex(SSL_CM(ssl)->ocsp,
args->dCert, ssl);
#ifdef WOLFSSL_NONBLOCK_OCSP
- if (ret == OCSP_WANT_READ) {
+ if (ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) {
goto exit_ppc;
}
#endif
- doLookup = (ret == OCSP_CERT_UNKNOWN);
+ doLookup = (ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN));
if (ret != 0) {
WOLFSSL_MSG("\tOCSP Lookup not ok");
args->fatal = 0;
@@ -15030,9 +16311,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->peerVerifyRet == 0) {
/* Return first cert error here */
ssl->peerVerifyRet =
- ret == OCSP_CERT_REVOKED
- ? WOLFSSL_X509_V_ERR_CERT_REVOKED
- : WOLFSSL_X509_V_ERR_CERT_REJECTED;
+ ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED)
+ ? WOLFSSL_X509_V_ERR_CERT_REVOKED
+ : WOLFSSL_X509_V_ERR_CERT_REJECTED;
}
#endif
}
@@ -15048,10 +16329,12 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
* same WOULD_BLOCK error code as OCSP's I/O
* callback, and it is enabling it using the
* same flag. */
- if (ret == OCSP_WANT_READ) {
+ if (ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) {
goto exit_ppc;
}
#endif
+ if (ret != 0)
+ DoCrlCallback(SSL_CM(ssl), ssl, args, &ret);
if (ret != 0) {
WOLFSSL_MSG("\tCRL check not ok");
args->fatal = 0;
@@ -15059,7 +16342,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->peerVerifyRet == 0) {
/* Return first cert error here */
ssl->peerVerifyRet =
- ret == CRL_CERT_REVOKED
+ ret == WC_NO_ERR_TRACE(CRL_CERT_REVOKED)
? WOLFSSL_X509_V_ERR_CERT_REVOKED
: WOLFSSL_X509_V_ERR_CERT_REJECTED;
}
@@ -15070,8 +16353,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
SSL_CM(ssl)->crlCheckAll && args->totalCerts == 1) {
/* Check the entire cert chain */
if (args->dCert->ca != NULL) {
- ret = ProcessPeerCertsChainCRLCheck(SSL_CM(ssl),
- args->dCert->ca);
+ ret = ProcessPeerCertsChainCRLCheck(ssl, args);
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(ret);
WOLFSSL_MSG("\tCRL chain check not ok");
@@ -15091,28 +16373,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (args->fatal == 0) {
int copyRet = 0;
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- if (ssl->options.handShakeDone) {
- FreeX509(&ssl->peerCert);
- InitX509(&ssl->peerCert, 0, ssl->heap);
- }
- else
- #endif
- #ifdef HAVE_SECURE_RENEGOTIATION
- if (ssl->secure_renegotiation &&
- ssl->secure_renegotiation->enabled) {
- /* free old peer cert */
- FreeX509(&ssl->peerCert);
- InitX509(&ssl->peerCert, 0, ssl->heap);
- }
- else
- #endif
- {
- }
-
- /* set X509 format for peer cert */
+ /* free old peer cert */
+ FreeX509(&ssl->peerCert);
+ InitX509(&ssl->peerCert, 0, ssl->heap);
copyRet = CopyDecodedToX509(&ssl->peerCert, args->dCert);
- if (copyRet == MEMORY_E) {
+ if (copyRet == WC_NO_ERR_TRACE(MEMORY_E)) {
args->fatal = 1;
}
}
@@ -15204,7 +16469,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif
-
if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
#ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN
/* Per RFC 5280 section 4.2.1.6, "Whenever such identities
@@ -15213,7 +16477,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (args->dCert->altNames) {
if (CheckForAltNames(args->dCert,
(char*)ssl->buffers.domainName.buffer,
- NULL) != 1) {
+ (ssl->buffers.domainName.buffer == NULL ? 0 :
+ (word32)XSTRLEN(
+ (const char *)ssl->buffers.domainName.buffer)),
+ NULL, 0, 0) != 1) {
WOLFSSL_MSG("DomainName match on alt names failed");
/* try to get peer key still */
ret = DOMAIN_NAME_MISMATCH;
@@ -15221,26 +16488,38 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
}
else {
+ #ifndef WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY
if (MatchDomainName(
- args->dCert->subjectCN,
- args->dCert->subjectCNLen,
- (char*)ssl->buffers.domainName.buffer) == 0) {
- WOLFSSL_MSG("DomainName match on common name failed");
+ args->dCert->subjectCN,
+ args->dCert->subjectCNLen,
+ (char*)ssl->buffers.domainName.buffer,
+ (ssl->buffers.domainName.buffer == NULL ? 0 :
+ (word32)XSTRLEN(
+ (const char *)ssl->buffers.domainName.buffer)
+ ), 0) == 0)
+ #endif
+ {
+ WOLFSSL_MSG("DomainName match failed");
ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
}
}
#else /* WOLFSSL_ALL_NO_CN_IN_SAN */
/* Old behavior. */
+ #ifndef WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY
if (MatchDomainName(args->dCert->subjectCN,
args->dCert->subjectCNLen,
- (char*)ssl->buffers.domainName.buffer) == 0) {
- WOLFSSL_MSG("DomainName match on common name failed");
+ (char*)ssl->buffers.domainName.buffer,
+ (ssl->buffers.domainName.buffer == NULL ? 0 :
+ (word32)XSTRLEN(ssl->buffers.domainName.buffer)), 0) == 0)
+ #endif
+ {
if (CheckForAltNames(args->dCert,
(char*)ssl->buffers.domainName.buffer,
- NULL) != 1) {
- WOLFSSL_MSG(
- "DomainName match on alt names failed too");
+ (ssl->buffers.domainName.buffer == NULL ? 0 :
+ (word32)XSTRLEN(ssl->buffers.domainName.buffer)),
+ NULL, 0) != 1) {
+ WOLFSSL_MSG("DomainName match failed");
/* try to get peer key still */
ret = DOMAIN_NAME_MISMATCH;
WOLFSSL_ERROR_VERBOSE(ret);
@@ -15529,7 +16808,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
break;
}
#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */
- #if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
case FALCON_LEVEL1k:
case FALCON_LEVEL5k:
@@ -15579,10 +16857,16 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
break;
}
#endif /* HAVE_FALCON */
- #if defined(HAVE_DILITHIUM)
+ #if defined(HAVE_DILITHIUM) && \
+ !defined(WOLFSSL_DILITHIUM_NO_VERIFY)
+ case ML_DSA_LEVEL2k:
+ case ML_DSA_LEVEL3k:
+ case ML_DSA_LEVEL5k:
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
case DILITHIUM_LEVEL2k:
case DILITHIUM_LEVEL3k:
case DILITHIUM_LEVEL5k:
+ #endif
{
int keyRet = 0;
if (ssl->peerDilithiumKey == NULL) {
@@ -15596,18 +16880,32 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
if (keyRet == 0) {
- if (args->dCert->keyOID == DILITHIUM_LEVEL2k) {
+ if (args->dCert->keyOID == ML_DSA_LEVEL2k) {
+ keyRet = wc_dilithium_set_level(
+ ssl->peerDilithiumKey, WC_ML_DSA_44);
+ }
+ else if (args->dCert->keyOID == ML_DSA_LEVEL3k) {
+ keyRet = wc_dilithium_set_level(
+ ssl->peerDilithiumKey, WC_ML_DSA_65);
+ }
+ else if (args->dCert->keyOID == ML_DSA_LEVEL5k) {
+ keyRet = wc_dilithium_set_level(
+ ssl->peerDilithiumKey, WC_ML_DSA_87);
+ }
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ else if (args->dCert->keyOID == DILITHIUM_LEVEL2k) {
keyRet = wc_dilithium_set_level(
- ssl->peerDilithiumKey, 2);
+ ssl->peerDilithiumKey, WC_ML_DSA_44_DRAFT);
}
else if (args->dCert->keyOID == DILITHIUM_LEVEL3k) {
keyRet = wc_dilithium_set_level(
- ssl->peerDilithiumKey, 3);
+ ssl->peerDilithiumKey, WC_ML_DSA_65_DRAFT);
}
else if (args->dCert->keyOID == DILITHIUM_LEVEL5k) {
keyRet = wc_dilithium_set_level(
- ssl->peerDilithiumKey, 5);
+ ssl->peerDilithiumKey, WC_ML_DSA_87_DRAFT);
}
+ #endif
}
if (keyRet != 0 ||
@@ -15632,7 +16930,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
break;
}
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
default:
break;
}
@@ -15675,8 +16972,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* If we can't validate the peer cert chain against the CAs loaded
* into wolfSSL, try to validate against the system certificates
* using Apple's native trust APIs */
- if ((ret != 0) && (ssl->ctx->doAppleNativeCertValidationFlag)) {
- if (DoAppleNativeCertValidation(args->certs,
+ if ((ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)) &&
+ (ssl->ctx->doAppleNativeCertValidationFlag)) {
+ if (DoAppleNativeCertValidation(ssl, args->certs,
args->totalCerts)) {
WOLFSSL_MSG("Apple native cert chain validation SUCCESS");
ret = 0;
@@ -15687,12 +16985,14 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */
- /* Do verify callback */
- ret = DoVerifyCallback(SSL_CM(ssl), ssl, ret, args);
+ /* Do leaf verify callback when it wasn't called yet */
+ if (ret == 0 || ret != args->leafVerifyErr)
+ ret = DoVerifyCallback(SSL_CM(ssl), ssl, ret, args);
if (ssl->options.verifyNone &&
- (ret == CRL_MISSING || ret == CRL_CERT_REVOKED ||
- ret == CRL_CERT_DATE_ERR)) {
+ (ret == WC_NO_ERR_TRACE(CRL_MISSING) ||
+ ret == WC_NO_ERR_TRACE(CRL_CERT_REVOKED) ||
+ ret == WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR))) {
WOLFSSL_MSG("Ignoring CRL problem based on verify setting");
ret = ssl->error = 0;
}
@@ -15708,13 +17008,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ssl->options.serverState = SERVER_CERT_COMPLETE;
}
- if (IsEncryptionOn(ssl, 0)) {
+ if (IsEncryptionOn(ssl, 0))
args->idx += ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- args->idx += MacSize(ssl);
- #endif
- }
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_END;
@@ -15739,7 +17034,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
- if (ret == WC_PENDING_E || ret == OCSP_WANT_READ) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) ||
+ ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) {
/* Mark message as not received so it can process again */
ssl->msgsReceived.got_certificate = 0;
@@ -15769,7 +17065,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif
-#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_TLS) && !defined(WOLFSSL_NO_TLS12)
#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
/* handle processing of certificate (11) */
@@ -15785,7 +17081,8 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* Reset the session cert chain count in case the session resume failed,
* do not reset if we are resuming after an async wait */
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
- if (ssl->error != OCSP_WANT_READ && ssl->error != WC_PENDING_E)
+ if (ssl->error != WC_NO_ERR_TRACE(OCSP_WANT_READ) &&
+ ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
ssl->session->chain.count = 0;
@@ -15814,6 +17111,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
int ret = 0;
byte status_type;
word32 status_length;
+ int endCertificateOK = 0;
WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_DO);
WOLFSSL_ENTER("DoCertificateStatus");
@@ -15837,6 +17135,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */
case WOLFSSL_CSR2_OCSP:
ret = ProcessCSR(ssl, input, inOutIdx, status_length);
+ endCertificateOK = (ret == 0);
break;
#endif
@@ -15847,6 +17146,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
OcspRequest* request;
word32 list_length = status_length;
byte idx = 0;
+ Signer *pendingCAs = NULL;
#ifdef WOLFSSL_SMALL_STACK
CertStatus* status;
@@ -15858,14 +17158,12 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
OcspResponse response[1];
#endif
- do {
- if (ssl->status_request_v2) {
- ssl->status_request_v2 = 0;
- break;
- }
-
+ if (!ssl->status_request_v2)
return BUFFER_ERROR;
- } while(0);
+
+ ssl->status_request_v2 = 0;
+
+ pendingCAs = TLSX_CSR2_GetPendingSigners(ssl->extensions);
#ifdef WOLFSSL_SMALL_STACK
status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap,
@@ -15876,12 +17174,9 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
DYNAMIC_TYPE_OCSP_REQUEST);
if (status == NULL || single == NULL || response == NULL) {
- if (status)
- XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
- if (single)
- XFREE(single, ssl->heap, DYNAMIC_TYPE_OCSP_ENTRY);
- if (response)
- XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS);
+ XFREE(single, ssl->heap, DYNAMIC_TYPE_OCSP_ENTRY);
+ XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
return MEMORY_ERROR;
}
@@ -15905,40 +17200,44 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (status_length) {
InitOcspResponse(response, single, status, input +*inOutIdx,
status_length, ssl->heap);
-
+ response->pendingCAs = pendingCAs;
if ((OcspResponseDecode(response, SSL_CM(ssl), ssl->heap,
- 0) != 0)
+ 0, 0) != 0)
|| (response->responseStatus != OCSP_SUCCESSFUL)
|| (response->single->status->status != CERT_GOOD))
ret = BAD_CERTIFICATE_STATUS_ERROR;
- while (ret == 0) {
+ if (ret == 0) {
request = (OcspRequest*)TLSX_CSR2_GetRequest(
- ssl->extensions, status_type, idx++);
+ ssl->extensions, status_type, idx);
- if (request == NULL)
+ if (request == NULL) {
ret = BAD_CERTIFICATE_STATUS_ERROR;
- else if (CompareOcspReqResp(request, response) == 0)
- break;
- else if (idx == 1) /* server cert must be OK */
+ }
+ else if (CompareOcspReqResp(request, response) != 0) {
ret = BAD_CERTIFICATE_STATUS_ERROR;
+ }
}
/* only frees 'single' if single->isDynamic is set */
FreeOcspResponse(response);
+ ret = CsrDoStatusVerifyCb(ssl, input + *inOutIdx, status_length,
+ idx, ret);
+ if (ret == 0 && idx == 0) /* server cert must be OK */
+ endCertificateOK = 1;
+
*inOutIdx += status_length;
list_length -= status_length;
}
+ idx++;
}
ssl->status_request_v2 = 0;
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS);
- XFREE(single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
- XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
- #endif
+ WC_FREE_VAR_EX(status, NULL, DYNAMIC_TYPE_OCSP_STATUS);
+ WC_FREE_VAR_EX(single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
+ WC_FREE_VAR_EX(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
}
break;
@@ -15949,26 +17248,29 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = BUFFER_ERROR;
}
+ /* end certificate MUST be present */
+ if (endCertificateOK == 0)
+ ret = BAD_CERTIFICATE_STATUS_ERROR;
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ if (ret == 0) {
+ if (TLSX_CSR2_MergePendingCA(ssl) < 0) {
+ WOLFSSL_MSG("Failed to merge pending CAs");
+ }
+ }
+ else {
+ TLSX_CSR2_ClearPendingCA(ssl);
+ }
+#endif
+
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(ret);
SendAlert(ssl, alert_fatal, bad_certificate_status_response);
}
if (IsEncryptionOn(ssl, 0)) {
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead) {
- word32 digestSz = MacSize(ssl);
- if (*inOutIdx + ssl->keys.padSz + digestSz > size)
- return BUFFER_E;
- *inOutIdx += ssl->keys.padSz + digestSz;
- }
- else
- #endif
- {
- if (*inOutIdx + ssl->keys.padSz > size)
- return BUFFER_E;
- *inOutIdx += ssl->keys.padSz;
- }
+ if (*inOutIdx + ssl->keys.padSz > size)
+ return BUFFER_E;
+ *inOutIdx += ssl->keys.padSz;
}
WOLFSSL_LEAVE("DoCertificateStatus", ret);
@@ -15979,11 +17281,11 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#endif
-#endif /* !WOLFSSL_NO_TLS12 */
+#endif /* !NO_TLS && !WOLFSSL_NO_TLS12 */
#endif /* !NO_CERTS */
-#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_TLS) && !defined(WOLFSSL_NO_TLS12)
static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32 size, word32 totalSz)
@@ -15999,24 +17301,12 @@ static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (IsEncryptionOn(ssl, 0)) {
/* If size == totalSz then we are in DtlsMsgDrain so no need to worry
* about padding */
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead) {
- word32 digestSz = MacSize(ssl);
- if (size != totalSz &&
- *inOutIdx + ssl->keys.padSz + digestSz > totalSz)
- return BUFFER_E;
- *inOutIdx += ssl->keys.padSz + digestSz;
- }
- else
- #endif
- {
- /* access beyond input + size should be checked against totalSz */
- if (size != totalSz &&
- *inOutIdx + ssl->keys.padSz > totalSz)
- return BUFFER_E;
+ /* access beyond input + size should be checked against totalSz */
+ if (size != totalSz &&
+ *inOutIdx + ssl->keys.padSz > totalSz)
+ return BUFFER_E;
- *inOutIdx += ssl->keys.padSz;
- }
+ *inOutIdx += ssl->keys.padSz;
}
if (ssl->options.side == WOLFSSL_SERVER_END) {
@@ -16053,17 +17343,8 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
* If size == totalSz then we are in DtlsMsgDrain so no need to worry about
* padding */
if (size != totalSz) {
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead) {
- if (*inOutIdx + size + ssl->keys.padSz + MacSize(ssl) > totalSz)
- return BUFFER_E;
- }
- else
- #endif
- {
- if (*inOutIdx + size + ssl->keys.padSz > totalSz)
- return BUFFER_E;
- }
+ if (*inOutIdx + size + ssl->keys.padSz > totalSz)
+ return BUFFER_E;
}
#ifdef WOLFSSL_CALLBACKS
@@ -16106,21 +17387,17 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
/* force input exhaustion at ProcessReply consuming padSz */
*inOutIdx += size + ssl->keys.padSz;
-#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- *inOutIdx += MacSize(ssl);
-#endif
if (ssl->options.side == WOLFSSL_CLIENT_END) {
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
#ifdef OPENSSL_EXTRA
- ssl->cbmode = SSL_CB_MODE_WRITE;
+ ssl->cbmode = WOLFSSL_CB_MODE_WRITE;
ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
#endif
if (!ssl->options.resuming) {
#ifdef OPENSSL_EXTRA
if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_CONNECT_LOOP, WOLFSSL_SUCCESS);
}
#endif
ssl->options.handShakeState = HANDSHAKE_DONE;
@@ -16133,13 +17410,13 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
else {
ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
#ifdef OPENSSL_EXTRA
- ssl->cbmode = SSL_CB_MODE_READ;
+ ssl->cbmode = WOLFSSL_CB_MODE_READ;
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
#endif
if (ssl->options.resuming) {
#ifdef OPENSSL_EXTRA
if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_ACCEPT_LOOP, WOLFSSL_SUCCESS);
}
#endif
ssl->options.handShakeState = HANDSHAKE_DONE;
@@ -16268,6 +17545,15 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
return DUPLICATE_MSG_E;
}
+ if (!ssl->msgsReceived.got_server_hello ||
+ ssl->msgsReceived.got_change_cipher ||
+ ssl->msgsReceived.got_finished ||
+ (!ssl->options.resuming &&
+ !ssl->msgsReceived.got_server_hello_done)) {
+ WOLFSSL_MSG("session_ticket received in wrong order");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
ssl->msgsReceived.got_session_ticket = 1;
break;
@@ -16283,20 +17569,36 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
#ifndef NO_WOLFSSL_CLIENT
if (ssl->options.side == WOLFSSL_CLIENT_END) {
- if ( ssl->msgsReceived.got_server_hello == 0) {
+ if (!ssl->msgsReceived.got_server_hello) {
WOLFSSL_MSG("No ServerHello before Cert");
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
return OUT_OF_ORDER_E;
}
+ if (ssl->msgsReceived.got_certificate_status ||
+ ssl->msgsReceived.got_server_key_exchange ||
+ ssl->msgsReceived.got_certificate_request ||
+ ssl->msgsReceived.got_server_hello_done) {
+ WOLFSSL_MSG("Cert received in wrong order");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
}
#endif
#ifndef NO_WOLFSSL_SERVER
if (ssl->options.side == WOLFSSL_SERVER_END) {
- if ( ssl->msgsReceived.got_client_hello == 0) {
+ if (!ssl->msgsReceived.got_client_hello) {
WOLFSSL_MSG("No ClientHello before Cert");
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
return OUT_OF_ORDER_E;
}
+ if (ssl->msgsReceived.got_client_key_exchange ||
+ ssl->msgsReceived.got_certificate_verify ||
+ ssl->msgsReceived.got_change_cipher ||
+ ssl->msgsReceived.got_finished) {
+ WOLFSSL_MSG("Cert received in wrong order");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
}
#endif
break;
@@ -16315,7 +17617,6 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
return DUPLICATE_MSG_E;
}
- ssl->msgsReceived.got_certificate_status = 1;
if (ssl->msgsReceived.got_certificate == 0) {
WOLFSSL_MSG("No Certificate before CertificateStatus");
@@ -16327,7 +17628,15 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
return OUT_OF_ORDER_E;
}
+ if (ssl->msgsReceived.got_server_key_exchange ||
+ ssl->msgsReceived.got_certificate_request ||
+ ssl->msgsReceived.got_server_hello_done) {
+ WOLFSSL_MSG("CertificateStatus received in wrong order");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+ ssl->msgsReceived.got_certificate_status = 1;
break;
#endif
@@ -16345,28 +17654,139 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
return DUPLICATE_MSG_E;
}
+ if (ssl->msgsReceived.got_server_hello == 0) {
+ WOLFSSL_MSG("No ServerHello before ServerKeyExchange");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+ if (ssl->msgsReceived.got_certificate_request ||
+ ssl->msgsReceived.got_server_hello_done) {
+ WOLFSSL_MSG("ServerKeyExchange received in wrong order");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+
ssl->msgsReceived.got_server_key_exchange = 1;
+ break;
+#endif
+#ifndef NO_WOLFSSL_CLIENT
+ case certificate_request:
+ #ifndef NO_WOLFSSL_SERVER
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+ WOLFSSL_MSG("CertificateRequest received by server");
+ WOLFSSL_ERROR_VERBOSE(SIDE_ERROR);
+ return SIDE_ERROR;
+ }
+ #endif
+ if (ssl->msgsReceived.got_certificate_request) {
+ WOLFSSL_MSG("Duplicate CertificateRequest received");
+ WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
+ return DUPLICATE_MSG_E;
+ }
if (ssl->msgsReceived.got_server_hello == 0) {
- WOLFSSL_MSG("No ServerHello before ServerKeyExchange");
+ WOLFSSL_MSG("No ServerHello before CertificateRequest");
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
return OUT_OF_ORDER_E;
}
+ if (!ssl->options.resuming && ssl->specs.kea != rsa_kea &&
+ (ssl->specs.kea != ecc_diffie_hellman_kea ||
+ !ssl->specs.static_ecdh) &&
+ ssl->specs.kea != ecc_static_diffie_hellman_kea &&
+ !ssl->msgsReceived.got_server_key_exchange) {
+ WOLFSSL_MSG("No ServerKeyExchange before CertificateRequest");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+ if (!ssl->msgsReceived.got_certificate) {
+ WOLFSSL_MSG("No Certificate before CertificateRequest");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+ if (ssl->msgsReceived.got_server_hello_done) {
+ WOLFSSL_MSG("CertificateRequest received in wrong order");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+ ssl->msgsReceived.got_certificate_request = 1;
+
+ break;
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+ case server_hello_done:
+ #ifndef NO_WOLFSSL_SERVER
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+ WOLFSSL_MSG("ServerHelloDone received by server");
+ WOLFSSL_ERROR_VERBOSE(SIDE_ERROR);
+ return SIDE_ERROR;
+ }
+ #endif
+ if (ssl->msgsReceived.got_server_hello_done) {
+ WOLFSSL_MSG("Duplicate ServerHelloDone received");
+ WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
+ return DUPLICATE_MSG_E;
+ }
+ ssl->msgsReceived.got_server_hello_done = 1;
+
+ if (ssl->msgsReceived.got_certificate == 0) {
+ if (ssl->specs.kea == psk_kea ||
+ ssl->specs.kea == dhe_psk_kea ||
+ ssl->specs.kea == ecdhe_psk_kea ||
+ ssl->options.usingAnon_cipher) {
+ WOLFSSL_MSG("No Cert required");
+ }
+ else {
+ WOLFSSL_MSG("No Certificate before ServerHelloDone");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+ }
+ if (ssl->msgsReceived.got_server_key_exchange == 0) {
+ int pskNoServerHint = 0; /* not required in this case */
+
+ #ifndef NO_PSK
+ if (ssl->specs.kea == psk_kea &&
+ ssl->arrays != NULL &&
+ ssl->arrays->server_hint[0] == 0)
+ pskNoServerHint = 1;
+ #endif
+ if (ssl->specs.static_ecdh == 1 ||
+ ssl->specs.kea == rsa_kea ||
+ pskNoServerHint) {
+ WOLFSSL_MSG("No KeyExchange required");
+ }
+ else {
+ WOLFSSL_MSG("No ServerKeyExchange before ServerDone");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+ }
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
if (ssl->msgsReceived.got_certificate_status == 0) {
int csrRet = 0;
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
if (csrRet == 0 && ssl->status_request) {
- WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
+ WOLFSSL_MSG("No CertificateStatus before ServerHelloDone");
csrRet = TLSX_CSR_ForceRequest(ssl);
}
#endif
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
if (csrRet == 0 && ssl->status_request_v2) {
- WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange");
+ WOLFSSL_MSG("No CertificateStatus before ServerHelloDone");
csrRet = TLSX_CSR2_ForceRequest(ssl);
}
+ if (ssl->status_request_v2) {
+ if (csrRet == 0) {
+ if (TLSX_CSR2_MergePendingCA(ssl) < 0) {
+ WOLFSSL_MSG("Failed to merge pending CAs");
+ }
+ }
+ else {
+ TLSX_CSR2_ClearPendingCA(ssl);
+ }
+ }
#endif
if (csrRet != 0) {
/* Error out if OCSP lookups are enabled and failed or if
@@ -16390,78 +17810,6 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
}
}
#endif
-
- break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
- case certificate_request:
- #ifndef NO_WOLFSSL_SERVER
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- WOLFSSL_MSG("CertificateRequest received by server");
- WOLFSSL_ERROR_VERBOSE(SIDE_ERROR);
- return SIDE_ERROR;
- }
- #endif
- if (ssl->msgsReceived.got_certificate_request) {
- WOLFSSL_MSG("Duplicate CertificateRequest received");
- WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
- return DUPLICATE_MSG_E;
- }
- ssl->msgsReceived.got_certificate_request = 1;
-
- break;
-#endif
-
-#ifndef NO_WOLFSSL_CLIENT
- case server_hello_done:
- #ifndef NO_WOLFSSL_SERVER
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- WOLFSSL_MSG("ServerHelloDone received by server");
- WOLFSSL_ERROR_VERBOSE(SIDE_ERROR);
- return SIDE_ERROR;
- }
- #endif
- if (ssl->msgsReceived.got_server_hello_done) {
- WOLFSSL_MSG("Duplicate ServerHelloDone received");
- WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
- return DUPLICATE_MSG_E;
- }
- ssl->msgsReceived.got_server_hello_done = 1;
-
- if (ssl->msgsReceived.got_certificate == 0) {
- if (ssl->specs.kea == psk_kea ||
- ssl->specs.kea == dhe_psk_kea ||
- ssl->specs.kea == ecdhe_psk_kea ||
- ssl->options.usingAnon_cipher) {
- WOLFSSL_MSG("No Cert required");
- }
- else {
- WOLFSSL_MSG("No Certificate before ServerHelloDone");
- WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
- return OUT_OF_ORDER_E;
- }
- }
- if (ssl->msgsReceived.got_server_key_exchange == 0) {
- int pskNoServerHint = 0; /* not required in this case */
-
- #ifndef NO_PSK
- if (ssl->specs.kea == psk_kea &&
- ssl->arrays != NULL &&
- ssl->arrays->server_hint[0] == 0)
- pskNoServerHint = 1;
- #endif
- if (ssl->specs.static_ecdh == 1 ||
- ssl->specs.kea == rsa_kea ||
- pskNoServerHint) {
- WOLFSSL_MSG("No KeyExchange required");
- }
- else {
- WOLFSSL_MSG("No ServerKeyExchange before ServerDone");
- WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
- return OUT_OF_ORDER_E;
- }
- }
break;
#endif
@@ -16479,13 +17827,18 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
return DUPLICATE_MSG_E;
}
- ssl->msgsReceived.got_certificate_verify = 1;
-
if ( ssl->msgsReceived.got_certificate == 0) {
WOLFSSL_MSG("No Cert before CertVerify");
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
return OUT_OF_ORDER_E;
}
+ if (ssl->msgsReceived.got_change_cipher ||
+ ssl->msgsReceived.got_finished) {
+ WOLFSSL_MSG("CertVerify received in wrong order");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+ ssl->msgsReceived.got_certificate_verify = 1;
break;
#endif
@@ -16503,13 +17856,19 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
return DUPLICATE_MSG_E;
}
- ssl->msgsReceived.got_client_key_exchange = 1;
-
if (ssl->msgsReceived.got_client_hello == 0) {
WOLFSSL_MSG("No ClientHello before ClientKeyExchange");
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
return OUT_OF_ORDER_E;
}
+ if (ssl->msgsReceived.got_certificate_verify||
+ ssl->msgsReceived.got_change_cipher ||
+ ssl->msgsReceived.got_finished) {
+ WOLFSSL_MSG("ClientKeyExchange received in wrong order");
+ WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
+ return OUT_OF_ORDER_E;
+ }
+ ssl->msgsReceived.got_client_key_exchange = 1;
break;
#endif
@@ -16528,13 +17887,12 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
}
}
#endif
- ssl->msgsReceived.got_finished = 1;
-
if (ssl->msgsReceived.got_change_cipher == 0) {
WOLFSSL_MSG("Finished received before ChangeCipher");
WOLFSSL_ERROR_VERBOSE(NO_CHANGE_CIPHER_E);
return NO_CHANGE_CIPHER_E;
}
+ ssl->msgsReceived.got_finished = 1;
break;
case change_cipher_hs:
@@ -16607,7 +17965,7 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
}
#endif
}
-#endif
+#endif /* !NO_WOLFSSL_SERVER */
if (ssl->options.dtls)
ssl->msgsReceived.got_change_cipher = 1;
break;
@@ -16621,7 +17979,6 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
return 0;
}
-
int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
byte type, word32 size, word32 totalSz)
{
@@ -16646,10 +18003,6 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
expectedIdx = *inOutIdx + size +
(ssl->keys.encryptionOn ? ssl->keys.padSz : 0);
-#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead && ssl->keys.encryptionOn)
- expectedIdx += MacSize(ssl);
-#endif
#if !defined(NO_WOLFSSL_SERVER) && \
defined(HAVE_SECURE_RENEGOTIATION) && \
@@ -16732,13 +18085,13 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* hello_request not hashed */
if (type != hello_request
#ifdef WOLFSSL_ASYNC_CRYPT
- && ssl->error != WC_PENDING_E
+ && ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
#ifdef WOLFSSL_NONBLOCK_OCSP
- && ssl->error != OCSP_WANT_READ
+ && ssl->error != WC_NO_ERR_TRACE(OCSP_WANT_READ)
#endif
) {
- ret = HashInput(ssl, input + *inOutIdx, size);
+ ret = HashInput(ssl, input + *inOutIdx, (int)size);
if (ret != 0) {
WOLFSSL_MSG("Incomplete handshake hashes");
return ret;
@@ -16752,6 +18105,18 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
case certificate_request:
case server_hello_done:
if (ssl->options.resuming) {
+ /* Client requested resumption, but server is doing a
+ * full handshake */
+
+ /* The server's decision to resume isn't known until after the
+ * "server_hello". If subsequent handshake messages like
+ * "certificate" or "server_key_exchange" are received then we
+ * are doing a full handshake */
+
+ /* If the server included a session id then we
+ * treat this as a fatal error, since the server said it was
+ * doing resumption, but did not. */
+
/* https://www.rfc-editor.org/rfc/rfc5077.html#section-3.4
* Alternatively, the client MAY include an empty Session ID
* in the ClientHello. In this case, the client ignores the
@@ -16760,7 +18125,7 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
* messages.
*/
#ifndef WOLFSSL_WPAS
- if (ssl->session->sessionIDSz != 0) {
+ if (ssl->arrays->sessionIDSz != 0) {
/* Fatal error. Only try to send an alert. RFC 5246 does not
* allow for reverting back to a full handshake after the
* server has indicated the intention to do a resumption. */
@@ -16782,9 +18147,9 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#ifdef OPENSSL_EXTRA
if (ssl->CBIS != NULL){
- ssl->cbmode = SSL_CB_MODE_READ;
+ ssl->cbmode = WOLFSSL_CB_MODE_READ;
ssl->cbtype = type;
- ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_ACCEPT_LOOP, WOLFSSL_SUCCESS);
}
#endif
@@ -16800,23 +18165,12 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
WOLFSSL_MSG("processing hello verify request");
ret = DoHelloVerifyRequest(ssl, input,inOutIdx, size);
if (IsEncryptionOn(ssl, 0)) {
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead) {
- word32 digestSz = MacSize(ssl);
- if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
- return BUFFER_E;
- *inOutIdx += ssl->keys.padSz + digestSz;
- }
- else
- #endif
- {
- /* access beyond input + size should be checked against totalSz
- */
- if (*inOutIdx + ssl->keys.padSz > totalSz)
- return BUFFER_E;
+ /* access beyond input + size should be checked against totalSz
+ */
+ if (*inOutIdx + ssl->keys.padSz > totalSz)
+ return BUFFER_E;
- *inOutIdx += ssl->keys.padSz;
- }
+ *inOutIdx += ssl->keys.padSz;
}
break;
@@ -16831,7 +18185,8 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
IsAtLeastTLSv1_3(ssl->version)) {
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
- if (ret != WC_PENDING_E && ret != OCSP_WANT_READ)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E) &&
+ ret != WC_NO_ERR_TRACE(OCSP_WANT_READ))
#endif
{
ssl->options.cacheMessages = 0;
@@ -16888,13 +18243,8 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
AddLateName("ServerHelloDone", &ssl->timeoutInfo);
#endif
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
- if (IsEncryptionOn(ssl, 0)) {
+ if (IsEncryptionOn(ssl, 0))
*inOutIdx += ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- *inOutIdx += MacSize(ssl);
- #endif
- }
break;
case finished:
@@ -16913,7 +18263,8 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (ssl->options.resuming || !ssl->options.verifyPeer || \
!IsAtLeastTLSv1_2(ssl) || IsAtLeastTLSv1_3(ssl->version)) {
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
- if (ret != WC_PENDING_E && ret != OCSP_WANT_READ)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E) &&
+ ret != WC_NO_ERR_TRACE(OCSP_WANT_READ))
#endif
{
ssl->options.cacheMessages = 0;
@@ -16928,24 +18279,12 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* If size == totalSz then we are in DtlsMsgDrain so no need to worry
* about padding */
if (IsEncryptionOn(ssl, 0)) {
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead) {
- word32 digestSz = MacSize(ssl);
- if (size != totalSz &&
- *inOutIdx + ssl->keys.padSz + digestSz > totalSz)
- return BUFFER_E;
- *inOutIdx += ssl->keys.padSz + digestSz;
- }
- else
- #endif
- {
- /* access beyond input + size should be checked against totalSz
- */
- if (size != totalSz &&
- *inOutIdx + ssl->keys.padSz > totalSz)
- return BUFFER_E;
- *inOutIdx += ssl->keys.padSz;
- }
+ /* access beyond input + size should be checked against totalSz
+ */
+ if (size != totalSz &&
+ *inOutIdx + ssl->keys.padSz > totalSz)
+ return BUFFER_E;
+ *inOutIdx += ssl->keys.padSz;
}
break;
@@ -16979,7 +18318,8 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
/* if async, offset index so this msg will be processed again */
- if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) {
+ if ((ret == WC_NO_ERR_TRACE(WC_PENDING_E) ||
+ ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) && *inOutIdx > 0) {
*inOutIdx -= HANDSHAKE_HEADER_SZ;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
@@ -16989,7 +18329,8 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
/* make sure async error is cleared */
- if (ret == 0 && (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) {
+ if (ret == 0 && (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) ||
+ ssl->error == WC_NO_ERR_TRACE(OCSP_WANT_READ))) {
ssl->error = 0;
}
#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
@@ -17025,7 +18366,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
byte type;
word32 size;
- if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0) {
+ if (GetHandshakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0) {
WOLFSSL_ERROR_VERBOSE(PARSE_ERROR);
return PARSE_ERROR;
}
@@ -17053,7 +18394,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
byte type;
word32 size;
- if (GetHandShakeHeader(ssl, input, inOutIdx, &type, &size,
+ if (GetHandshakeHeader(ssl, input, inOutIdx, &type, &size,
totalSz) != 0) {
WOLFSSL_ERROR_VERBOSE(PARSE_ERROR);
return PARSE_ERROR;
@@ -17112,7 +18453,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ssl->error != WC_PENDING_E)
+ if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
/* for async this copy was already done, do not replace, since
@@ -17132,7 +18473,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ssl->arrays->pendingMsgSz - idx,
ssl->arrays->pendingMsgSz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* setup to process fragment again */
ssl->arrays->pendingMsgOffset -= inputLength;
*inOutIdx -= inputLength;
@@ -17150,8 +18491,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
WOLFSSL_LEAVE("DoHandShakeMsg()", ret);
return ret;
}
-
-#endif /* !WOLFSSL_NO_TLS12 */
+#endif /* !NO_TLS && !WOLFSSL_NO_TLS12 */
#ifdef WOLFSSL_EXTRA_ALERTS
int SendFatalAlertOnly(WOLFSSL *ssl, int error)
@@ -17164,43 +18504,41 @@ int SendFatalAlertOnly(WOLFSSL *ssl, int error)
switch (error) {
/* not fatal errors */
- case WANT_WRITE:
- case WANT_READ:
- case ZERO_RETURN:
+ case WC_NO_ERR_TRACE(WANT_WRITE):
+ case WC_NO_ERR_TRACE(WANT_READ):
+ case WC_NO_ERR_TRACE(ZERO_RETURN):
#ifdef WOLFSSL_NONBLOCK_OCSP
- case OCSP_WANT_READ:
+ case WC_NO_ERR_TRACE(OCSP_WANT_READ):
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
- case WC_PENDING_E:
+ case WC_NO_ERR_TRACE(WC_PENDING_E):
#endif
return 0;
/* peer already disconnected and ssl is possibly in bad state
* don't try to send an alert */
- case SOCKET_ERROR_E:
+ case WC_NO_ERR_TRACE(SOCKET_ERROR_E):
return error;
- case BUFFER_ERROR:
- case ASN_PARSE_E:
- case COMPRESSION_ERROR:
+ case WC_NO_ERR_TRACE(BUFFER_ERROR):
+ case WC_NO_ERR_TRACE(ASN_PARSE_E):
+ case WC_NO_ERR_TRACE(COMPRESSION_ERROR):
why = decode_error;
break;
- case MATCH_SUITE_ERROR:
- why = illegal_parameter;
- break;
- case VERIFY_FINISHED_ERROR:
- case SIG_VERIFY_E:
+ case WC_NO_ERR_TRACE(VERIFY_FINISHED_ERROR):
+ case WC_NO_ERR_TRACE(SIG_VERIFY_E):
why = decrypt_error;
break;
- case DUPLICATE_MSG_E:
- case NO_CHANGE_CIPHER_E:
- case OUT_OF_ORDER_E:
+ case WC_NO_ERR_TRACE(DUPLICATE_MSG_E):
+ case WC_NO_ERR_TRACE(NO_CHANGE_CIPHER_E):
+ case WC_NO_ERR_TRACE(OUT_OF_ORDER_E):
why = unexpected_message;
break;
- case ECC_OUT_OF_RANGE_E:
+ case WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E):
why = bad_record_mac;
break;
- case VERSION_ERROR:
+ case WC_NO_ERR_TRACE(MATCH_SUITE_ERROR):
+ case WC_NO_ERR_TRACE(VERSION_ERROR):
default:
why = handshake_failure;
break;
@@ -17684,12 +19022,12 @@ int DtlsMsgDrain(WOLFSSL* ssl)
DtlsTxMsgListClean(ssl);
}
else if (!IsAtLeastTLSv1_3(ssl->version)) {
- if (SendFatalAlertOnly(ssl, ret) == SOCKET_ERROR_E) {
+ if (SendFatalAlertOnly(ssl, ret) == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) {
ret = SOCKET_ERROR_E;
}
}
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
break;
}
#endif
@@ -17750,8 +19088,9 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (type == finished && ssl->keys.dtls_peer_handshake_number >=
ssl->keys.dtls_expected_peer_handshake_number &&
- ssl->keys.curEpoch == ssl->keys.dtls_epoch) {
- /* finished msg should be ignore from the current epoch
+ ssl->keys.curEpoch == ssl->keys.dtls_epoch &&
+ ssl->keys.curEpoch != 0) {
+ /* finished msg should be ignored from the current epoch
* if it comes from a previous handshake */
if (ssl->options.side == WOLFSSL_CLIENT_END) {
ignoreFinished = ssl->options.connectState < FINISHED_DONE;
@@ -17808,22 +19147,9 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
input + *inOutIdx, size, type,
fragOffset, fragSz, ssl->heap);
*inOutIdx += fragSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) {
- word32 digestSz = MacSize(ssl);
- if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) {
- WOLFSSL_ERROR(BUFFER_E);
- return BUFFER_E;
- }
- *inOutIdx += digestSz;
- }
- else
- #endif
- {
- if (*inOutIdx + ssl->keys.padSz > totalSz) {
- WOLFSSL_ERROR(BUFFER_E);
- return BUFFER_E;
- }
+ if (*inOutIdx + ssl->keys.padSz > totalSz) {
+ WOLFSSL_ERROR(BUFFER_E);
+ return BUFFER_E;
}
*inOutIdx += ssl->keys.padSz;
ret = 0;
@@ -17864,22 +19190,9 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* Already saw this message and processed it. It can be ignored. */
WOLFSSL_MSG("Already saw this message and processed it");
*inOutIdx += fragSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) {
- word32 digestSz = MacSize(ssl);
- if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) {
- WOLFSSL_ERROR(BUFFER_E);
- return BUFFER_E;
- }
- *inOutIdx += digestSz;
- }
- else
- #endif
- {
- if (*inOutIdx + ssl->keys.padSz > totalSz) {
- WOLFSSL_ERROR(BUFFER_E);
- return BUFFER_E;
- }
+ if (*inOutIdx + ssl->keys.padSz > totalSz) {
+ WOLFSSL_ERROR(BUFFER_E);
+ return BUFFER_E;
}
#ifndef WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT
if (IsDtlsNotSctpMode(ssl) &&
@@ -17912,17 +19225,11 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
input + *inOutIdx, size, type,
fragOffset, fragSz, ssl->heap);
*inOutIdx += fragSz;
- *inOutIdx += ssl->keys.padSz;
-#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) {
- word32 digestSz = MacSize(ssl);
- if (*inOutIdx + digestSz > totalSz) {
- WOLFSSL_ERROR(BUFFER_E);
- return BUFFER_E;
- }
- *inOutIdx += digestSz;
+ if (*inOutIdx + ssl->keys.padSz > totalSz) {
+ WOLFSSL_ERROR(BUFFER_E);
+ return BUFFER_E;
}
-#endif
+ *inOutIdx += ssl->keys.padSz;
ret = 0;
if (ssl->dtls_rx_msg_list != NULL && ssl->dtls_rx_msg_list->ready)
ret = DtlsMsgDrain(ssl);
@@ -17942,14 +19249,6 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (idx + fragSz + ssl->keys.padSz > totalSz)
return BUFFER_E;
*inOutIdx = idx + fragSz + ssl->keys.padSz;
-#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) {
- word32 digestSz = MacSize(ssl);
- if (*inOutIdx + digestSz > totalSz)
- return BUFFER_E;
- *inOutIdx += digestSz;
- }
-#endif
/* In async mode always store the message and process it with
* DtlsMsgDrain because in case of a WC_PENDING_E it will be
* easier this way. */
@@ -17986,6 +19285,7 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif /* WOLFSSL_DTLS13 */
+#ifndef NO_TLS
#ifndef WOLFSSL_NO_TLS12
#ifdef HAVE_AEAD
@@ -18006,8 +19306,8 @@ static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_CHAPOL_AEAD)
/* Used for the older version of creating AEAD tags with Poly1305 */
-static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
- byte* cipher, word16 sz, byte* tag)
+static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, int additionalSz,
+ const byte* out, byte* cipher, word16 sz, byte* tag)
{
int ret = 0;
int msglen = (sz - ssl->specs.aead_mac_size);
@@ -18025,12 +19325,12 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
return ret;
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional,
- AEAD_AUTH_DATA_SZ)) != 0)
+ additionalSz)) != 0)
return ret;
/* length of additional input plus padding */
XMEMSET(padding, 0, sizeof(padding));
- padding[0] = AEAD_AUTH_DATA_SZ;
+ padding[0] = (byte)additionalSz;
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding,
sizeof(padding))) != 0)
return ret;
@@ -18038,7 +19338,7 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
/* add cipher info and then its length */
XMEMSET(padding, 0, sizeof(padding));
- if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0)
+ if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, (word32)msglen)) != 0)
return ret;
/* 32 bit size of cipher to 64 bit endian */
@@ -18073,19 +19373,21 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
* Return 0 on success negative values in error case
*/
int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
- word16 sz)
+ word16 sz, byte type)
{
- const byte* additionalSrc = input - RECORD_HEADER_SZ;
int ret = 0;
word32 msgLen = (sz - ssl->specs.aead_mac_size);
byte tag[POLY1305_AUTH_SZ];
byte add[AEAD_AUTH_DATA_SZ];
+ int addSz = 0;
byte nonce[CHACHA20_NONCE_SZ];
byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */
#ifdef CHACHA_AEAD_TEST
int i;
#endif
Keys* keys = &ssl->keys;
+ byte* seq = NULL;
+ int verifyOrder = CUR_ORDER;
XMEMSET(tag, 0, sizeof(tag));
XMEMSET(nonce, 0, sizeof(nonce));
@@ -18103,36 +19405,23 @@ int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
/* opaque SEQ number stored for AD */
if (ssl->options.dtls && DtlsSCRKeysSet(ssl)) {
if (ssl->keys.dtls_epoch ==
- ssl->secure_renegotiation->tmp_keys.dtls_epoch) {
+ ssl->secure_renegotiation->tmp_keys.dtls_epoch)
keys = &ssl->secure_renegotiation->tmp_keys;
- WriteSEQ(ssl, CUR_ORDER, add);
- }
else
- WriteSEQ(ssl, PREV_ORDER, add);
+ verifyOrder = PREV_ORDER;
}
- else
#endif
- WriteSEQ(ssl, CUR_ORDER, add);
+
+ addSz = writeAeadAuthData(ssl, (word16)msgLen, type, add, 0, &seq,
+ verifyOrder);
+ if (addSz < 0)
+ return addSz;
if (ssl->options.oldPoly != 0) {
/* get nonce. SEQ should not be incremented again here */
- XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
+ XMEMCPY(nonce + CHACHA20_OLD_OFFSET, seq, SEQ_SZ);
}
- /* Store the type, version. Unfortunately, they are in
- * the input buffer ahead of the plaintext. */
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- additionalSrc -= DTLS_HANDSHAKE_EXTRA;
- }
- #endif
-
- /* add TLS message size to additional data */
- add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
- add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff;
-
- XMEMCPY(add + AEAD_TYPE_OFFSET, additionalSrc, 3);
-
#ifdef CHACHA_AEAD_TEST
printf("Encrypt Additional : ");
for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
@@ -18151,15 +19440,8 @@ int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
if (ssl->options.oldPoly == 0) {
/* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
* record sequence number XORed with client_write_IV/server_write_IV */
- XMEMCPY(nonce, keys->aead_enc_imp_IV, CHACHA20_IMP_IV_SZ);
- nonce[4] ^= add[0];
- nonce[5] ^= add[1];
- nonce[6] ^= add[2];
- nonce[7] ^= add[3];
- nonce[8] ^= add[4];
- nonce[9] ^= add[5];
- nonce[10] ^= add[6];
- nonce[11] ^= add[7];
+ XMEMCPY(nonce + CHACHA20_OFFSET, seq, SEQ_SZ);
+ xorbuf(nonce, keys->aead_enc_imp_IV, CHACHA20_IMP_IV_SZ);
}
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("ChachaAEADEncrypt nonce", nonce, CHACHA20_NONCE_SZ);
@@ -18214,7 +19496,7 @@ int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
/* get the poly1305 tag using either old padding scheme or more recent */
if (ssl->options.oldPoly != 0) {
- if ((ret = Poly1305TagOld(ssl, add, (const byte* )out,
+ if ((ret = Poly1305TagOld(ssl, add, addSz, (const byte* )out,
poly, sz, tag)) != 0) {
ForceZero(poly, sizeof(poly));
#ifdef WOLFSSL_CHECK_MEM_ZERO
@@ -18232,8 +19514,8 @@ int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
#endif
return ret;
}
- if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
- sizeof(add), out, msgLen, tag, sizeof(tag))) != 0) {
+ if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add, addSz, out, msgLen,
+ tag, sizeof(tag))) != 0) {
ForceZero(poly, sizeof(poly));
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Check(poly, CHACHA20_256_KEY_SIZE);
@@ -18289,12 +19571,14 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
word16 sz)
{
byte add[AEAD_AUTH_DATA_SZ];
+ int addSz = 0;
byte nonce[CHACHA20_NONCE_SZ];
byte tag[POLY1305_AUTH_SZ];
byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
int ret = 0;
int msgLen = (sz - ssl->specs.aead_mac_size);
Keys* keys = &ssl->keys;
+ byte* seq = NULL;
#ifdef CHACHA_AEAD_TEST
int i;
@@ -18323,24 +19607,17 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
keys = &ssl->secure_renegotiation->tmp_keys;
#endif
- /* sequence number field is 64-bits */
- WriteSEQ(ssl, PEER_ORDER, add);
+
+ addSz = writeAeadAuthData(ssl, (word16)msgLen, no_type, add, 1, &seq,
+ PEER_ORDER);
+ if (addSz < 0)
+ return addSz;
if (ssl->options.oldPoly != 0) {
/* get nonce, SEQ should not be incremented again here */
- XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2);
+ XMEMCPY(nonce + CHACHA20_OLD_OFFSET, seq, SEQ_SZ);
}
- /* get AD info */
- /* Store the type, version. */
- add[AEAD_TYPE_OFFSET] = ssl->curRL.type;
- add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
- add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
-
- /* add TLS message size to additional data */
- add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
- add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff;
-
#ifdef CHACHA_AEAD_TEST
printf("Decrypt Additional : ");
for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
@@ -18352,15 +19629,8 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
if (ssl->options.oldPoly == 0) {
/* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
* record sequence number XORed with client_write_IV/server_write_IV */
- XMEMCPY(nonce, keys->aead_dec_imp_IV, CHACHA20_IMP_IV_SZ);
- nonce[4] ^= add[0];
- nonce[5] ^= add[1];
- nonce[6] ^= add[2];
- nonce[7] ^= add[3];
- nonce[8] ^= add[4];
- nonce[9] ^= add[5];
- nonce[10] ^= add[6];
- nonce[11] ^= add[7];
+ XMEMCPY(nonce + CHACHA20_OFFSET, seq, SEQ_SZ);
+ xorbuf(nonce, keys->aead_dec_imp_IV, CHACHA20_IMP_IV_SZ);
}
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("ChachaAEADEncrypt nonce", nonce, CHACHA20_NONCE_SZ);
@@ -18405,7 +19675,8 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
/* get the tag using Poly1305 */
if (ssl->options.oldPoly != 0) {
- if ((ret = Poly1305TagOld(ssl, add, input, poly, sz, tag)) != 0) {
+ if ((ret = Poly1305TagOld(ssl, add, addSz, input, poly, sz, tag))
+ != 0) {
ForceZero(poly, sizeof(poly));
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Check(poly, CHACHA20_256_KEY_SIZE);
@@ -18422,8 +19693,8 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
#endif
return ret;
}
- if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
- sizeof(add), input, msgLen, tag, sizeof(tag))) != 0) {
+ if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add, addSz, input,
+ (word32)msgLen, tag, sizeof(tag))) != 0) {
ForceZero(poly, sizeof(poly));
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Check(poly, CHACHA20_256_KEY_SIZE);
@@ -18447,7 +19718,7 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
/* if the tag was good decrypt message */
if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain,
- input, msgLen)) != 0)
+ input, (word32)msgLen)) != 0)
return ret;
#ifdef CHACHA_AEAD_TEST
@@ -18507,9 +19778,74 @@ typedef int (*Sm4AuthDecryptFunc)(wc_Sm4* sm4, byte* out, const byte* in,
#endif
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+#define TLS_AEAD_CID_SZ(s, dec) \
+ ((dec) ? DtlsGetCidRxSize((s)) \
+ : DtlsGetCidTxSize((s)))
+#define TLS_AEAD_CID(s, dec, b, c) \
+ ((dec) ? wolfSSL_dtls_cid_get_rx((s), (b), (c)) \
+ : wolfSSL_dtls_cid_get_tx((s), (b), (c)))
+#endif
+/**
+ *
+ * @param ssl WOLFSSL object
+ * @param sz Length of fragment
+ * @param type Record content type
+ * @param additional AAD output buffer. Assumed AEAD_AUTH_DATA_SZ length.
+ * @param dec Are we decrypting
+ * @return >= 0 length of auth data
+ * < 0 error
+ */
+int writeAeadAuthData(WOLFSSL* ssl, word16 sz, byte type,
+ byte* additional, byte dec, byte** seq, int verifyOrder)
+{
+ word32 idx = 0;
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ byte cidSz = 0;
+ if (ssl->options.dtls && (cidSz = TLS_AEAD_CID_SZ(ssl, dec)) > 0) {
+ if (cidSz > DTLS_CID_MAX_SIZE) {
+ WOLFSSL_MSG("DTLS CID too large");
+ return DTLS_CID_ERROR;
+ }
+
+ XMEMSET(additional + idx, 0xFF, SEQ_SZ);
+ idx += SEQ_SZ;
+ additional[idx++] = dtls12_cid;
+ additional[idx++] = cidSz;
+ additional[idx++] = dtls12_cid;
+ additional[idx++] = dec ? ssl->curRL.pvMajor : ssl->version.major;
+ additional[idx++] = dec ? ssl->curRL.pvMinor : ssl->version.minor;
+ WriteSEQ(ssl, verifyOrder, additional + idx);
+ if (seq != NULL)
+ *seq = additional + idx;
+ idx += SEQ_SZ;
+ if (TLS_AEAD_CID(ssl, dec, additional + idx, (unsigned int)cidSz)
+ == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
+ WOLFSSL_MSG("DTLS CID write failed");
+ return DTLS_CID_ERROR;
+ }
+ idx += cidSz;
+ c16toa(sz, additional + idx);
+ idx += LENGTH_SZ;
+
+ return (int)idx;
+ }
+#endif
+ if (seq != NULL)
+ *seq = additional + idx;
+ WriteSEQ(ssl, verifyOrder, additional + idx);
+ idx += SEQ_SZ;
+ additional[idx++] = dec ? ssl->curRL.type : type;
+ additional[idx++] = dec ? ssl->curRL.pvMajor : ssl->version.major;
+ additional[idx++] = dec ? ssl->curRL.pvMinor : ssl->version.minor;
+ c16toa(sz, additional + idx);
+ idx += LENGTH_SZ;
+
+ return (int)idx;
+}
static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
- word16 sz, int asyncOkay)
+ word16 sz, int asyncOkay, byte type)
{
int ret = 0;
#ifdef WOLFSSL_ASYNC_CRYPT
@@ -18520,8 +19856,8 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
#endif
(void)out;
- (void)input;
(void)sz;
+ (void)type;
if (input == NULL) {
return BAD_FUNC_ARG;
@@ -18546,7 +19882,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E && asyncOkay) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) {
ret = wolfSSL_AsyncPush(ssl, asyncDev);
}
#endif
@@ -18564,7 +19900,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
#endif
ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E && asyncOkay) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) {
ret = wolfSSL_AsyncPush(ssl, asyncDev);
}
#endif
@@ -18576,7 +19912,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */
{
AES_AUTH_ENCRYPT_FUNC aes_auth_fn;
- const byte* additionalSrc;
+ int additionalSz;
#ifdef WOLFSSL_ASYNC_CRYPT
/* initialize event */
@@ -18594,27 +19930,17 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
#else
aes_auth_fn = AES_CCM_ENCRYPT;
#endif
- additionalSrc = input - 5;
- XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ);
-
- /* sequence number field is 64-bits */
- WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional);
-
- /* Store the type, version. Unfortunately, they are in
- * the input buffer ahead of the plaintext. */
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- additionalSrc -= DTLS_HANDSHAKE_EXTRA;
+ additionalSz = writeAeadAuthData(ssl,
+ /* Length of the plain text minus the explicit
+ * IV length minus the authentication tag size. */
+ sz - (word16)(AESGCM_EXP_IV_SZ) - ssl->specs.aead_mac_size,
+ type, ssl->encrypt.additional, 0, NULL, CUR_ORDER);
+ if (additionalSz < 0) {
+ ret = additionalSz;
+ break;
}
- #endif
- XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET,
- additionalSrc, 3);
- /* Store the length of the plain text minus the explicit
- * IV length minus the authentication tag size. */
- c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
- ssl->encrypt.additional + AEAD_LEN_OFFSET);
#if !defined(NO_PUBLIC_GCM_SET_IV) && \
((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)))
@@ -18632,23 +19958,23 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
ssl->encrypt.nonce, AESGCM_NONCE_SZ,
out + sz - ssl->specs.aead_mac_size,
ssl->specs.aead_mac_size,
- ssl->encrypt.additional, AEAD_AUTH_DATA_SZ);
+ ssl->encrypt.additional, (word32)(additionalSz));
}
- if (ret == NOT_COMPILED_IN)
+ if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN))
#endif /* HAVE_PK_CALLBACKS */
{
ret = aes_auth_fn(ssl->encrypt.aes,
- out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ,
- sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
- ssl->encrypt.nonce, AESGCM_NONCE_SZ,
- out + sz - ssl->specs.aead_mac_size,
- ssl->specs.aead_mac_size,
- ssl->encrypt.additional, AEAD_AUTH_DATA_SZ);
+ out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ,
+ sz - (word16)(AESGCM_EXP_IV_SZ) - ssl->specs.aead_mac_size,
+ ssl->encrypt.nonce, AESGCM_NONCE_SZ,
+ out + sz - ssl->specs.aead_mac_size,
+ ssl->specs.aead_mac_size,
+ ssl->encrypt.additional, (word32)(additionalSz));
}
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E && asyncOkay) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) {
ret = wolfSSL_AsyncPush(ssl, asyncDev);
}
#endif
@@ -18665,27 +19991,18 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
#ifdef HAVE_ARIA
case wolfssl_aria_gcm:
{
- const byte* additionalSrc = input - RECORD_HEADER_SZ;
+ int additionalSz;
byte *outBuf = NULL;
- XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ);
-
- /* sequence number field is 64-bits */
- WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional);
- /* Store the type, version. Unfortunately, they are in
- * the input buffer ahead of the plaintext. */
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- additionalSrc -= DTLS_HANDSHAKE_EXTRA;
- }
- #endif
- XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET,
- additionalSrc, 3);
+ additionalSz = ret = writeAeadAuthData(ssl,
+ /* Length of the plain text minus the explicit
+ * IV length minus the authentication tag size. */
+ sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, type,
+ ssl->encrypt.additional, 0, NULL, CUR_ORDER);
+ if (ret < 0)
+ break;
+ ret = 0;
- /* Store the length of the plain text minus the explicit
- * IV length minus the authentication tag size. */
- c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
- ssl->encrypt.additional + AEAD_LEN_OFFSET);
XMEMCPY(ssl->encrypt.nonce,
ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ);
XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ,
@@ -18700,7 +20017,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
(byte*) input + AESGCM_EXP_IV_SZ,
sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
ssl->encrypt.nonce, AESGCM_NONCE_SZ,
- ssl->encrypt.additional, AEAD_AUTH_DATA_SZ,
+ ssl->encrypt.additional, additionalSz,
out + sz - ssl->specs.aead_mac_size,
ssl->specs.aead_mac_size
);
@@ -18723,7 +20040,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
!defined(NO_CHAPOL_AEAD)
case wolfssl_chacha:
- ret = ChachaAEADEncrypt(ssl, out, input, sz);
+ ret = ChachaAEADEncrypt(ssl, out, input, sz, type);
break;
#endif
@@ -18738,7 +20055,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
#endif
ret = wc_Sm4CbcEncrypt(ssl->encrypt.sm4, out, input, sz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E && asyncOkay) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) {
ret = wolfSSL_AsyncPush(ssl, asyncDev);
}
#endif
@@ -18802,7 +20119,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
ssl->encrypt.additional, AEAD_AUTH_DATA_SZ);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E && asyncOkay) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) {
ret = wolfSSL_AsyncPush(ssl, asyncDev);
}
#endif
@@ -18832,7 +20149,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
#ifdef WOLFSSL_ASYNC_CRYPT
/* if async is not okay, then block */
- if (ret == WC_PENDING_E && !asyncOkay) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && !asyncOkay) {
ret = wc_AsyncWait(ret, asyncDev, event_flags);
}
#endif
@@ -18841,12 +20158,12 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input,
}
static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input,
- word16 sz, int asyncOkay)
+ word16 sz, int asyncOkay, byte type)
{
int ret = 0;
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ssl->error == WC_PENDING_E) {
+ if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ssl->error = 0; /* clear async */
}
#endif
@@ -18932,14 +20249,14 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input,
case CIPHER_STATE_DO:
{
- ret = EncryptDo(ssl, out, input, sz, asyncOkay);
+ ret = EncryptDo(ssl, out, input, sz, asyncOkay, type);
/* Advance state */
ssl->encrypt.state = CIPHER_STATE_END;
#ifdef WOLFSSL_ASYNC_CRYPT
/* If pending, then leave and return will resume below */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return ret;
}
#endif
@@ -19035,7 +20352,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev);
}
#endif
@@ -19053,7 +20370,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
#endif
ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
}
#endif
@@ -19065,6 +20382,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */
{
wc_AesAuthDecryptFunc aes_auth_fn;
+ int additionalSz;
#ifdef WOLFSSL_ASYNC_CRYPT
/* initialize event */
@@ -19083,17 +20401,13 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
aes_auth_fn = wc_AesCcmDecrypt;
#endif
- XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ);
-
- /* sequence number field is 64-bits */
- WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional);
-
- ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
- ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
- ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
-
- c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
- ssl->decrypt.additional + AEAD_LEN_OFFSET);
+ additionalSz = writeAeadAuthData(ssl,
+ sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, no_type,
+ ssl->decrypt.additional, 1, NULL, PEER_ORDER);
+ if (additionalSz < 0) {
+ ret = additionalSz;
+ break;
+ }
#if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION)
if (ssl->options.dtls && IsDtlsMsgSCRKeys(ssl))
@@ -19112,26 +20426,26 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
ret = ssl->ctx->PerformTlsRecordProcessingCb(ssl, 0,
plain + AESGCM_EXP_IV_SZ,
input + AESGCM_EXP_IV_SZ,
- sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
+ sz - (word16)(AESGCM_EXP_IV_SZ) - ssl->specs.aead_mac_size,
ssl->decrypt.nonce, AESGCM_NONCE_SZ,
(byte *)(input + sz - ssl->specs.aead_mac_size),
ssl->specs.aead_mac_size,
- ssl->decrypt.additional, AEAD_AUTH_DATA_SZ);
+ ssl->decrypt.additional, (word32)(additionalSz));
}
- if (ret == NOT_COMPILED_IN)
+ if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN))
#endif /* HAVE_PK_CALLBACKS */
{
if ((ret = aes_auth_fn(ssl->decrypt.aes,
- plain + AESGCM_EXP_IV_SZ,
- input + AESGCM_EXP_IV_SZ,
- sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
- ssl->decrypt.nonce, AESGCM_NONCE_SZ,
- input + sz - ssl->specs.aead_mac_size,
- ssl->specs.aead_mac_size,
- ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) {
+ plain + AESGCM_EXP_IV_SZ,
+ input + AESGCM_EXP_IV_SZ,
+ sz - (word16)(AESGCM_EXP_IV_SZ) - ssl->specs.aead_mac_size,
+ ssl->decrypt.nonce, AESGCM_NONCE_SZ,
+ input + sz - ssl->specs.aead_mac_size,
+ ssl->specs.aead_mac_size,
+ ssl->decrypt.additional, (word32)(additionalSz))) < 0) {
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl,
&ssl->decrypt.aes->asyncDev);
}
@@ -19146,17 +20460,14 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
case wolfssl_aria_gcm:
{
byte *outBuf = NULL;
- XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ);
-
- /* sequence number field is 64-bits */
- WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional);
+ int additionalSz;
- ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
- ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
- ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
-
- c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
- ssl->decrypt.additional + AEAD_LEN_OFFSET);
+ additionalSz = ret = writeAeadAuthData(ssl,
+ sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, no_type,
+ ssl->decrypt.additional, 1, NULL, PEER_ORDER);
+ if (ret < 0)
+ break;
+ ret = 0;
#if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION)
if (ssl->options.dtls && IsDtlsMsgSCRKeys(ssl))
@@ -19179,7 +20490,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
(byte *)input + AESGCM_EXP_IV_SZ,
sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
ssl->decrypt.nonce, AESGCM_NONCE_SZ,
- ssl->decrypt.additional, AEAD_AUTH_DATA_SZ,
+ ssl->decrypt.additional, additionalSz,
(byte *)input + sz - ssl->specs.aead_mac_size,
ssl->specs.aead_mac_size
);
@@ -19217,7 +20528,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
#endif
ret = wc_Sm4CbcDecrypt(ssl->decrypt.sm4, plain, input, sz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
}
#endif
@@ -19278,7 +20589,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
ssl->specs.aead_mac_size,
ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) {
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl,
&ssl->decrypt.sm4->asyncDev);
}
@@ -19318,9 +20629,9 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz)
#ifdef WOLFSSL_ASYNC_CRYPT
ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* check for still pending */
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
ssl->error = 0; /* clear async */
@@ -19435,7 +20746,7 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz)
#ifdef WOLFSSL_ASYNC_CRYPT
/* If pending, leave and return below */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return ret;
}
#endif
@@ -19502,12 +20813,7 @@ static WC_INLINE int CipherHasExpIV(WOLFSSL *ssl)
/* check cipher text size for sanity */
static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
{
-#ifdef HAVE_TRUNCATED_HMAC
- word32 minLength = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
- : ssl->specs.hash_size;
-#else
- word32 minLength = ssl->specs.hash_size; /* covers stream */
-#endif
+ word32 minLength = MacSize(ssl);
#ifndef WOLFSSL_AEAD_ONLY
if (ssl->specs.cipher_type == block) {
@@ -19554,7 +20860,7 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
#ifndef WOLFSSL_AEAD_ONLY
-#ifdef WOLSSL_OLD_TIMINGPADVERIFY
+#ifdef WOLFSSL_OLD_TIMINGPADVERIFY
#define COMPRESS_LOWER 64
#define COMPRESS_UPPER 55
#define COMPRESS_CONSTANT 13
@@ -19854,7 +21160,7 @@ static byte MaskPadding(const byte* data, int sz, int macSz)
checkSz = TLS_MAX_PAD_SZ;
for (i = 0; i < checkSz; i++) {
- byte mask = ctMaskLTE(i, paddingSz);
+ volatile byte mask = ctMaskLTE(i, paddingSz);
good |= mask & (data[sz - 1 - i] ^ paddingSz);
}
@@ -19874,16 +21180,21 @@ static byte MaskPadding(const byte* data, int sz, int macSz)
static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac)
{
int i, j;
- unsigned char mac[WC_MAX_DIGEST_SIZE];
- int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz;
- int macEnd = sz - 1 - data[sz - 1];
- int macStart = macEnd - macSz;
int r = 0;
- unsigned char started, notEnded;
+ unsigned char mac[WC_MAX_DIGEST_SIZE];
+ volatile int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz;
+ volatile int macEnd = sz - 1 - data[sz - 1];
+ volatile int macStart = macEnd - macSz;
+ volatile int maskScanStart;
+ volatile int maskMacStart;
+ volatile unsigned char started;
+ volatile unsigned char notEnded;
unsigned char good = 0;
- scanStart &= ctMaskIntGTE(scanStart, 0);
- macStart &= ctMaskIntGTE(macStart, 0);
+ maskScanStart = ctMaskIntGTE(scanStart, 0);
+ maskMacStart = ctMaskIntGTE(macStart, 0);
+ scanStart &= maskScanStart;
+ macStart &= maskMacStart;
/* Div on Intel has different speeds depending on value.
* Use a bitwise AND or mod a specific value (converted to mul). */
@@ -19898,7 +21209,7 @@ static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac)
r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE;
#endif
- XMEMSET(mac, 0, macSz);
+ XMEMSET(mac, 0, (size_t)(macSz));
for (i = scanStart; i < sz; i += macSz) {
for (j = 0; j < macSz && j + i < sz; j++) {
started = ctMaskGTE(i + j, macStart);
@@ -19935,11 +21246,12 @@ int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz,
byte good;
int ret = 0;
+ XMEMSET(verify, 0, WC_MAX_DIGEST_SIZE);
good = MaskPadding(input, pLen, macSz);
/* 4th argument has potential to underflow, ssl->hmac function should
* either increment the size by (macSz + padLen + 1) before use or check on
* the size to make sure is valid. */
- ret = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen,
+ ret = ssl->hmac(ssl, verify, input, (word32)(pLen - macSz - padLen - 1), padLen,
content, 1, PEER_ORDER);
good |= MaskMac(input, pLen, ssl->specs.hash_size, verify);
@@ -19960,46 +21272,76 @@ int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz,
return ret;
}
#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */
-#endif /* WOLSSL_OLD_TIMINGPADVERIFY */
+#endif /* WOLFSSL_OLD_TIMINGPADVERIFY */
#endif /* WOLFSSL_AEAD_ONLY */
int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
{
- word32 msgSz = WOLFSSL_IS_QUIC(ssl)? ssl->curSize : ssl->keys.encryptSz;
+ word32 msgSz = ssl->curSize;
word32 idx = *inOutIdx;
int dataSz;
- int ivExtra = 0;
byte* rawData = input + idx; /* keep current for hmac */
#ifdef HAVE_LIBZ
byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
#endif
-
#ifdef WOLFSSL_EARLY_DATA
- if (ssl->options.tls1_3 && ssl->options.handShakeDone == 0) {
- int process = 0;
+ int isEarlyData = ssl->options.tls1_3 &&
+ ssl->options.handShakeDone == 0 &&
+ ssl->options.side == WOLFSSL_SERVER_END;
+ int acceptEarlyData = ssl->earlyData != no_early_data &&
+ ssl->options.clientState == CLIENT_HELLO_COMPLETE;
+#endif
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- if ((ssl->earlyData != no_early_data) &&
- (ssl->options.clientState == CLIENT_HELLO_COMPLETE)) {
- process = 1;
- }
- if (!process) {
- WOLFSSL_MSG("Ignoring EarlyData!");
- *inOutIdx += ssl->curSize;
- if (*inOutIdx > ssl->buffers.inputBuffer.length)
- return BUFFER_E;
+#if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_DTLS13)
+ if (ssl->options.tls1_3 && ssl->options.dtls)
+ isEarlyData = isEarlyData && w64Equal(ssl->keys.curEpoch64,
+ w64From32(0x0, DTLS13_EPOCH_EARLYDATA));
+#endif
+#ifdef WOLFSSL_DTLS13
+ /* Application data should never appear in epoch 0 or 2 */
+ if (ssl->options.tls1_3 && ssl->options.dtls &&
+ (w64Equal(ssl->keys.curEpoch64, w64From32(0x0, DTLS13_EPOCH_HANDSHAKE))
+ || w64Equal(ssl->keys.curEpoch64, w64From32(0x0, 0x0))))
+ {
+ WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
+ return SANITY_MSG_E;
+ }
+#endif
- return 0;
- }
- }
- if (!process) {
- WOLFSSL_MSG("Received App data before a handshake completed");
- if (sniff == NO_SNIFF) {
- SendAlert(ssl, alert_fatal, unexpected_message);
- }
- WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
- return OUT_OF_ORDER_E;
- }
+#ifdef WOLFSSL_EARLY_DATA
+ if (isEarlyData && acceptEarlyData) {
+ WOLFSSL_MSG("Processing EarlyData");
+ }
+ else if (isEarlyData && !acceptEarlyData) {
+ WOLFSSL_MSG("Ignoring EarlyData!");
+ *inOutIdx += ssl->curSize;
+ if (*inOutIdx > ssl->buffers.inputBuffer.length)
+ return BUFFER_E;
+#ifdef WOLFSSL_DTLS13
+ /* Receiving app data from the traffic epoch before the handshake is
+ * done means that there was a disruption. */
+ if (ssl->options.dtls && !w64Equal(ssl->keys.curEpoch64,
+ w64From32(0x0, DTLS13_EPOCH_EARLYDATA)))
+ ssl->dtls13Rtx.sendAcks = 1;
+#endif
+ return 0;
+ }
+ else
+#endif
+#ifdef WOLFSSL_DTLS
+ if (ssl->options.handShakeDone == 0 && ssl->options.dtls) {
+ WOLFSSL_MSG("Dropping app data received before handshake complete");
+ *inOutIdx += ssl->curSize;
+ if (*inOutIdx > ssl->buffers.inputBuffer.length)
+ return BUFFER_E;
+#ifdef WOLFSSL_DTLS13
+ /* Receiving app data from the traffic epoch before the handshake is
+ * done means that there was a disruption. */
+ if (ssl->options.tls1_3 && !w64Equal(ssl->keys.curEpoch64,
+ w64From32(0x0, DTLS13_EPOCH_EARLYDATA)))
+ ssl->dtls13Rtx.sendAcks = 1;
+#endif
+ return 0;
}
else
#endif
@@ -20029,23 +21371,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
}
#endif
-#ifndef WOLFSSL_AEAD_ONLY
- if (ssl->specs.cipher_type == block) {
- if (ssl->options.tls1_1)
- ivExtra = ssl->specs.block_size;
- }
- else
-#endif
- if (ssl->specs.cipher_type == aead) {
- if (CipherHasExpIV(ssl))
- ivExtra = AESGCM_EXP_IV_SZ;
- }
-
- dataSz = msgSz - ivExtra - ssl->keys.padSz;
-#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- dataSz -= MacSize(ssl);
-#endif
+ dataSz = (int)(msgSz - ssl->keys.padSz);
if (dataSz < 0) {
WOLFSSL_MSG("App data buffer error, malicious input?");
if (sniff == NO_SNIFF) {
@@ -20077,17 +21403,13 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
if (dataSz < 0) return dataSz;
}
#endif
- idx += rawSz;
+ idx += (word32)rawSz;
ssl->buffers.clearOutputBuffer.buffer = rawData;
- ssl->buffers.clearOutputBuffer.length = dataSz;
+ ssl->buffers.clearOutputBuffer.length = (unsigned int)dataSz;
}
idx += ssl->keys.padSz;
-#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- idx += MacSize(ssl);
-#endif
#ifdef HAVE_LIBZ
/* decompress could be bigger, overwrite after verify */
@@ -20254,6 +21576,13 @@ const char* AlertTypeToString(int type)
return internal_error_str;
}
+ case inappropriate_fallback:
+ {
+ static const char inappropriate_fallback_str[] =
+ "inappropriate_fallback";
+ return inappropriate_fallback_str;
+ }
+
case user_canceled:
{
static const char user_canceled_str[] =
@@ -20268,6 +21597,20 @@ const char* AlertTypeToString(int type)
return no_renegotiation_str;
}
+ case missing_extension:
+ {
+ static const char missing_extension_str[] =
+ "missing_extension";
+ return missing_extension_str;
+ }
+
+ case unsupported_extension:
+ {
+ static const char unsupported_extension_str[] =
+ "unsupported_extension";
+ return unsupported_extension_str;
+ }
+
case unrecognized_name:
{
static const char unrecognized_name_str[] =
@@ -20282,6 +21625,20 @@ const char* AlertTypeToString(int type)
return bad_certificate_status_response_str;
}
+ case unknown_psk_identity:
+ {
+ static const char unknown_psk_identity_str[] =
+ "unknown_psk_identity";
+ return unknown_psk_identity_str;
+ }
+
+ case certificate_required:
+ {
+ static const char certificate_required_str[] =
+ "certificate_required";
+ return certificate_required_str;
+ }
+
case no_application_protocol:
{
static const char no_application_protocol_str[] =
@@ -20303,7 +21660,11 @@ static void LogAlert(int type)
typeStr = AlertTypeToString(type);
if (typeStr != NULL) {
char buff[60];
- XSNPRINTF(buff, sizeof(buff), "Alert type: %s", typeStr);
+ if (XSNPRINTF(buff, sizeof(buff), "Alert type: %s", typeStr)
+ >= (int)sizeof(buff))
+ {
+ buff[sizeof(buff) - 1] = 0;
+ }
WOLFSSL_MSG(buff);
}
#else
@@ -20333,26 +21694,8 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type)
}
#endif
- if (IsEncryptionOn(ssl, 0)) {
- int ivExtra = 0;
-#ifndef WOLFSSL_AEAD_ONLY
- if (ssl->specs.cipher_type == block) {
- if (ssl->options.tls1_1)
- ivExtra = ssl->specs.block_size;
- }
- else
-#endif
- if (ssl->specs.cipher_type == aead) {
- if (CipherHasExpIV(ssl))
- ivExtra = AESGCM_EXP_IV_SZ;
- }
- dataSz -= ivExtra;
+ if (IsEncryptionOn(ssl, 0))
dataSz -= ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- dataSz -= MacSize(ssl);
- #endif
- }
/* make sure can read the message */
if (dataSz != ALERT_SIZE) {
@@ -20395,10 +21738,6 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type)
if (IsEncryptionOn(ssl, 0)) {
*inOutIdx += ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- *inOutIdx += MacSize(ssl);
- #endif
}
return level;
@@ -20411,11 +21750,14 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
int usedLength;
int dtlsExtra = 0;
+ if (ssl->options.disableRead)
+ return WC_NO_ERR_TRACE(WANT_READ);
/* check max input length */
- usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx;
- maxLength = ssl->buffers.inputBuffer.bufferSize - usedLength;
- inSz = (int)(size - usedLength); /* from last partial read */
+ usedLength = (int)(ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx);
+ maxLength = (int)(ssl->buffers.inputBuffer.bufferSize -
+ (word32)usedLength);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls && IsDtlsNotSctpMode(ssl)) {
@@ -20429,15 +21771,24 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
if (size < (word32)inSz)
dtlsExtra = (int)(inSz - size);
}
+ else
#endif
+ {
+ /* check that no lengths or size values are negative */
+ if (usedLength < 0 || maxLength < 0) {
+ return BUFFER_ERROR;
+ }
- /* check that no lengths or size values are negative */
- if (usedLength < 0 || maxLength < 0 || inSz <= 0) {
- return BUFFER_ERROR;
+ /* Return if we have enough data already in the buffer */
+ if (size <= (word32)usedLength) {
+ return 0;
+ }
+
+ inSz = (int)(size - (word32)usedLength); /* from last partial read */
}
if (inSz > maxLength) {
- if (GrowInputBuffer(ssl, size + dtlsExtra, usedLength) < 0)
+ if (GrowInputBuffer(ssl, (int)(size + (word32)dtlsExtra), usedLength) < 0)
return MEMORY_E;
}
@@ -20445,20 +21796,20 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
XMEMMOVE(ssl->buffers.inputBuffer.buffer,
ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
- usedLength);
+ (size_t)(usedLength));
/* remove processed data */
ssl->buffers.inputBuffer.idx = 0;
- ssl->buffers.inputBuffer.length = usedLength;
+ ssl->buffers.inputBuffer.length = (word32)usedLength;
/* read data from network */
do {
int in = wolfSSLReceive(ssl,
ssl->buffers.inputBuffer.buffer +
ssl->buffers.inputBuffer.length,
- inSz);
- if (in == WANT_READ)
- return WANT_READ;
+ (word32)inSz);
+ if (in == WC_NO_ERR_TRACE(WANT_READ))
+ return WC_NO_ERR_TRACE(WANT_READ);
if (in < 0) {
WOLFSSL_ERROR_VERBOSE(SOCKET_ERROR_E);
@@ -20470,9 +21821,18 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
return RECV_OVERFLOW_E;
}
- ssl->buffers.inputBuffer.length += in;
- inSz -= in;
+ if ((word32)in < size) {
+ if (!RecordsCanSpanReads(ssl)) {
+ WOLFSSL_MSG("DTLS: Received partial record, ignoring");
+#ifdef WOLFSSL_DTLS_DROP_STATS
+ ssl->replayDropCount++;
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+ continue;
+ }
+ }
+ ssl->buffers.inputBuffer.length += (word32)in;
+ inSz -= in;
} while (ssl->buffers.inputBuffer.length < size);
#ifdef WOLFSSL_DEBUG_TLS
@@ -20505,9 +21865,10 @@ static WC_INLINE int VerifyMacEnc(WOLFSSL* ssl, const byte* input, word32 msgSz,
WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR);
return VERIFY_MAC_ERROR;
}
+ XMEMSET(verify, 0, WC_MAX_DIGEST_SIZE);
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1, PEER_ORDER);
- ret |= ConstantCompare(verify, input + msgSz - digestSz, digestSz);
+ ret |= ConstantCompare(verify, input + msgSz - digestSz, (int)digestSz);
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR);
return VERIFY_MAC_ERROR;
@@ -20524,20 +21885,13 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
int ret;
word32 pad = 0;
word32 padByte = 0;
-#ifdef HAVE_TRUNCATED_HMAC
- word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
- : ssl->specs.hash_size;
-#else
- word32 digestSz = ssl->specs.hash_size;
-#endif
+ word32 digestSz = MacSize(ssl);
byte verify[WC_MAX_DIGEST_SIZE];
+ XMEMSET(verify, 0, WC_MAX_DIGEST_SIZE);
if (ssl->specs.cipher_type == block) {
- int ivExtra = 0;
- if (ssl->options.tls1_1)
- ivExtra = ssl->specs.block_size;
- pad = *(input + msgSz - ivExtra - 1);
+ pad = input[msgSz - 1];
padByte = 1;
if (ssl->options.tls) {
@@ -20546,16 +21900,18 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
if(ssl->ctx->VerifyMacCb) {
void* ctx = wolfSSL_GetVerifyMacCtx(ssl);
ret = ssl->ctx->VerifyMacCb(ssl, input,
- (msgSz - ivExtra) - digestSz - pad - 1,
- digestSz, content, ctx);
- if (ret != 0 && ret != PROTOCOLCB_UNAVAILABLE) {
+ msgSz - digestSz - pad - 1,
+ digestSz, (word32)content, ctx);
+ if (ret != 0 &&
+ ret != WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) {
return ret;
}
}
- if (!ssl->ctx->VerifyMacCb || ret == PROTOCOLCB_UNAVAILABLE)
+ if (!ssl->ctx->VerifyMacCb ||
+ ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE))
#endif
- ret = TimingPadVerify(ssl, input, pad, digestSz, msgSz - ivExtra,
- content);
+ ret = TimingPadVerify(ssl, input, (int)pad, (int)digestSz,
+ (int)msgSz, content);
if (ret != 0)
return ret;
}
@@ -20573,9 +21929,9 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
}
(void)PadCheck(dummy, (byte)pad, MAX_PAD_SIZE); /* timing only */
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1,
- pad, content, 1, PEER_ORDER);
+ (int)pad, content, 1, PEER_ORDER);
if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
- digestSz) != 0) {
+ (int)digestSz) != 0) {
WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR);
return VERIFY_MAC_ERROR;
}
@@ -20588,7 +21944,7 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
else if (ssl->specs.cipher_type == stream) {
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1,
PEER_ORDER);
- if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0) {
+ if (ConstantCompare(verify, input + msgSz - digestSz, (int)digestSz) != 0) {
WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR);
return VERIFY_MAC_ERROR;
}
@@ -20604,7 +21960,7 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
}
#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY)
else {
- *padSz = digestSz + pad + padByte;
+ *padSz = pad + padByte;
}
#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */
@@ -20644,7 +22000,9 @@ static int DtlsShouldDrop(WOLFSSL* ssl, int retcode)
}
if ((ssl->options.handShakeDone && retcode != 0)
- || retcode == SEQUENCE_ERROR || retcode == DTLS_CID_ERROR) {
+ || retcode == WC_NO_ERR_TRACE(SEQUENCE_ERROR)
+ || retcode == WC_NO_ERR_TRACE(DTLS_CID_ERROR)
+ || retcode == WC_NO_ERR_TRACE(DTLS_PARTIAL_RECORD_READ)) {
WOLFSSL_MSG_EX("Silently dropping DTLS message: %d", retcode);
return 1;
}
@@ -20672,16 +22030,219 @@ static int DtlsShouldDrop(WOLFSSL* ssl, int retcode)
}
#endif /* WOLFSSL_DTLS */
-int ProcessReply(WOLFSSL* ssl)
+#if defined(WOLFSSL_TLS13) || \
+ (defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID))
+static int removeMsgInnerPadding(WOLFSSL* ssl)
{
- return ProcessReplyEx(ssl, 0);
+ word32 i = ssl->buffers.inputBuffer.idx +
+ ssl->curSize;
+ if (ssl->specs.cipher_type == aead)
+ i -= ssl->specs.aead_mac_size;
+ else
+ i -= ssl->keys.padSz + MacSize(ssl);
+
+ /* check that the end of the logical length doesn't extend
+ * past the real buffer */
+ if (i > ssl->buffers.inputBuffer.length || i == 0) {
+ WOLFSSL_ERROR(BUFFER_ERROR);
+ return BUFFER_ERROR;
+ }
+
+ /* Remove padding from end of plain text. */
+ for (--i; i > ssl->buffers.inputBuffer.idx; i--) {
+ if (ssl->buffers.inputBuffer.buffer[i] != 0)
+ break;
+ }
+
+ /* Get the real content type from the end of the data. */
+ ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i];
+ /* consider both contentType byte and MAC as padding */
+ ssl->keys.padSz = ssl->buffers.inputBuffer.idx
+ + ssl->curSize - i;
+ return 0;
+}
+#endif
+
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+static void dtlsClearPeer(WOLFSSL_SOCKADDR* peer)
+{
+ XFREE(peer->sa, NULL, DYNAMIC_TYPE_SOCKADDR);
+ peer->sa = NULL;
+ peer->sz = 0;
+ peer->bufSz = 0;
+}
+
+
+/**
+ * @brief Handle pending peer during record processing.
+ * @param ssl WOLFSSL object.
+ * @param deprotected 0 when we have not decrypted the record yet
+ * 1 when we have decrypted and verified the record
+ */
+static void dtlsProcessPendingPeer(WOLFSSL* ssl, int deprotected)
+{
+ if (ssl->buffers.dtlsCtx.pendingPeer.sa != NULL) {
+ if (!deprotected) {
+ /* Here we have just read an entire record from the network. It is
+ * still encrypted. If processingPendingRecord is set then that
+ * means that an error occurred when processing the previous record.
+ * In that case we should clear the pendingPeer because we only
+ * want to allow it to be valid for one record. */
+ if (ssl->buffers.dtlsCtx.processingPendingRecord) {
+ /* Clear the pending peer. */
+ dtlsClearPeer(&ssl->buffers.dtlsCtx.pendingPeer);
+ }
+ ssl->buffers.dtlsCtx.processingPendingRecord =
+ !ssl->buffers.dtlsCtx.processingPendingRecord;
+ }
+ else {
+ /* Pending peer present and record deprotected. Update the peer. */
+ (void)wolfSSL_dtls_set_peer(ssl,
+ ssl->buffers.dtlsCtx.pendingPeer.sa,
+ ssl->buffers.dtlsCtx.pendingPeer.sz);
+ ssl->buffers.dtlsCtx.processingPendingRecord = 0;
+ dtlsClearPeer(&ssl->buffers.dtlsCtx.pendingPeer);
+ }
+ }
+ else {
+ ssl->buffers.dtlsCtx.processingPendingRecord = 0;
+ }
+}
+#endif
+static int DoDecrypt(WOLFSSL *ssl)
+{
+ int ret;
+ int atomicUser = 0;
+ bufferStatic* in = &ssl->buffers.inputBuffer;
+
+#ifdef ATOMIC_USER
+ if (ssl->ctx->DecryptVerifyCb)
+ atomicUser = 1;
+#endif
+
+ ret = SanityCheckCipherText(ssl, ssl->curSize);
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (atomicUser) {
+#ifdef ATOMIC_USER
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ if (ssl->options.startedETMRead) {
+ ret = ssl->ctx->VerifyDecryptCb(ssl,
+ in->buffer + in->idx, in->buffer + in->idx,
+ ssl->curSize - MacSize(ssl),
+ ssl->curRL.type, 1, &ssl->keys.padSz,
+ ssl->DecryptVerifyCtx);
+ }
+ else
+#endif
+ {
+ ret = ssl->ctx->DecryptVerifyCb(ssl,
+ in->buffer + in->idx,
+ in->buffer + in->idx,
+ ssl->curSize, ssl->curRL.type, 1,
+ &ssl->keys.padSz, ssl->DecryptVerifyCtx);
+ }
+#endif /* ATOMIC_USER */
+ }
+ else {
+ if (!ssl->options.tls1_3) {
+#ifndef WOLFSSL_NO_TLS12
+#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
+ if (ssl->options.startedETMRead) {
+ word32 digestSz = MacSize(ssl);
+ ret = DecryptTls(ssl,
+ in->buffer + in->idx,
+ in->buffer + in->idx,
+ ssl->curSize - (word16)digestSz);
+ if (ret == 0) {
+ byte invalid = 0;
+ byte padding = (byte)-1;
+ word32 i;
+ word32 off = in->idx + ssl->curSize - digestSz - 1;
+
+ /* Last of padding bytes - indicates length. */
+ ssl->keys.padSz = in->buffer[off];
+ /* Constant time checking of padding - don't leak the length of
+ * the data. */
+ /* Compare max pad bytes or at most data + pad. */
+ for (i = 1; i < MAX_PAD_SIZE && off >= i; i++) {
+ /* Mask on indicates this is expected to be a padding byte.
+ */
+ volatile byte maskPadByte = ctMaskLTE((int)i,
+ (int)ssl->keys.padSz);
+ padding &= maskPadByte;
+ /* When this is a padding byte and not equal to length then
+ * mask is set. */
+ invalid |= padding & ctMaskNotEq(in->buffer[off - i],
+ (int)ssl->keys.padSz);
+ }
+ /* If mask is set then there was an error. */
+ if (invalid) {
+ ret = DECRYPT_ERROR;
+ }
+ ssl->keys.padSz += 1;
+ ssl->keys.decryptedCur = 1;
+ }
+ }
+ else
+#endif
+ {
+ ret = DecryptTls(ssl,
+ in->buffer + in->idx,
+ in->buffer + in->idx,
+ ssl->curSize);
+ }
+#else
+ ret = DECRYPT_ERROR;
+#endif
+ }
+ else
+ {
+ #ifdef WOLFSSL_TLS13
+ byte *aad = (byte*)&ssl->curRL;
+ word16 aad_size = RECORD_HEADER_SZ;
+ #ifdef WOLFSSL_DTLS13
+ if (ssl->options.dtls) {
+ /* aad now points to the record header */
+ aad = ssl->dtls13CurRL;
+ aad_size = ssl->dtls13CurRlLength;
+ }
+ #endif /* WOLFSSL_DTLS13 */
+ /* Don't send an alert for DTLS. We will just drop it
+ * silently later. */
+ ret = DecryptTls13(ssl,
+ in->buffer + in->idx,
+ in->buffer + in->idx,
+ ssl->curSize,
+ aad, aad_size);
+ #else
+ ret = DECRYPT_ERROR;
+ #endif /* WOLFSSL_TLS13 */
+ }
+ (void)in;
+ }
+ return ret;
}
+#ifdef WOLFSSL_DTLS
+static void DropAndRestartProcessReply(WOLFSSL* ssl)
+{
+ ssl->options.processReply = doProcessInit;
+ ssl->buffers.inputBuffer.length = 0;
+ ssl->buffers.inputBuffer.idx = 0;
+#ifdef WOLFSSL_DTLS_DROP_STATS
+ if (ssl->options.dtls)
+ ssl->replayDropCount++;
+#endif /* WOLFSSL_DTLS_DROP_STATS */
+}
+#endif /* WOLFSSL_DTLS */
/* Process input requests. Return 0 is done, 1 is call again to complete, and
negative number is error. If allowSocketErr is set, SOCKET_ERROR_E in
ssl->error will be whitelisted. This is useful when the connection has been
closed and the endpoint wants to check for an alert sent by the other end. */
-int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
+static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
{
int ret = 0, type = internal_error, readSz;
int atomicUser = 0;
@@ -20694,17 +22255,20 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
atomicUser = 1;
#endif
- if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE
+ if (ssl->error != 0 &&
+ ssl->error != WC_NO_ERR_TRACE(WANT_READ) &&
+ ssl->error != WC_NO_ERR_TRACE(WANT_WRITE)
#if defined(HAVE_SECURE_RENEGOTIATION) || defined(WOLFSSL_DTLS13)
- && ssl->error != APP_DATA_READY
+ && ssl->error != WC_NO_ERR_TRACE(APP_DATA_READY)
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
- && ssl->error != WC_PENDING_E
+ && ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
#ifdef WOLFSSL_NONBLOCK_OCSP
- && ssl->error != OCSP_WANT_READ
+ && ssl->error != WC_NO_ERR_TRACE(OCSP_WANT_READ)
#endif
- && (allowSocketErr != 1 || ssl->error != SOCKET_ERROR_E)
+ && (allowSocketErr != 1 ||
+ ssl->error != WC_NO_ERR_TRACE(SOCKET_ERROR_E))
) {
WOLFSSL_MSG("ProcessReply retry in error state, not allowed");
return ssl->error;
@@ -20715,7 +22279,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
#if defined(WOLFSSL_CHECK_ALERT_ON_ERR) && \
(defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP))
if (allowSocketErr == 1 && \
- (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) {
+ (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) ||
+ ssl->error == WC_NO_ERR_TRACE(OCSP_WANT_READ))) {
return ssl->error;
}
#endif
@@ -20774,7 +22339,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
/* get header or return error */
if (!ssl->options.dtls) {
- if ((ret = GetInputData(ssl, readSz)) < 0)
+ if ((ret = GetInputData(ssl, (word32)readSz)) < 0)
return ret;
} else {
#ifdef WOLFSSL_DTLS
@@ -20782,7 +22347,12 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
used = ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx;
if (used < readSz) {
- if ((ret = GetInputData(ssl, readSz)) < 0)
+ if (used > 0 && !RecordsCanSpanReads(ssl)) {
+ WOLFSSL_MSG("DTLS: Partial record in buffer, dropping");
+ DropAndRestartProcessReply(ssl);
+ continue;
+ }
+ if ((ret = GetInputData(ssl, (word32)readSz)) < 0)
return ret;
}
#endif
@@ -20794,7 +22364,11 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
if ( ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.clientState == NULL_STATE &&
ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
- != handshake) {
+ != handshake &&
+ /* change_cipher_spec here is an error but we want to handle
+ * it correctly later */
+ ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
+ != change_cipher_spec) {
byte b0, b1;
ssl->options.processReply = runProcessOldClientHello;
@@ -20876,14 +22450,12 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
&ssl->curRL, &ssl->curSize);
#ifdef WOLFSSL_DTLS
+#ifdef WOLFSSL_DTLS_CID
+ if (ssl->options.dtls)
+ dtlsProcessPendingPeer(ssl, 0);
+#endif
if (ssl->options.dtls && DtlsShouldDrop(ssl, ret)) {
- ssl->options.processReply = doProcessInit;
- ssl->buffers.inputBuffer.length = 0;
- ssl->buffers.inputBuffer.idx = 0;
-#ifdef WOLFSSL_DTLS_DROP_STATS
- ssl->replayDropCount++;
-#endif /* WOLFSSL_DTLS_DROP_STATS */
-
+ DropAndRestartProcessReply(ssl);
#ifdef WOLFSSL_DTLS13
/* return to send ACKS and shortcut rtx timer */
if (IsAtLeastTLSv1_3(ssl->version)
@@ -20896,7 +22468,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
#endif
if (ret != 0) {
switch (ret) {
- case VERSION_ERROR:
+ case WC_NO_ERR_TRACE(VERSION_ERROR):
/* send alert per RFC5246 Appendix E. Backward
* Compatibility */
if (ssl->options.side == WOLFSSL_CLIENT_END)
@@ -20904,7 +22476,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
wolfssl_alert_protocol_version);
break;
#ifdef HAVE_MAX_FRAGMENT
- case LENGTH_ERROR:
+ case WC_NO_ERR_TRACE(LENGTH_ERROR):
SendAlert(ssl, alert_fatal, record_overflow);
break;
#endif /* HAVE_MAX_FRAGMENT */
@@ -20934,7 +22506,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
if (!ssl->options.dtls) {
if ((ret = GetInputData(ssl, ssl->curSize)) < 0) {
#ifdef WOLFSSL_EXTRA_ALERTS
- if (ret != WANT_READ)
+ if (ret != WC_NO_ERR_TRACE(WANT_READ))
SendAlert(ssl, alert_fatal, bad_record_mac);
#endif
return ret;
@@ -20945,9 +22517,15 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
/* read ahead may already have */
used = ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx;
- if (used < ssl->curSize)
+ if (used < ssl->curSize) {
+ if (!RecordsCanSpanReads(ssl)) {
+ WOLFSSL_MSG("Partial record received, dropping");
+ DropAndRestartProcessReply(ssl);
+ continue;
+ }
if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
return ret;
+ }
#endif
}
@@ -20978,8 +22556,6 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
ssl->keys.padSz = 0;
ssl->options.processReply = verifyEncryptedMessage;
- /* in case > 1 msg per record */
- ssl->curStartIdx = ssl->buffers.inputBuffer.idx;
FALL_THROUGH;
/* verify digest of encrypted message */
@@ -20991,7 +22567,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
ssl->buffers.inputBuffer.idx,
ssl->curSize, ssl->curRL.type);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
#endif
if (ret < 0) {
@@ -21000,9 +22576,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
/* If in DTLS mode, if the decrypt fails for any
* reason, pretend the datagram never happened. */
if (ssl->options.dtls) {
- ssl->options.processReply = doProcessInit;
- ssl->buffers.inputBuffer.idx =
- ssl->buffers.inputBuffer.length;
+ DropAndRestartProcessReply(ssl);
return HandleDTLSDecryptFailed(ssl);
}
#endif /* WOLFSSL_DTLS */
@@ -21026,119 +22600,9 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
(!IsAtLeastTLSv1_3(ssl->version) ||
ssl->curRL.type != change_cipher_spec))
{
- bufferStatic* in = &ssl->buffers.inputBuffer;
-
- ret = SanityCheckCipherText(ssl, ssl->curSize);
- if (ret < 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- SendAlert(ssl, alert_fatal, bad_record_mac);
- #endif
- return ret;
- }
-
- if (atomicUser) {
- #ifdef ATOMIC_USER
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead) {
- ret = ssl->ctx->VerifyDecryptCb(ssl,
- in->buffer + in->idx, in->buffer + in->idx,
- ssl->curSize - MacSize(ssl),
- ssl->curRL.type, 1, &ssl->keys.padSz,
- ssl->DecryptVerifyCtx);
- }
- else
- #endif
- {
- ret = ssl->ctx->DecryptVerifyCb(ssl,
- in->buffer + in->idx,
- in->buffer + in->idx,
- ssl->curSize, ssl->curRL.type, 1,
- &ssl->keys.padSz, ssl->DecryptVerifyCtx);
- }
- #endif /* ATOMIC_USER */
- }
- else {
- if (!ssl->options.tls1_3) {
- #ifndef WOLFSSL_NO_TLS12
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead) {
- word32 digestSz = MacSize(ssl);
- ret = DecryptTls(ssl,
- in->buffer + in->idx,
- in->buffer + in->idx,
- ssl->curSize - (word16)digestSz);
- if (ret == 0) {
- byte invalid = 0;
- byte padding = (byte)-1;
- word32 i;
- word32 off = in->idx + ssl->curSize - digestSz - 1;
-
- /* Last of padding bytes - indicates length. */
- ssl->keys.padSz = in->buffer[off];
- /* Constant time checking of padding - don't leak
- * the length of the data.
- */
- /* Compare max pad bytes or at most data + pad. */
- for (i = 1; i < MAX_PAD_SIZE && off >= i; i++) {
- /* Mask on indicates this is expected to be a
- * padding byte.
- */
- padding &= ctMaskLTE(i, ssl->keys.padSz);
- /* When this is a padding byte and not equal
- * to length then mask is set.
- */
- invalid |= padding &
- ctMaskNotEq(in->buffer[off - i],
- ssl->keys.padSz);
- }
- /* If mask is set then there was an error. */
- if (invalid) {
- ret = DECRYPT_ERROR;
- }
- ssl->keys.padSz += 1;
- ssl->keys.decryptedCur = 1;
- }
- }
- else
- #endif
- {
- ret = DecryptTls(ssl,
- in->buffer + in->idx,
- in->buffer + in->idx,
- ssl->curSize);
- }
- #else
- ret = DECRYPT_ERROR;
- #endif
- }
- else
- {
- #ifdef WOLFSSL_TLS13
- byte *aad = (byte*)&ssl->curRL;
- word16 aad_size = RECORD_HEADER_SZ;
- #ifdef WOLFSSL_DTLS13
- if (ssl->options.dtls) {
- /* aad now points to the record header */
- aad = ssl->dtls13CurRL;
- aad_size = ssl->dtls13CurRlLength;
- }
- #endif /* WOLFSSL_DTLS13 */
- /* Don't send an alert for DTLS. We will just drop it
- * silently later. */
- ret = DecryptTls13(ssl,
- in->buffer + in->idx,
- in->buffer + in->idx,
- ssl->curSize,
- aad, aad_size);
- #else
- ret = DECRYPT_ERROR;
- #endif /* WOLFSSL_TLS13 */
- }
- (void)in;
- }
-
+ ret = DoDecrypt(ssl);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
#endif
@@ -21146,12 +22610,17 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
#ifndef WOLFSSL_NO_TLS12
/* handle success */
#ifndef WOLFSSL_AEAD_ONLY
- if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
+ if (ssl->options.tls1_1 &&
+ ssl->specs.cipher_type == block) {
ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
+ ssl->curSize -= ssl->specs.block_size;
+ }
#endif
/* go past TLSv1.1 IV */
- if (CipherHasExpIV(ssl))
+ if (CipherHasExpIV(ssl)) {
ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ;
+ ssl->curSize -= AESGCM_EXP_IV_SZ;
+ }
#endif
}
else {
@@ -21160,9 +22629,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
/* If in DTLS mode, if the decrypt fails for any
* reason, pretend the datagram never happened. */
if (ssl->options.dtls) {
- ssl->options.processReply = doProcessInit;
- ssl->buffers.inputBuffer.idx =
- ssl->buffers.inputBuffer.length;
+ DropAndRestartProcessReply(ssl);
return HandleDTLSDecryptFailed(ssl);
}
#endif /* WOLFSSL_DTLS */
@@ -21222,7 +22689,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
ssl->curSize, ssl->curRL.type,
&ssl->keys.padSz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
#endif
if (ret < 0) {
@@ -21230,9 +22697,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
/* If in DTLS mode, if the decrypt fails for any
* reason, pretend the datagram never happened. */
if (ssl->options.dtls) {
- ssl->options.processReply = doProcessInit;
- ssl->buffers.inputBuffer.idx =
- ssl->buffers.inputBuffer.length;
+ DropAndRestartProcessReply(ssl);
return HandleDTLSDecryptFailed(ssl);
}
#endif /* WOLFSSL_DTLS */
@@ -21248,39 +22713,58 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
ssl->keys.encryptSz = ssl->curSize;
ssl->keys.decryptedCur = 1;
-#ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3) {
- word32 i = (ssl->buffers.inputBuffer.idx +
- ssl->curSize - ssl->specs.aead_mac_size);
- /* check that the end of the logical length doesn't extend
- * past the real buffer */
- if (i > ssl->buffers.inputBuffer.length || i == 0) {
- WOLFSSL_ERROR(BUFFER_ERROR);
- return BUFFER_ERROR;
- }
-
- /* Remove padding from end of plain text. */
- for (--i; i > ssl->buffers.inputBuffer.idx; i--) {
- if (ssl->buffers.inputBuffer.buffer[i] != 0)
- break;
- }
+ }
- /* Get the real content type from the end of the data. */
- ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i];
- /* consider both contentType byte and MAC as padding */
- ssl->keys.padSz = ssl->buffers.inputBuffer.idx
- + ssl->curSize - i;
+ if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 1) {
+#if defined(WOLFSSL_TLS13) || \
+ (defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID))
+ int removePadding = 0;
+ if (ssl->options.tls1_3)
+ removePadding = 1;
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ if (!ssl->options.tls1_3 && ssl->options.dtls &&
+ ssl->curRL.type == dtls12_cid)
+ removePadding = 1;
+#endif
+ if (removePadding) {
+ ret = removeMsgInnerPadding(ssl);
+ if (ret != 0)
+ return ret;
}
+ else
#endif
+ {
+ /* With atomicUser the callback should have already included
+ * the mac in the padding size. The ETM callback doesn't do
+ * this for some reason. */
+ if (ssl->specs.cipher_type != aead
+#ifdef ATOMIC_USER
+ && (!atomicUser
+#ifdef HAVE_ENCRYPT_THEN_MAC
+ || ssl->options.startedETMRead
+#endif /* HAVE_ENCRYPT_THEN_MAC */
+ )
+#endif /* !ATOMIC_USER */
+ )
+ {
+ /* consider MAC as padding */
+ ssl->keys.padSz += MacSize(ssl);
+ }
+ }
+
}
+ /* in case > 1 msg per record */
+ ssl->curStartIdx = ssl->buffers.inputBuffer.idx;
+
ssl->options.processReply = runProcessingOneRecord;
FALL_THROUGH;
/* the record layer is here */
case runProcessingOneRecord:
-#ifdef WOLFSSL_DTLS13
+#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS13
if (IsAtLeastTLSv1_3(ssl->version)) {
if (!Dtls13CheckWindow(ssl)) {
/* drop packet */
@@ -21304,11 +22788,18 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
}
}
}
- else if (IsDtlsNotSctpMode(ssl)) {
+ else
+#endif /* WOLFSSL_DTLS13 */
+ if (IsDtlsNotSctpMode(ssl)) {
DtlsUpdateWindow(ssl);
}
+#ifdef WOLFSSL_DTLS_CID
+ /* Update the peer if we were able to de-protect the message */
+ if (IsEncryptionOn(ssl, 0))
+ dtlsProcessPendingPeer(ssl, 1);
+#endif
}
-#endif /* WOLFSSL_DTLS13 */
+#endif /* WOLFSSL_DTLS */
ssl->options.processReply = runProcessingOneMessage;
FALL_THROUGH;
@@ -21320,11 +22811,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
}
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (IsEncryptionOn(ssl, 0) && ssl->options.startedETMRead) {
- /* For TLS v1.1 the block size and explicit IV are added to idx,
- * so it needs to be included in this limit check */
- if ((ssl->curSize - ssl->keys.padSz -
- (ssl->buffers.inputBuffer.idx - ssl->curStartIdx) -
- MacSize(ssl) > MAX_PLAINTEXT_SZ)
+ if ((ssl->curSize - ssl->keys.padSz > MAX_PLAINTEXT_SZ)
#ifdef WOLFSSL_ASYNC_CRYPT
&& ssl->buffers.inputBuffer.length !=
ssl->buffers.inputBuffer.idx
@@ -21341,12 +22828,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
else
#endif
/* TLS13 plaintext limit is checked earlier before decryption */
- /* For TLS v1.1 the block size and explicit IV are added to idx,
- * so it needs to be included in this limit check */
if (!IsAtLeastTLSv1_3(ssl->version)
- && ssl->curSize - ssl->keys.padSz -
- (ssl->buffers.inputBuffer.idx - ssl->curStartIdx)
- > MAX_PLAINTEXT_SZ
+ && ssl->curSize - ssl->keys.padSz > MAX_PLAINTEXT_SZ
#ifdef WOLFSSL_ASYNC_CRYPT
&& ssl->buffers.inputBuffer.length !=
ssl->buffers.inputBuffer.idx
@@ -21373,14 +22856,15 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.length);
- if (ret == 0 || ret == WC_PENDING_E) {
+ if (ret == 0 ||
+ ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* Reset timeout as we have received a valid
* DTLS handshake message */
ssl->dtls_timeout = ssl->dtls_timeout_init;
}
else {
if (SendFatalAlertOnly(ssl, ret)
- == SOCKET_ERROR_E) {
+ == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) {
ret = SOCKET_ERROR_E;
}
}
@@ -21402,11 +22886,16 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
exit */
ssl->earlyData = no_early_data;
ssl->options.processReply = doProcessInit;
-
- return ZERO_RETURN;
+ if (ssl->options.clientInEarlyData)
+ return APP_DATA_READY;
}
#endif /* WOLFSSL_EARLY_DATA */
-
+ if (ret == 0 ||
+ ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
+ /* Reset timeout as we have received a valid
+ * DTLS handshake message */
+ ssl->dtls_timeout = ssl->dtls_timeout_init;
+ }
}
#endif /* WOLFSSL_DTLS13 */
}
@@ -21421,7 +22910,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
&ssl->buffers.inputBuffer.idx,
ssl->buffers.inputBuffer.length);
if (ret != 0) {
- if (SendFatalAlertOnly(ssl, ret) == SOCKET_ERROR_E)
+ if (SendFatalAlertOnly(ssl, ret) ==
+ WC_NO_ERR_TRACE(SOCKET_ERROR_E))
ret = SOCKET_ERROR_E;
}
#else
@@ -21443,7 +22933,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
ssl->options.handShakeState == HANDSHAKE_DONE) {
ssl->earlyData = no_early_data;
ssl->options.processReply = doProcessInit;
- return ZERO_RETURN;
+ if (ssl->options.clientInEarlyData)
+ return APP_DATA_READY;
}
#endif
#else
@@ -21455,13 +22946,13 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
* calling DtlsMsgPoolSend. This msg is done
* processing so let's move on. */
&& (!ssl->options.dtls
- || ret != WANT_WRITE)
+ || ret != WC_NO_ERR_TRACE(WANT_WRITE))
#ifdef WOLFSSL_ASYNC_CRYPT
/* In async case, on pending, move onto next message.
* Current message should have been DtlsMsgStore'ed and
* should be processed with DtlsMsgDrain */
&& (!ssl->options.dtls
- || ret != WC_PENDING_E)
+ || ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
) {
WOLFSSL_ERROR(ret);
@@ -21499,11 +22990,18 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
}
if (ssl->curSize != 1 ||
ssl->buffers.inputBuffer.buffer[i] != 1) {
- SendAlert(ssl, alert_fatal, illegal_parameter);
+ SendAlert(ssl, alert_fatal, unexpected_message);
WOLFSSL_ERROR_VERBOSE(UNKNOWN_RECORD_TYPE);
return UNKNOWN_RECORD_TYPE;
}
ssl->buffers.inputBuffer.idx++;
+ if (ssl->options.side == WOLFSSL_SERVER_END &&
+ !ssl->msgsReceived.got_client_hello) {
+ /* Can't appear before CH */
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ WOLFSSL_ERROR_VERBOSE(UNKNOWN_RECORD_TYPE);
+ return UNKNOWN_RECORD_TYPE;
+ }
if (!ssl->msgsReceived.got_change_cipher) {
ssl->msgsReceived.got_change_cipher = 1;
}
@@ -21512,6 +23010,11 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
WOLFSSL_ERROR_VERBOSE(UNKNOWN_RECORD_TYPE);
return UNKNOWN_RECORD_TYPE;
}
+ if (ssl->keys.decryptedCur == 1) {
+ SendAlert(ssl, alert_fatal, unexpected_message);
+ WOLFSSL_ERROR_VERBOSE(UNKNOWN_RECORD_TYPE);
+ return UNKNOWN_RECORD_TYPE;
+ }
break;
}
#endif
@@ -21532,28 +23035,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
}
if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) {
-#ifdef HAVE_AEAD
- if (ssl->specs.cipher_type == aead) {
- if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
- ssl->curSize -= AESGCM_EXP_IV_SZ;
- ssl->buffers.inputBuffer.idx += ssl->specs.aead_mac_size;
- ssl->curSize -= ssl->specs.aead_mac_size;
- }
- else
-#endif
- {
- ssl->buffers.inputBuffer.idx += ssl->keys.padSz;
- ssl->curSize -= (word16)ssl->keys.padSz;
- ssl->curSize -= ssl->specs.iv_size;
- }
-
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead) {
- word32 digestSz = MacSize(ssl);
- ssl->buffers.inputBuffer.idx += digestSz;
- ssl->curSize -= (word16)digestSz;
- }
- #endif
+ ssl->buffers.inputBuffer.idx += ssl->keys.padSz;
+ ssl->curSize -= (word16)ssl->keys.padSz;
}
if (ssl->curSize != 1) {
@@ -21574,7 +23057,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
/* Check for duplicate CCS message in DTLS mode.
* DTLS allows for duplicate messages, and it should be
* skipped. Also skip if out of order. */
- if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E)
+ if (ret != WC_NO_ERR_TRACE(DUPLICATE_MSG_E) &&
+ ret != WC_NO_ERR_TRACE(OUT_OF_ORDER_E))
return ret;
/* Reset error */
ret = 0;
@@ -21653,6 +23137,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
#endif
}
#endif
+ #ifndef WOLFSSL_RW_THREADED
#ifdef WOLFSSL_TLS13
if (ssl->keys.keyUpdateRespond) {
WOLFSSL_MSG("No KeyUpdate from peer seen");
@@ -21660,6 +23145,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
return SANITY_MSG_E;
}
#endif
+ #endif
if ((ret = DoApplicationData(ssl,
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
@@ -21669,7 +23155,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
defined(HAVE_SECURE_RENEGOTIATION)
/* Not really an error. We will return after cleaning
* up the processReply state. */
- if (ret != APP_DATA_READY)
+ if (ret != WC_NO_ERR_TRACE(APP_DATA_READY))
#endif
return ret;
}
@@ -21756,32 +23242,17 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
ssl->options.processReply = runProcessingOneMessage;
if (IsEncryptionOn(ssl, 0)) {
- WOLFSSL_MSG("Bundled encrypted messages, remove middle pad");
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead) {
- word32 digestSz = MacSize(ssl);
- if (ssl->buffers.inputBuffer.idx >=
- ssl->keys.padSz + digestSz) {
- ssl->buffers.inputBuffer.idx -=
- ssl->keys.padSz + digestSz;
- }
- else {
- WOLFSSL_MSG("\tmiddle padding error");
- WOLFSSL_ERROR_VERBOSE(FATAL_ERROR);
- return FATAL_ERROR;
- }
+ /* With encryption on, we advance the index by the value
+ * of ssl->keys.padSz. Since padding only appears once, we
+ * only can do this at the end of record parsing. We have to
+ * reset the index to the start of the next message here. */
+ if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) {
+ ssl->buffers.inputBuffer.idx -= ssl->keys.padSz;
}
- else
- #endif
- {
- if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) {
- ssl->buffers.inputBuffer.idx -= ssl->keys.padSz;
- }
- else {
- WOLFSSL_MSG("\tmiddle padding error");
- WOLFSSL_ERROR_VERBOSE(FATAL_ERROR);
- return FATAL_ERROR;
- }
+ else {
+ WOLFSSL_MSG("\tBuffer advanced not enough error");
+ WOLFSSL_ERROR_VERBOSE(FATAL_ERROR);
+ return FATAL_ERROR;
}
}
}
@@ -21798,7 +23269,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
#endif
#if defined(WOLFSSL_DTLS13) || defined(HAVE_SECURE_RENEGOTIATION)
/* Signal to user that we have application data ready to read */
- if (ret == APP_DATA_READY)
+ if (ret == WC_NO_ERR_TRACE(APP_DATA_READY))
return ret;
#endif
/* It is safe to shrink the input buffer here now. local vars will
@@ -21814,6 +23285,35 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
}
}
+int ProcessReply(WOLFSSL* ssl)
+{
+ return ProcessReplyEx(ssl, 0);
+}
+
+int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
+{
+ int ret;
+
+ ret = DoProcessReplyEx(ssl, allowSocketErr);
+
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ if (ssl->options.dtls) {
+ /* Don't clear pending peer if we are going to re-enter
+ * DoProcessReplyEx */
+ if (ret != WC_NO_ERR_TRACE(WANT_READ)
+#ifdef WOLFSSL_ASYNC_CRYPT
+ && ret != WC_NO_ERR_TRACE(WC_PENDING_E)
+#endif
+ ) {
+ dtlsClearPeer(&ssl->buffers.dtlsCtx.pendingPeer);
+ ssl->buffers.dtlsCtx.processingPendingRecord = 0;
+ }
+ }
+#endif
+
+ return ret;
+}
+
#if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) || \
(defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT))
int SendChangeCipher(WOLFSSL* ssl)
@@ -21824,17 +23324,17 @@ int SendChangeCipher(WOLFSSL* ssl)
int ret;
#ifdef OPENSSL_EXTRA
- ssl->cbmode = SSL_CB_MODE_WRITE;
+ ssl->cbmode = WOLFSSL_CB_MODE_WRITE;
if (ssl->options.side == WOLFSSL_SERVER_END){
ssl->options.serverState = SERVER_CHANGECIPHERSPEC_COMPLETE;
if (ssl->CBIS != NULL)
- ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_ACCEPT_LOOP, WOLFSSL_SUCCESS);
}
- else{
+ else {
ssl->options.clientState =
CLIENT_CHANGECIPHERSPEC_COMPLETE;
if (ssl->CBIS != NULL)
- ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_CONNECT_LOOP, WOLFSSL_SUCCESS);
}
#endif
@@ -21860,6 +23360,8 @@ int SendChangeCipher(WOLFSSL* ssl)
/* get output buffer */
output = GetOutputBuffer(ssl);
+ if (output == NULL)
+ return BUFFER_E;
AddRecordHeader(output, 1, change_cipher_spec, ssl, CUR_ORDER);
@@ -21872,7 +23374,7 @@ int SendChangeCipher(WOLFSSL* ssl)
input[0] = 1; /* turn it on */
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl) &&
- (ret = DtlsMsgPoolSave(ssl, input, inputSz, change_cipher_hs)) != 0) {
+ (ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz, change_cipher_hs)) != 0) {
return ret;
}
#endif
@@ -21885,7 +23387,7 @@ int SendChangeCipher(WOLFSSL* ssl)
#ifdef WOLFSSL_DTLS
else {
if (IsDtlsNotSctpMode(ssl)) {
- if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, change_cipher_hs)) != 0)
+ if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, change_cipher_hs)) != 0)
return ret;
DtlsSEQIncrement(ssl, CUR_ORDER);
}
@@ -21900,7 +23402,7 @@ int SendChangeCipher(WOLFSSL* ssl)
return ret;
}
#endif
- ssl->buffers.outputBuffer.length += sendSz;
+ ssl->buffers.outputBuffer.length += (word32)sendSz;
#ifdef WOLFSSL_TLS13
if (!ssl->options.tls1_3)
@@ -21929,7 +23431,8 @@ int SendChangeCipher(WOLFSSL* ssl)
else
return SendBuffered(ssl);
}
-#endif
+#endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS ||
+ * (WOLFSSL_TLS13 && WOLFSSL_TLS13_MIDDLEBOX_COMPAT) */
#if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY)
@@ -21989,7 +23492,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
ret = wc_Md5Final(&md5, result);
#ifdef WOLFSSL_ASYNC_CRYPT
/* TODO: Make non-blocking */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
}
#endif
@@ -22009,7 +23512,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
ret = wc_Md5Final(&md5, digest);
#ifdef WOLFSSL_ASYNC_CRYPT
/* TODO: Make non-blocking */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE);
}
#endif
@@ -22039,7 +23542,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
ret = wc_ShaFinal(&sha, result);
#ifdef WOLFSSL_ASYNC_CRYPT
/* TODO: Make non-blocking */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
}
#endif
@@ -22059,7 +23562,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
ret = wc_ShaFinal(&sha, digest);
#ifdef WOLFSSL_ASYNC_CRYPT
/* TODO: Make non-blocking */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE);
}
#endif
@@ -22110,9 +23613,7 @@ static int BuildMD5_CertVerify(const WOLFSSL* ssl, byte* digest)
}
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#endif
+ WC_FREE_VAR_EX(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX);
return ret;
}
@@ -22155,9 +23656,7 @@ static int BuildSHA_CertVerify(const WOLFSSL* ssl, byte* digest)
}
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
-#endif
+ WC_FREE_VAR_EX(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX);
return ret;
}
@@ -22256,6 +23755,10 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
BuildMsgArgs lcl_args;
#endif
+#ifdef WOLFSSL_DTLS_CID
+ byte cidSz = 0;
+#endif
+
WOLFSSL_ENTER("BuildMessage");
if (ssl == NULL) {
@@ -22271,11 +23774,12 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
(void)epochOrder;
-#ifndef NO_TLS
#if defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_TLS13)
+ /* TLS v1.3 only */
return BuildTls13Message(ssl, output, outSz, input, inSz, type,
hashOutput, sizeOnly, asyncOkay);
#else
+ /* TLS v1.2 or v1.3 */
#ifdef WOLFSSL_TLS13
if (ssl->options.tls1_3) {
return BuildTls13Message(ssl, output, outSz, input, inSz, type,
@@ -22283,6 +23787,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
}
#endif
+#ifndef WOLFSSL_NO_TLS12
#ifdef WOLFSSL_ASYNC_CRYPT
ret = WC_NO_PENDING_E;
if (asyncOkay) {
@@ -22292,7 +23797,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
args = &ssl->async->buildArgs;
ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* Check for error */
if (ret < 0)
goto exit_buildmsg;
@@ -22306,7 +23811,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
/* Reset state */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_NO_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_NO_PENDING_E))
#endif
{
ret = 0;
@@ -22316,9 +23821,10 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
ssl->options.buildMsgState = BUILD_MSG_BEGIN;
XMEMSET(args, 0, sizeof(BuildMsgArgs));
- args->sz = RECORD_HEADER_SZ + inSz;
+ args->sz = RECORD_HEADER_SZ + (word32)inSz;
args->idx = RECORD_HEADER_SZ;
args->headerSz = RECORD_HEADER_SZ;
+ args->type = (byte)type;
}
switch (ssl->options.buildMsgState) {
@@ -22384,6 +23890,14 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
args->sz += DTLS_RECORD_EXTRA;
args->idx += DTLS_RECORD_EXTRA;
args->headerSz += DTLS_RECORD_EXTRA;
+ #ifdef WOLFSSL_DTLS_CID
+ if ((cidSz = DtlsGetCidTxSize(ssl)) > 0) {
+ args->sz += cidSz;
+ args->idx += cidSz;
+ args->headerSz += cidSz;
+ args->sz++; /* real_type. no padding. */
+ }
+ #endif
}
#endif
@@ -22465,7 +23979,12 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
#endif
args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */
- AddRecordHeader(output, args->size, (byte)type, ssl, epochOrder);
+
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ if (ssl->options.dtls && DtlsGetCidTxSize(ssl) > 0)
+ args->type = dtls12_cid;
+#endif
+ AddRecordHeader(output, args->size, args->type, ssl, epochOrder);
/* write to output */
if (args->ivSz > 0) {
@@ -22473,8 +23992,17 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
min(args->ivSz, MAX_IV_SZ));
args->idx += min(args->ivSz, MAX_IV_SZ);
}
- XMEMCPY(output + args->idx, input, inSz);
- args->idx += inSz;
+ XMEMCPY(output + args->idx, input, (size_t)(inSz));
+ args->idx += (word32)inSz;
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ if (ssl->options.dtls && DtlsGetCidTxSize(ssl) > 0) {
+ output[args->idx++] = (byte)type; /* type goes after input */
+ inSz++;
+ }
+#endif
+ /* Make sure we don't access input anymore as inSz may have been
+ * incremented */
+ input = NULL;
ssl->options.buildMsgState = BUILD_MSG_HASH;
}
@@ -22486,7 +24014,8 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
goto exit_buildmsg;
if (type == handshake && hashOutput) {
- ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz);
+ ret = HashOutput(ssl, output,
+ (int)(args->headerSz + (word32)inSz), (int)args->ivSz);
if (ret != 0)
goto exit_buildmsg;
}
@@ -22522,7 +24051,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
if (ssl->options.startedETMWrite) {
if (ssl->ctx->EncryptMacCb) {
ret = ssl->ctx->EncryptMacCb(ssl, output + args->idx +
- args->pad + 1, type, 0,
+ args->pad + 1, args->type, 0,
output + args->headerSz,
output + args->headerSz,
args->size - args->digestSz,
@@ -22535,8 +24064,9 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
{
if (ssl->ctx->MacEncryptCb) {
ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx,
- output + args->headerSz + args->ivSz, inSz,
- type, 0, output + args->headerSz,
+ output + args->headerSz + args->ivSz,
+ (unsigned int)inSz, args->type, 0,
+ output + args->headerSz,
output + args->headerSz, args->size,
ssl->MacEncryptCtx);
goto exit_buildmsg;
@@ -22553,33 +24083,26 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
#ifdef HAVE_TRUNCATED_HMAC
if (ssl->truncated_hmac &&
ssl->specs.hash_size > args->digestSz) {
- #ifdef WOLFSSL_SMALL_STACK
- byte* hmac;
- #else
- byte hmac[WC_MAX_DIGEST_SIZE];
- #endif
+ WC_DECLARE_VAR(hmac, byte, WC_MAX_DIGEST_SIZE, 0);
- #ifdef WOLFSSL_SMALL_STACK
- hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap,
- DYNAMIC_TYPE_DIGEST);
- if (hmac == NULL)
- ERROR_OUT(MEMORY_E, exit_buildmsg);
- #endif
+ WC_ALLOC_VAR_EX(hmac, byte, WC_MAX_DIGEST_SIZE, ssl->heap,
+ DYNAMIC_TYPE_DIGEST,
+ ERROR_OUT(MEMORY_E,exit_buildmsg));
ret = ssl->hmac(ssl, hmac,
- output + args->headerSz + args->ivSz, inSz,
- -1, type, 0, epochOrder);
+ output + args->headerSz + args->ivSz,
+ (word32)inSz, -1, args->type, 0,
+ epochOrder);
XMEMCPY(output + args->idx, hmac, args->digestSz);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
- #endif
+ WC_FREE_VAR_EX(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
}
else
#endif
{
ret = ssl->hmac(ssl, output + args->idx, output +
- args->headerSz + args->ivSz, inSz, -1, type, 0, epochOrder);
+ args->headerSz + args->ivSz, (word32)inSz, -1,
+ args->type, 0, epochOrder);
}
}
#endif /* WOLFSSL_AEAD_ONLY */
@@ -22615,18 +24138,42 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
ssl->keys.dtls_prev_sequence_number_lo;
}
#endif
+
+#ifdef WOLFSSL_THREADED_CRYPT
+ if (asyncOkay) {
+ WOLFSSL_MSG("Not encrypting\n");
+ /* make sure build message state is reset */
+ ssl->options.buildMsgState = BUILD_MSG_BEGIN;
+
+ /* return sz on success */
+ if (ret == 0) {
+ ret = args->sz;
+ }
+ else {
+ WOLFSSL_ERROR_VERBOSE(ret);
+ }
+
+ /* Final cleanup */
+ FreeBuildMsgArgs(ssl, args);
+
+ return ret;
+ }
+ else
+#endif
+ {
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
if (ssl->options.startedETMWrite) {
ret = Encrypt(ssl, output + args->headerSz,
output + args->headerSz,
(word16)(args->size - args->digestSz),
- asyncOkay);
+ asyncOkay, args->type);
}
else
#endif
{
ret = Encrypt(ssl, output + args->headerSz,
- output + args->headerSz, args->size, asyncOkay);
+ output + args->headerSz, args->size, asyncOkay,
+ args->type);
}
#if defined(HAVE_SECURE_RENEGOTIATION) && defined(WOLFSSL_DTLS)
/* Restore sequence numbers */
@@ -22636,11 +24183,12 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
ssl->keys.dtls_sequence_number_lo = dtls_sequence_number_lo;
}
#endif
+ }
}
if (ret != 0) {
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret != WC_PENDING_E)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
/* Zeroize plaintext. */
@@ -22673,36 +24221,27 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
#ifdef HAVE_TRUNCATED_HMAC
if (ssl->truncated_hmac &&
ssl->specs.hash_size > args->digestSz) {
- #ifdef WOLFSSL_SMALL_STACK
- byte* hmac = NULL;
- #else
- byte hmac[WC_MAX_DIGEST_SIZE];
- #endif
+ WC_DECLARE_VAR(hmac, byte, WC_MAX_DIGEST_SIZE, 0);
- #ifdef WOLFSSL_SMALL_STACK
- hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap,
- DYNAMIC_TYPE_DIGEST);
- if (hmac == NULL)
- ERROR_OUT(MEMORY_E, exit_buildmsg);
- #endif
+ WC_ALLOC_VAR_EX(hmac, byte, WC_MAX_DIGEST_SIZE, ssl->heap,
+ DYNAMIC_TYPE_DIGEST,
+ ERROR_OUT(MEMORY_E,exit_buildmsg));
ret = ssl->hmac(ssl, hmac, output + args->headerSz,
- args->ivSz + inSz + args->pad + 1, -1, type,
- 0, epochOrder);
+ args->ivSz + inSz + args->pad + 1, -1,
+ args->type, 0, epochOrder);
XMEMCPY(output + args->idx + args->pad + 1, hmac,
args->digestSz);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
- #endif
+ WC_FREE_VAR_EX(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST);
}
else
#endif
{
ret = ssl->hmac(ssl, output + args->idx + args->pad + 1,
output + args->headerSz,
- args->ivSz + inSz + args->pad + 1, -1, type,
- 0, epochOrder);
+ args->ivSz + (word32)inSz + args->pad + 1,
+ -1, args->type, 0, epochOrder);
}
}
#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
@@ -22717,7 +24256,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
WOLFSSL_LEAVE("BuildMessage", ret);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return ret;
}
#endif
@@ -22732,7 +24271,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
/* return sz on success */
if (ret == 0) {
- ret = args->sz;
+ ret = (int)args->sz;
}
else {
WOLFSSL_ERROR_VERBOSE(ret);
@@ -22740,9 +24279,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
/* Final cleanup */
FreeBuildMsgArgs(ssl, args);
-
return ret;
-#endif /* !WOLFSSL_NO_TLS12 */
#else
(void)outSz;
(void)inSz;
@@ -22750,8 +24287,8 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
(void)hashOutput;
(void)asyncOkay;
return NOT_COMPILED_IN;
-#endif /* NO_TLS */
-
+#endif /* !WOLFSSL_NO_TLS12 */
+#endif
}
#ifndef WOLFSSL_NO_TLS12
@@ -22773,6 +24310,13 @@ int SendFinished(WOLFSSL* ssl)
/* check for available size */
outputSz = sizeof(input) + MAX_MSG_EXTRA;
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ if (ssl->options.dtls) {
+ byte cidSz = 0;
+ if ((cidSz = DtlsGetCidTxSize(ssl)) > 0)
+ outputSz += cidSz + 1; /* +1 for inner content type */
+ }
+#endif
/* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
* is not advanced yet */
@@ -22796,7 +24340,8 @@ int SendFinished(WOLFSSL* ssl)
/* get output buffer */
output = GetOutputBuffer(ssl);
- AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl);
+ AddHandShakeHeader(input, (word32)finishedSz, 0,
+ (word32)finishedSz, finished, ssl);
/* make finished hashes */
hashes = (Hashes*)&input[headerSz];
@@ -22836,6 +24381,7 @@ int SendFinished(WOLFSSL* ssl)
}
#endif
+ ssl->keys.encryptionOn = 1;
sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz,
handshake, 1, 0, 0, CUR_ORDER);
if (sendSz < 0)
@@ -22849,9 +24395,9 @@ int SendFinished(WOLFSSL* ssl)
if (ssl->options.side == WOLFSSL_SERVER_END) {
#ifdef OPENSSL_EXTRA
ssl->options.serverState = SERVER_FINISHED_COMPLETE;
- ssl->cbmode = SSL_CB_MODE_WRITE;
+ ssl->cbmode = WOLFSSL_CB_MODE_WRITE;
if (ssl->CBIS != NULL)
- ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_HANDSHAKE_DONE, WOLFSSL_SUCCESS);
#endif
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
@@ -22864,9 +24410,9 @@ int SendFinished(WOLFSSL* ssl)
if (ssl->options.side == WOLFSSL_CLIENT_END) {
#ifdef OPENSSL_EXTRA
ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
- ssl->cbmode = SSL_CB_MODE_WRITE;
+ ssl->cbmode = WOLFSSL_CB_MODE_WRITE;
if (ssl->CBIS != NULL)
- ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_HANDSHAKE_DONE, WOLFSSL_SUCCESS);
#endif
ssl->options.handShakeState = HANDSHAKE_DONE;
ssl->options.handShakeDone = 1;
@@ -22886,7 +24432,7 @@ int SendFinished(WOLFSSL* ssl)
}
#endif
- ssl->buffers.outputBuffer.length += sendSz;
+ ssl->buffers.outputBuffer.length += (word32)sendSz;
ret = SendBuffered(ssl);
@@ -22908,6 +24454,7 @@ int SendFinished(WOLFSSL* ssl)
return ret;
}
#endif /* WOLFSSL_NO_TLS12 */
+#endif /* !NO_TLS */
#ifndef NO_WOLFSSL_SERVER
#if (!defined(WOLFSSL_NO_TLS12) && \
@@ -22919,29 +24466,35 @@ int SendFinished(WOLFSSL* ssl)
*
* Returns 0 on success
*/
-static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
- DecodedCert* cert, byte* certData, word32 length)
+int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request,
+ DecodedCert* cert, byte* certData, word32 length,
+ byte *ctxOwnsRequest)
{
int ret;
if (request != NULL)
XMEMSET(request, 0, sizeof(OcspRequest));
+ if (ctxOwnsRequest!= NULL)
+ *ctxOwnsRequest = 0;
+
InitDecodedCert(cert, certData, length, ssl->heap);
/* TODO: Setup async support here */
- ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, SSL_CM(ssl));
- if (ret != 0) {
+ ret = ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, SSL_CM(ssl), NULL);
+ if (ret != 0)
WOLFSSL_MSG("ParseCert failed");
- }
if (ret == 0)
ret = InitOcspRequest(request, cert, 0, ssl->heap);
if (ret == 0) {
/* make sure ctx OCSP request is updated */
- if (!ssl->buffers.weOwnCert) {
+ if (!ssl->buffers.weOwnCert && SSL_CM(ssl) != NULL) {
wolfSSL_Mutex* ocspLock = &SSL_CM(ssl)->ocsp_stapling->ocspLock;
if (wc_LockMutex(ocspLock) == 0) {
- if (ssl->ctx->certOcspRequest == NULL)
+ if (ssl->ctx->certOcspRequest == NULL) {
ssl->ctx->certOcspRequest = request;
+ if (ctxOwnsRequest!= NULL)
+ *ctxOwnsRequest = 1;
+ }
wc_UnLockMutex(ocspLock);
}
}
@@ -22970,6 +24523,7 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
int ret = 0;
OcspRequest* request = NULL;
byte createdRequest = 0;
+ byte ctxOwnsRequest = 0;
if (ssl == NULL || ocspRequest == NULL || response == NULL)
return BAD_FUNC_ARG;
@@ -22983,22 +24537,14 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
if (request == NULL || ssl->buffers.weOwnCert) {
DerBuffer* der = ssl->buffers.certificate;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
- #else
- DecodedCert cert[1];
- #endif
+ WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
/* unable to fetch status. skip. */
if (der->buffer == NULL || der->length == 0)
return 0;
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_E;
- #endif
+ WC_ALLOC_VAR_EX(cert, DecodedCert, 1, ssl->heap, DYNAMIC_TYPE_DCERT,
+ return MEMORY_E);
request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
DYNAMIC_TYPE_OCSP_REQUEST);
if (request == NULL)
@@ -23007,7 +24553,7 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
createdRequest = 1;
if (ret == 0) {
ret = CreateOcspRequest(ssl, request, cert, der->buffer,
- der->length);
+ der->length, &ctxOwnsRequest);
}
if (ret != 0) {
@@ -23015,9 +24561,7 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
request = NULL;
}
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
- #endif
+ WC_FREE_VAR_EX(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
}
if (ret == 0) {
@@ -23026,15 +24570,15 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest,
ssl->heap);
/* Suppressing, not critical */
- if (ret == OCSP_CERT_REVOKED ||
- ret == OCSP_CERT_UNKNOWN ||
- ret == OCSP_LOOKUP_FAIL) {
+ if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED) ||
+ ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN) ||
+ ret == WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL)) {
ret = 0;
}
}
/* free request up if error case found otherwise return it */
- if (ret != 0 && createdRequest) {
+ if (ret != 0 && createdRequest && !ctxOwnsRequest) {
FreeOcspRequest(request);
XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
}
@@ -23066,20 +24610,104 @@ int cipherExtraData(WOLFSSL* ssl)
cipherExtra = ssl->specs.iv_size + ssl->specs.block_size +
ssl->specs.hash_size;
}
+ /* Add space needed for the CID */
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ if (ssl->options.dtls) {
+ byte cidSz = 0;
+ if ((cidSz = DtlsGetCidTxSize(ssl)) > 0)
+ cipherExtra += cidSz + 1; /* +1 for inner content type */
+ }
+#endif
/* Sanity check so we don't ever return negative. */
return cipherExtra > 0 ? cipherExtra : 0;
}
#ifndef WOLFSSL_NO_TLS12
+static int BuildMsgOrHashOutput(WOLFSSL* ssl, byte* output, int* sendSz,
+ int inputSz, enum HandShakeType type,
+ const char *name)
+{
+ int ret = 0;
+ if (IsEncryptionOn(ssl, 1)) {
+ byte* input;
+ int recordHeaderSz = RECORD_HEADER_SZ;
+
+ if (ssl->options.dtls)
+ recordHeaderSz += DTLS_RECORD_EXTRA;
+ inputSz -= recordHeaderSz;
+ if (inputSz <= 0) {
+ WOLFSSL_MSG("Bad inputSz");
+ return BUFFER_E;
+ }
+ input = (byte*)XMALLOC((size_t)inputSz, ssl->heap,
+ DYNAMIC_TYPE_IN_BUFFER);
+ if (input == NULL)
+ return MEMORY_E;
+
+ XMEMCPY(input, output + recordHeaderSz, (size_t)(inputSz));
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl) &&
+ (ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz,
+ type)) != 0) {
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ return ret;
+ }
+ #else
+ (void)type;
+ #endif
+ *sendSz = BuildMessage(ssl, output, *sendSz, input, inputSz,
+ handshake, 1, 0, 0, CUR_ORDER);
+ XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+
+ if (*sendSz < 0)
+ return *sendSz;
+ } else {
+ if (type == certificate_request)
+ *sendSz = inputSz;
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ ret = DtlsMsgPoolSave(ssl, output, (word32)*sendSz, type);
+ if (ret != 0)
+ return ret;
+ }
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
+ ret = HashOutput(ssl, output, *sendSz, 0);
+ if (ret != 0)
+ return ret;
+ }
+#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
+ if (ssl->hsInfoOn)
+ AddPacketName(ssl, name);
+ if (ssl->toInfoOn) {
+ ret = AddPacketInfo(ssl, name, handshake, output,
+ *sendSz, WRITE_PROTO, 0, ssl->heap);
+ if (ret != 0)
+ return ret;
+ }
+#else
+ (void)name;
+#endif
+ ssl->buffers.outputBuffer.length += (word32)*sendSz;
+ ssl->options.buildingMsg = 0;
+ return 0;
+}
+
#ifndef NO_CERTS
-#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)
+
+#if (!defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)) && \
+ !defined(NO_TLS)
/* handle generation of certificate (11) */
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");
@@ -23089,6 +24717,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
@@ -23111,10 +24754,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) {
@@ -23133,7 +24785,7 @@ int SendCertificate(WOLFSSL* ssl)
maxFragment = MAX_RECORD_SIZE;
- maxFragment = wolfSSL_GetMaxFragSize(ssl, maxFragment);
+ maxFragment = (word32)wolfSSL_GetMaxFragSize(ssl, (int)maxFragment);
while (length > 0 && ret == 0) {
byte* output = NULL;
@@ -23153,12 +24805,12 @@ int SendCertificate(WOLFSSL* ssl)
else {
fragSz = maxFragment - HANDSHAKE_HEADER_SZ;
}
- sendSz += fragSz + HANDSHAKE_HEADER_SZ;
+ sendSz += (int)(fragSz) + HANDSHAKE_HEADER_SZ;
i += HANDSHAKE_HEADER_SZ;
}
else {
fragSz = min(length, maxFragment);
- sendSz += fragSz;
+ sendSz += (int)(fragSz);
}
if (IsEncryptionOn(ssl, 1))
@@ -23207,12 +24859,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))
@@ -23222,10 +24880,10 @@ int SendCertificate(WOLFSSL* ssl)
fragSz -= CERT_HEADER_SZ;
if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) {
- HashRaw(ssl, ssl->buffers.certificate->buffer, certSz);
+ HashRaw(ssl, ssl->buffers.certificate->buffer, (int)certSz);
if (certChainSz)
HashRaw(ssl, ssl->buffers.certChain->buffer,
- certChainSz);
+ (int)certChainSz);
}
}
}
@@ -23264,7 +24922,7 @@ int SendCertificate(WOLFSSL* ssl)
if (IsEncryptionOn(ssl, 1)) {
byte* input = NULL;
- int inputSz = i; /* build msg adds rec hdr */
+ int inputSz = (int)i; /* build msg adds rec hdr */
int recordHeaderSz = RECORD_HEADER_SZ;
if (ssl->options.dtls)
@@ -23277,11 +24935,11 @@ int SendCertificate(WOLFSSL* ssl)
}
if (inputSz > 0) { /* clang thinks could be zero, let's help */
- input = (byte*)XMALLOC(inputSz, ssl->heap,
+ input = (byte*)XMALLOC((size_t)inputSz, ssl->heap,
DYNAMIC_TYPE_IN_BUFFER);
if (input == NULL)
return MEMORY_E;
- XMEMCPY(input, output + recordHeaderSz, inputSz);
+ XMEMCPY(input, output + recordHeaderSz, (size_t)(inputSz));
}
#ifndef WOLFSSL_DTLS
@@ -23293,7 +24951,7 @@ int SendCertificate(WOLFSSL* ssl)
handshake, 1, 0, 0, CUR_ORDER);
else /* DTLS 1.2 has to ignore fragmentation in hashing so we need to
* calculate the hash ourselves above */ {
- if ((ret = DtlsMsgPoolSave(ssl, input, inputSz, certificate)) != 0) {
+ if ((ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz, certificate)) != 0) {
XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
return ret;
}
@@ -23308,10 +24966,10 @@ int SendCertificate(WOLFSSL* ssl)
return sendSz;
}
else {
- sendSz = i;
+ sendSz = (int)i;
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl)) {
- if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, certificate)) != 0)
+ if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, certificate)) != 0)
return ret;
}
if (ssl->options.dtls)
@@ -23330,12 +24988,12 @@ int SendCertificate(WOLFSSL* ssl)
}
#endif
- ssl->buffers.outputBuffer.length += sendSz;
+ ssl->buffers.outputBuffer.length += (word32)sendSz;
if (!ssl->options.groupMessages)
ret = SendBuffered(ssl);
}
- if (ret != WANT_WRITE) {
+ if (ret != WC_NO_ERR_TRACE(WANT_WRITE)) {
/* Clean up the fragment offset. */
ssl->options.buildingMsg = 0;
ssl->fragOffset = 0;
@@ -23353,8 +25011,10 @@ int SendCertificate(WOLFSSL* ssl)
return ret;
}
-#endif /* !NO_WOLFSSL_SERVER || !WOLFSSL_NO_CLIENT_AUTH */
+#endif /* !NO_TLS && (!NO_WOLFSSL_SERVER || !WOLFSSL_NO_CLIENT_AUTH) */
+
+#if !defined(NO_TLS)
/* handle generation of certificate_request (13) */
int SendCertificateRequest(WOLFSSL* ssl)
{
@@ -23379,7 +25039,7 @@ int SendCertificateRequest(WOLFSSL* ssl)
#ifndef WOLFSSL_NO_CA_NAMES
/* Certificate Authorities */
- names = SSL_CA_NAMES(ssl);
+ names = SSL_PRIORITY_CA_NAMES(ssl);
while (names != NULL) {
byte seq[MAX_SEQ_SZ];
WOLFSSL_X509_NAME* name = names->data.name;
@@ -23424,7 +25084,7 @@ int SendCertificateRequest(WOLFSSL* ssl)
/* get output buffer */
output = GetOutputBuffer(ssl);
- AddHeaders(output, reqSz, certificate_request, ssl);
+ AddHeaders(output, (word32)reqSz, certificate_request, ssl);
/* write to output */
output[i++] = (byte)typeTotal; /* # of types */
@@ -23471,7 +25131,7 @@ int SendCertificateRequest(WOLFSSL* ssl)
c16toa((word16)dnLen, &output[i]); /* auth's */
i += REQ_HEADER_SZ;
#ifndef WOLFSSL_NO_CA_NAMES
- names = SSL_CA_NAMES(ssl);
+ names = SSL_PRIORITY_CA_NAMES(ssl);
while (names != NULL) {
byte seq[MAX_SEQ_SZ];
WOLFSSL_X509_NAME* name = names->data.name;
@@ -23487,91 +25147,39 @@ int SendCertificateRequest(WOLFSSL* ssl)
names = names->next;
}
#endif
- (void)i;
-
- if (IsEncryptionOn(ssl, 1)) {
- byte* input = NULL;
- int inputSz = i; /* build msg adds rec hdr */
- int recordHeaderSz = RECORD_HEADER_SZ;
-
- if (ssl->options.dtls)
- recordHeaderSz += DTLS_RECORD_EXTRA;
- inputSz -= recordHeaderSz;
-
- if (inputSz <= 0) {
- WOLFSSL_MSG("Send Cert Req bad inputSz");
- return BUFFER_E;
- }
-
- input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- if (input == NULL)
- return MEMORY_E;
-
- XMEMCPY(input, output + recordHeaderSz, inputSz);
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl) &&
- (ret = DtlsMsgPoolSave(ssl, input, inputSz, certificate_request)) != 0) {
- XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- return ret;
- }
- #endif
- sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
- handshake, 1, 0, 0, CUR_ORDER);
- XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-
- if (sendSz < 0)
- return sendSz;
- } else {
- sendSz = i;
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl)) {
- if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, certificate_request)) != 0)
- return ret;
- }
- if (ssl->options.dtls)
- DtlsSEQIncrement(ssl, CUR_ORDER);
- #endif
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0)
- return ret;
- }
+ ret = BuildMsgOrHashOutput(ssl, output, &sendSz, i, certificate_request,
+ "CertificateRequest");
+ if (ret != 0)
+ return ret;
- #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
- if (ssl->hsInfoOn)
- AddPacketName(ssl, "CertificateRequest");
- if (ssl->toInfoOn) {
- ret = AddPacketInfo(ssl, "CertificateRequest", handshake, output,
- sendSz, WRITE_PROTO, 0, ssl->heap);
- if (ret != 0)
- return ret;
- }
- #endif
- ssl->buffers.outputBuffer.length += sendSz;
if (ssl->options.groupMessages)
ret = 0;
else
ret = SendBuffered(ssl);
- ssl->options.buildingMsg = 0;
WOLFSSL_LEAVE("SendCertificateRequest", ret);
WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND);
return ret;
}
+#endif /* !NO_TLS */
+
#ifndef NO_WOLFSSL_SERVER
+
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
- byte count)
+ word32 count)
{
byte* output = NULL;
word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
word32 length = ENUM_LEN;
+ word32 headerSz= idx;
int sendSz = 0;
int ret = 0;
- int i = 0;
+ word32 i = 0;
WOLFSSL_ENTER("BuildCertificateStatus");
@@ -23588,93 +25196,98 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
default:
return 0;
}
+#ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ headerSz = idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
+ sendSz = idx + length;
- sendSz = idx + length;
+ } else
+#endif
+ sendSz = (int)(idx + length);
if (ssl->keys.encryptionOn)
sendSz += MAX_MSG_EXTRA;
- /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
- * is not advanced yet */
- ssl->options.buildingMsg = 1;
-
- if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) {
- output = GetOutputBuffer(ssl);
-
- AddHeaders(output, length, certificate_status, ssl);
-
- output[idx++] = type;
+ output =(byte*)XMALLOC(sendSz, ssl->heap, DYNAMIC_TYPE_OCSP);
+ if (output == NULL)
+ return MEMORY_E;
- if (type == WOLFSSL_CSR2_OCSP_MULTI) {
- c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx);
- idx += OPAQUE24_LEN;
- }
+ AddHeaders(output, length, certificate_status, ssl);
- for (i = 0; i < count; i++) {
- c32to24(status[i].length, output + idx);
- idx += OPAQUE24_LEN;
+ output[idx++] = type;
- XMEMCPY(output + idx, status[i].buffer, status[i].length);
- idx += status[i].length;
- }
+ if (type == WOLFSSL_CSR2_OCSP_MULTI) {
+ c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx);
+ idx += OPAQUE24_LEN;
+ }
- if (IsEncryptionOn(ssl, 1)) {
- byte* input;
- int inputSz = idx; /* build msg adds rec hdr */
- int recordHeaderSz = RECORD_HEADER_SZ;
+ for (i = 0; i < count; i++) {
+ c32to24(status[i].length, output + idx);
+ idx += OPAQUE24_LEN;
- if (ssl->options.dtls)
- recordHeaderSz += DTLS_RECORD_EXTRA;
- inputSz -= recordHeaderSz;
- input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- if (input == NULL)
- return MEMORY_E;
+ XMEMCPY(output + idx, status[i].buffer, status[i].length);
+ idx += status[i].length;
+ }
+ /* Send Message. Handled message fragmentation in the function if needed */
+ ret = SendHandshakeMsg(ssl, output, (sendSz - headerSz), certificate_status,
+ "Certificate Status");
+ XFREE(output, ssl->heap, DYNAMIC_TYPE_OCSP);
- XMEMCPY(input, output + recordHeaderSz, inputSz);
- #ifdef WOLFSSL_DTLS
- ret = DtlsMsgPoolSave(ssl, input, inputSz, certificate_status);
- #endif
- if (ret == 0)
- sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
- handshake, 1, 0, 0, CUR_ORDER);
- XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ WOLFSSL_LEAVE("BuildCertificateStatus", ret);
+ return ret;
+}
+#endif
- if (sendSz < 0)
- ret = sendSz;
- }
- else {
- #ifdef WOLFSSL_DTLS
- if (ret == 0 && IsDtlsNotSctpMode(ssl))
- ret = DtlsMsgPoolSave(ssl, output, sendSz, certificate_status);
- if (ret == 0 && ssl->options.dtls)
- DtlsSEQIncrement(ssl, CUR_ORDER);
- #endif
- ret = HashOutput(ssl, output, sendSz, 0);
- }
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+ defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+static int BuildCertificateStatusWithStatusCB(WOLFSSL* ssl, byte status_type)
+{
+ WOLFSSL_OCSP *ocsp;
+ int ret = 0;
- #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
- if (ret == 0 && ssl->hsInfoOn)
- AddPacketName(ssl, "CertificateStatus");
- if (ret == 0 && ssl->toInfoOn) {
- ret = AddPacketInfo(ssl, "CertificateStatus", handshake, output,
- sendSz, WRITE_PROTO, 0, ssl->heap);
- if (ret != 0)
- return ret;
- }
- #endif
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+ if (status_type != WOLFSSL_CSR2_OCSP &&
+ status_type != WOLFSSL_CSR2_OCSP_MULTI)
+ return 0;
- if (ret == 0) {
- ssl->options.buildingMsg = 0;
- ssl->buffers.outputBuffer.length += sendSz;
- if (!ssl->options.groupMessages)
- ret = SendBuffered(ssl);
+ ocsp = SSL_CM(ssl)->ocsp_stapling;
+ if (ocsp == NULL || ocsp->statusCb == NULL)
+ return BAD_FUNC_ARG;
+ WOLFSSL_MSG("Calling ocsp->statusCb");
+ ret = ocsp->statusCb(ssl, ocsp->statusCbArg);
+ switch (ret) {
+ case WOLFSSL_OCSP_STATUS_CB_OK: {
+ word32 cnt = 1;
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ if (status_type == WOLFSSL_CSR2_OCSP_MULTI) {
+ /* Find last response set */
+ for (cnt = XELEM_CNT(ssl->ocspCsrResp);
+ cnt > 0 && ssl->ocspCsrResp[cnt-1].buffer == NULL;
+ cnt--);
+ cnt = MIN(cnt, (word32)ssl->buffers.certChainCnt + 1);
+ }
+#endif
+ ret = BuildCertificateStatus(ssl, status_type, ssl->ocspCsrResp,
+ cnt);
+ break;
}
+ case WOLFSSL_OCSP_STATUS_CB_NOACK:
+ /* No OCSP response to send */
+ ret = 0;
+ break;
+ case WOLFSSL_OCSP_STATUS_CB_ALERT_FATAL:
+ /* fall through */
+ default:
+ ret = WOLFSSL_FATAL_ERROR;
+ break;
}
- WOLFSSL_LEAVE("BuildCertificateStatus", ret);
return ret;
}
-#endif
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST ||
+ * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+
#endif /* NO_WOLFSSL_SERVER */
/* handle generation of certificate_status (22) */
@@ -23686,7 +25299,10 @@ int SendCertificateStatus(WOLFSSL* ssl)
WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_SEND);
WOLFSSL_ENTER("SendCertificateStatus");
- (void) ssl;
+ if (ssl == NULL || SSL_CM(ssl) == NULL) {
+ WOLFSSL_MSG("SendCertificateStatus bad args");
+ return BAD_FUNC_ARG;
+ }
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
status_type = ssl->status_request;
@@ -23696,6 +25312,14 @@ int SendCertificateStatus(WOLFSSL* ssl)
status_type = status_type ? status_type : ssl->status_request_v2;
#endif
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+ defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ if (SSL_CM(ssl)->ocsp_stapling != NULL &&
+ SSL_CM(ssl)->ocsp_stapling->statusCb != NULL) {
+ return BuildCertificateStatusWithStatusCB(ssl, status_type);
+ }
+#endif
+
switch (status_type) {
#ifndef NO_WOLFSSL_SERVER
@@ -23722,7 +25346,8 @@ int SendCertificateStatus(WOLFSSL* ssl)
}
/* Let's not error out the connection if we can't verify our cert */
- if (ret == ASN_SELF_SIGNED_E || ret == ASN_NO_SIGNER_E)
+ if (ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E) ||
+ ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E))
ret = 0;
if (response.buffer) {
@@ -23740,7 +25365,8 @@ int SendCertificateStatus(WOLFSSL* ssl)
{
OcspRequest* request = ssl->ctx->certOcspRequest;
buffer responses[1 + MAX_CHAIN_DEPTH];
- int i = 0;
+ byte ctxOwnsRequest = 0;
+ word32 i = 0;
XMEMSET(responses, 0, sizeof(responses));
@@ -23758,36 +25384,26 @@ int SendCertificateStatus(WOLFSSL* ssl)
|| ssl->buffers.weOwnCertChain)) {
buffer der;
word32 idx = 0;
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert;
- #else
- DecodedCert cert[1];
- #endif
+ WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
DerBuffer* chain;
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_E;
- #endif
+ WC_ALLOC_VAR_EX(cert, DecodedCert, 1, ssl->heap,
+ DYNAMIC_TYPE_DCERT, return MEMORY_E);
request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap,
DYNAMIC_TYPE_OCSP_REQUEST);
if (request == NULL) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
- #endif
+ WC_FREE_VAR_EX(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
return MEMORY_E;
}
- /* use certChain if available, otherwise use peer certificate */
+ /* use certChain if available, otherwise use certificate */
chain = ssl->buffers.certChain;
if (chain == NULL) {
chain = ssl->buffers.certificate;
}
if (chain && chain->buffer) {
- while (idx + OPAQUE24_LEN < chain->length) {
+ while (ret == 0 && idx + OPAQUE24_LEN < chain->length) {
c24to32(chain->buffer + idx, &der.length);
idx += OPAQUE24_LEN;
@@ -23796,32 +25412,30 @@ int SendCertificateStatus(WOLFSSL* ssl)
if (idx > chain->length)
break;
-
ret = CreateOcspRequest(ssl, request, cert, der.buffer,
- der.length);
+ der.length, &ctxOwnsRequest);
if (ret == 0) {
request->ssl = ssl;
- ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling,
+ ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling,
request, &responses[i + 1], ssl->heap);
/* Suppressing, not critical */
- if (ret == OCSP_CERT_REVOKED ||
- ret == OCSP_CERT_UNKNOWN ||
- ret == OCSP_LOOKUP_FAIL) {
+ if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED) ||
+ ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN) ||
+ ret == WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL)) {
ret = 0;
}
i++;
- FreeOcspRequest(request);
+ if (!ctxOwnsRequest)
+ FreeOcspRequest(request);
}
}
}
-
- XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
- #endif
+ if (!ctxOwnsRequest)
+ XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ WC_FREE_VAR_EX(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
}
else {
while (ret == 0 &&
@@ -23831,9 +25445,9 @@ int SendCertificateStatus(WOLFSSL* ssl)
request, &responses[++i], ssl->heap);
/* Suppressing, not critical */
- if (ret == OCSP_CERT_REVOKED ||
- ret == OCSP_CERT_UNKNOWN ||
- ret == OCSP_LOOKUP_FAIL) {
+ if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED) ||
+ ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN) ||
+ ret == WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL)) {
ret = 0;
}
}
@@ -23842,7 +25456,7 @@ int SendCertificateStatus(WOLFSSL* ssl)
if (responses[0].buffer) {
if (ret == 0) {
ret = BuildCertificateStatus(ssl, status_type, responses,
- (byte)i + 1);
+ i + 1);
}
for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) {
@@ -23854,7 +25468,8 @@ int SendCertificateStatus(WOLFSSL* ssl)
}
/* Let's not error out the connection if we can't verify our cert */
- if (ret == ASN_SELF_SIGNED_E || ret == ASN_NO_SIGNER_E)
+ if (ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E) ||
+ ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E))
ret = 0;
break;
@@ -23968,7 +25583,8 @@ static int ModifyForMTU(WOLFSSL* ssl, int buffSz, int outputSz, int mtuSz)
}
#endif /* WOLFSSL_DTLS */
-#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS)
+#if !defined(NO_TLS) && defined(WOLFSSL_TLS13) && \
+ !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS)
/*
* Enforce limits specified in
* https://www.rfc-editor.org/rfc/rfc8446#section-5.5
@@ -24044,6 +25660,52 @@ static int CheckTLS13AEADSendLimit(WOLFSSL* ssl)
}
#endif /* WOLFSSL_TLS13 && !WOLFSSL_TLS13_IGNORE_AEAD_LIMITS */
+#ifdef WOLFSSL_THREADED_CRYPT
+int SendAsyncData(WOLFSSL* ssl)
+{
+ int i;
+
+ for (i = 0; i < WOLFSSL_THREADED_CRYPT_CNT; i++) {
+ ThreadCrypt* encrypt = &ssl->buffers.encrypt[i];
+
+ if (encrypt->done) {
+ int error;
+
+ GrowOutputBuffer(ssl, encrypt->buffer.length);
+ XMEMCPY(ssl->buffers.outputBuffer.buffer, encrypt->buffer.buffer,
+ encrypt->buffer.length);
+ ssl->buffers.outputBuffer.length = encrypt->buffer.length;
+ ssl->buffers.outputBuffer.idx = 0;
+ encrypt->done = 0;
+ encrypt->avail = 1;
+ if ((error = SendBuffered(ssl)) < 0) {
+ ssl->error = error;
+ WOLFSSL_ERROR(ssl->error);
+ /* store for next call if WANT_WRITE or user embedSend() that
+ doesn't present like WANT_WRITE */
+ ssl->buffers.plainSz = encrypt->buffer.length;
+ ssl->buffers.prevSent = encrypt->buffer.length;
+ if (ssl->error == WC_NO_ERR_TRACE(SOCKET_ERROR_E) &&
+ (ssl->options.connReset || ssl->options.isClosed)) {
+ return SOCKET_PEER_CLOSED_E; /* peer reset or closed */
+ }
+ return ssl->error;
+ }
+
+ /* only one message per attempt */
+ if (ssl->options.partialWrite == 1) {
+ WOLFSSL_MSG("Partial Write on, only sending one record");
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
+
+#ifndef NO_TLS
+
/**
* ssl_in_handshake():
* Invoked in wolfSSL_read/wolfSSL_write to check if wolfSSL_negotiate() is
@@ -24054,10 +25716,12 @@ static int CheckTLS13AEADSendLimit(WOLFSSL* ssl)
* 2 in SCR and we have plain data ready
* Early data logic may bypass this logic in TLSv1.3 when appropriate.
*/
-static int ssl_in_handshake(WOLFSSL *ssl, int send)
+static int ssl_in_handshake(WOLFSSL *ssl, int sending_data)
{
+int SendAsyncData = 1;
+(void)SendAsyncData;
if (IsSCR(ssl)) {
- if (send) {
+ if (sending_data) {
/* allow sending data in SCR */
return 0;
} else {
@@ -24090,25 +25754,33 @@ static int ssl_in_handshake(WOLFSSL *ssl, int send)
return 0;
}
-int SendData(WOLFSSL* ssl, const void* data, int sz)
+int SendData(WOLFSSL* ssl, const void* data, size_t sz)
{
- int sent = 0, /* plainText size */
- sendSz,
+ word32 sent = 0; /* plainText size */
+ int sendSz,
ret;
#if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_EARLY_DATA_GROUP)
int groupMsgs = 0;
#endif
+ int error = ssl->error;
- if (ssl->error == WANT_WRITE
+ if (sz > INT_MAX) {
+ WOLFSSL_MSG("SendData sz overflow");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
+ if (error == WC_NO_ERR_TRACE(WANT_WRITE)
#ifdef WOLFSSL_ASYNC_CRYPT
- || ssl->error == WC_PENDING_E
+ || error == WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
) {
+ error = 0;
ssl->error = 0;
}
/* don't allow write after decrypt or mac error */
- if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR) {
+ if (error == WC_NO_ERR_TRACE(VERIFY_MAC_ERROR) ||
+ error == WC_NO_ERR_TRACE(DECRYPT_ERROR)) {
/* For DTLS allow these possible errors and allow the session
to continue despite them */
if (ssl->options.dtls) {
@@ -24133,28 +25805,51 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
groupMsgs = 1;
#endif
}
- else if (IsAtLeastTLSv1_3(ssl->version) &&
+ else
+#endif
+ if (IsAtLeastTLSv1_3(ssl->version) &&
ssl->options.side == WOLFSSL_SERVER_END &&
ssl->options.acceptState >= TLS13_ACCEPT_FINISHED_SENT) {
/* We can send data without waiting on peer finished msg */
WOLFSSL_MSG("server sending data before receiving client finished");
}
- else
-#endif
- if (ssl_in_handshake(ssl, 1)) {
+ else if (ssl_in_handshake(ssl, 1)) {
int err;
WOLFSSL_MSG("handshake not complete, trying to finish");
if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
#ifdef WOLFSSL_ASYNC_CRYPT
/* if async would block return WANT_WRITE */
- if (ssl->error == WC_PENDING_E) {
+ if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return WOLFSSL_CBIO_ERR_WANT_WRITE;
}
#endif
- return err;
+ return err;
}
}
+#ifdef WOLFSSL_RW_THREADED
+#ifdef WOLFSSL_DTLS13
+ if (ssl->options.dtls) {
+ /* Dtls13DoScheduledWork(ssl) may return WANT_WRITE */
+ if ((error = Dtls13DoScheduledWork(ssl)) < 0) {
+ ssl->error = error;
+ WOLFSSL_ERROR(error);
+ return error;
+ }
+ }
+#endif /* WOLFSSL_DTLS13 */
+#ifdef WOLFSSL_TLS13
+ if (ssl->options.sendKeyUpdate) {
+ ssl->options.sendKeyUpdate = 0;
+ ret = SendTls13KeyUpdate(ssl);
+ if (ret != 0) {
+ ssl->error = BUILD_MSG_ERROR;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+#endif
+#endif
+
/* last time system socket output buffer was full, try again to send */
if (ssl->buffers.outputBuffer.length > 0
#if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_EARLY_DATA_GROUP)
@@ -24162,24 +25857,25 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
#endif
) {
WOLFSSL_MSG("output buffer was full, trying to send again");
- if ( (ssl->error = SendBuffered(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset ||
- ssl->options.isClosed)) {
- ssl->error = SOCKET_PEER_CLOSED_E;
- WOLFSSL_ERROR(ssl->error);
+ if ( (error = SendBuffered(ssl)) < 0) {
+ WOLFSSL_ERROR(error);
+ if (error == WC_NO_ERR_TRACE(SOCKET_ERROR_E) &&
+ (ssl->options.connReset || ssl->options.isClosed)) {
+ error = SOCKET_PEER_CLOSED_E;
+ ssl->error = error;
+ WOLFSSL_ERROR(error);
return 0; /* peer reset or closed */
}
- return ssl->error;
+ return (ssl->error = error);
}
else {
/* advance sent to previous sent + plain size just sent */
sent = ssl->buffers.prevSent + ssl->buffers.plainSz;
WOLFSSL_MSG("sent write buffered data");
- if (sent > sz) {
+ if (sent > (word32)sz) {
WOLFSSL_MSG("error: write() after WANT_WRITE with short size");
- return ssl->error = BAD_FUNC_ARG;
+ return (ssl->error = BAD_FUNC_ARG);
}
}
}
@@ -24190,6 +25886,19 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
return WOLFSSL_FATAL_ERROR;
}
+#ifdef WOLFSSL_THREADED_CRYPT
+ ret = SendAsyncData(ssl);
+ if (ret != 0) {
+ ssl->error = ret;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ if (ssl->dtls13WaitKeyUpdateAck) {
+ ret = DoDtls13KeyUpdateAck(ssl);
+ if (ret != 0)
+ return ret;
+ }
+#endif
+
for (;;) {
byte* out;
byte* sendBuffer = (byte*)data + sent; /* may switch on comp */
@@ -24198,6 +25907,10 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
#ifdef HAVE_LIBZ
byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
#endif
+#ifdef WOLFSSL_THREADED_CRYPT
+ int i;
+ ThreadCrypt* encrypt = NULL;
+#endif
#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS)
if (IsAtLeastTLSv1_3(ssl->version)) {
@@ -24247,36 +25960,59 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
}
#endif /* WOLFSSL_DTLS13 */
-#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- buffSz = wolfSSL_GetMaxFragSize(ssl, sz - sent);
- }
- else
-#endif
- {
- buffSz = wolfSSL_GetMaxFragSize(ssl, sz - sent);
-
- }
+ buffSz = wolfSSL_GetMaxFragSize(ssl, (word32)sz - sent);
- if (sent == sz) break;
+ if (sent == (word32)sz) break;
#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_DTLS_SIZE_CHECK)
- if (ssl->options.dtls && (buffSz < sz - sent)) {
- ssl->error = DTLS_SIZE_ERROR;
- WOLFSSL_ERROR(ssl->error);
- return ssl->error;
+ if (ssl->options.dtls && ((size_t)buffSz < (word32)sz - sent)) {
+ error = DTLS_SIZE_ERROR;
+ ssl->error = error;
+ WOLFSSL_ERROR(error);
+ return error;
}
#endif
outputSz = buffSz + COMP_EXTRA + DTLS_RECORD_HEADER_SZ;
if (IsEncryptionOn(ssl, 1) || ssl->options.tls1_3)
outputSz += cipherExtraData(ssl);
+#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
+ if (ssl->options.dtls) {
+ byte cidSz = 0;
+ if ((cidSz = DtlsGetCidTxSize(ssl)) > 0)
+ outputSz += cidSz + 1; /* +1 for inner content type */
+ }
+#endif
+
/* check for available size */
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
- return ssl->error = ret;
+ return (ssl->error = ret);
/* get output buffer */
+#ifndef WOLFSSL_THREADED_CRYPT
out = GetOutputBuffer(ssl);
+#else
+ do {
+ for (i = 0; i < WOLFSSL_THREADED_CRYPT_CNT; i++) {
+ if (ssl->buffers.encrypt[i].avail) {
+ encrypt = &ssl->buffers.encrypt[i];
+ break;
+ }
+ }
+ if (encrypt == NULL) {
+ ret = SendAsyncData(ssl);
+ if (ret != 0) {
+ ssl->error = ret;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+ }
+ while (encrypt == NULL);
+ encrypt->done = 0;
+ encrypt->avail = 0;
+ GrowAnOutputBuffer(ssl, &encrypt->buffer, outputSz);
+ out = encrypt->buffer.buffer;
+#endif
#ifdef HAVE_LIBZ
if (ssl->options.usingCompression) {
@@ -24311,7 +26047,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
}
if (sendSz < 0) {
#ifdef WOLFSSL_ASYNC_CRYPT
- if (sendSz == WC_PENDING_E)
+ if (sendSz == WC_NO_ERR_TRACE(WC_PENDING_E))
ssl->error = sendSz;
#endif
return BUILD_MSG_ERROR;
@@ -24320,21 +26056,73 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
#ifdef WOLFSSL_ASYNC_CRYPT
FreeAsyncCtx(ssl, 0);
#endif
- ssl->buffers.outputBuffer.length += sendSz;
+#ifdef WOLFSSL_THREADED_CRYPT
+ if (!encrypt->init) {
+ SetKeys(&encrypt->encrypt, NULL, &ssl->keys, &ssl->specs,
+ ssl->options.side, ssl->heap, ssl->devId, ssl->rng,
+ ssl->options.tls1_3);
+ encrypt->init = 1;
+ }
+ encrypt->buffer.length = sendSz;
+ encrypt->offset = RECORD_HEADER_SZ;
+ if (ssl->options.dtls) {
+ encrypt->offset += DTLS_RECORD_EXTRA;
+ }
+ encrypt->cryptLen = outputSz - encrypt->offset;
+ #ifdef HAVE_TRUNCATED_HMAC
+ if (ssl->truncated_hmac) {
+ encrypt->cryptLen -= min(TRUNCATED_HMAC_SZ, ssl->specs.hash_size);
+ }
+ else
+ #endif
+ {
+ encrypt->cryptLen -= ssl->specs.hash_size;
+ }
+
+#if !defined(NO_PUBLIC_GCM_SET_IV) && \
+ ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \
+ (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)))
+ XMEMCPY(encrypt->nonce, ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ);
+ XMEMCPY(encrypt->nonce + AESGCM_IMP_IV_SZ, ssl->keys.aead_exp_IV,
+ AESGCM_EXP_IV_SZ);
+#endif
+ XMEMSET(encrypt->additional, 0, AEAD_AUTH_DATA_SZ);
+ WriteSEQ(ssl, CUR_ORDER, encrypt->additional);
+ XMEMCPY(encrypt->additional + AEAD_TYPE_OFFSET, encrypt->buffer.buffer,
+ 3);
+ c16toa(sendSz - encrypt->offset - AESGCM_EXP_IV_SZ -
+ ssl->specs.aead_mac_size, encrypt->additional + AEAD_LEN_OFFSET);
+
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+ #endif
+
+ if (encrypt->signal != NULL) {
+ encrypt->signal(encrypt->signalCtx, ssl);
+ }
+ return sendSz;
+#else
+ ssl->buffers.outputBuffer.length += (word32)sendSz;
- if ( (ssl->error = SendBuffered(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
+ if ( (error = SendBuffered(ssl)) < 0) {
+ ssl->error = error;
+ WOLFSSL_ERROR(error);
/* store for next call if WANT_WRITE or user embedSend() that
doesn't present like WANT_WRITE */
ssl->buffers.plainSz = buffSz;
ssl->buffers.prevSent = sent;
- if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset ||
- ssl->options.isClosed)) {
+ if (error == WC_NO_ERR_TRACE(SOCKET_ERROR_E) &&
+ (ssl->options.connReset || ssl->options.isClosed)) {
+ error = SOCKET_PEER_CLOSED_E;
ssl->error = SOCKET_PEER_CLOSED_E;
- WOLFSSL_ERROR(ssl->error);
+ WOLFSSL_ERROR(error);
return 0; /* peer reset or closed */
}
- return ssl->error;
+ return error;
+ }
+ else {
+ ssl->error = 0; /* Clear any previous errors */
}
sent += buffSz;
@@ -24344,20 +26132,29 @@ int SendData(WOLFSSL* ssl, const void* data, int sz)
WOLFSSL_MSG("Partial Write on, only sending one record");
break;
}
+#endif
}
return sent;
}
/* process input data */
-int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
+int ReceiveData(WOLFSSL* ssl, byte* output, size_t sz, int peek)
{
int size;
+ int error = ssl->error;
WOLFSSL_ENTER("ReceiveData");
+ if (sz > INT_MAX) {
+ WOLFSSL_MSG("ReceiveData sz overflow");
+ return WOLFSSL_FATAL_ERROR;
+ }
+
/* reset error state */
- if (ssl->error == WANT_READ || ssl->error == WOLFSSL_ERROR_WANT_READ) {
+ if (error == WC_NO_ERR_TRACE(WANT_READ) ||
+ error == WOLFSSL_ERROR_WANT_READ) {
+ error = 0;
ssl->error = 0;
}
@@ -24365,25 +26162,26 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
if (ssl->options.dtls) {
/* In DTLS mode, we forgive some errors and allow the session
* to continue despite them. */
- if (ssl->error == VERIFY_MAC_ERROR ||
- ssl->error == DECRYPT_ERROR ||
- ssl->error == DTLS_SIZE_ERROR) {
+ if (error == WC_NO_ERR_TRACE(VERIFY_MAC_ERROR) ||
+ error == WC_NO_ERR_TRACE(DECRYPT_ERROR) ||
+ error == WC_NO_ERR_TRACE(DTLS_SIZE_ERROR)) {
+ error = 0;
ssl->error = 0;
}
}
#endif /* WOLFSSL_DTLS */
- if (ssl->error != 0 && ssl->error != WANT_WRITE
+ if (error != 0 && error != WC_NO_ERR_TRACE(WANT_WRITE)
#ifdef WOLFSSL_ASYNC_CRYPT
- && ssl->error != WC_PENDING_E
+ && error != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
#if defined(HAVE_SECURE_RENEGOTIATION) || defined(WOLFSSL_DTLS13)
- && ssl->error != APP_DATA_READY
+ && error != WC_NO_ERR_TRACE(APP_DATA_READY)
#endif
) {
WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed");
- return ssl->error;
+ return error;
}
#ifdef WOLFSSL_EARLY_DATA
@@ -24399,7 +26197,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
#ifdef WOLFSSL_ASYNC_CRYPT
/* if async would block return WANT_WRITE */
- if (ssl->error == WC_PENDING_E) {
+ if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return WOLFSSL_CBIO_ERR_WANT_READ;
}
#endif
@@ -24421,32 +26219,39 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
#endif
while (ssl->buffers.clearOutputBuffer.length == 0) {
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- if (ssl->error == ZERO_RETURN) {
+ if ( (error = ProcessReply(ssl)) < 0) {
+ if (error == WC_NO_ERR_TRACE(ZERO_RETURN)) {
+ ssl->error = error;
WOLFSSL_MSG("Zero return, no more data coming");
return 0; /* no more data coming */
}
- if (ssl->error == SOCKET_ERROR_E) {
+ if (error == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) {
if (ssl->options.connReset || ssl->options.isClosed) {
WOLFSSL_MSG("Peer reset or closed, connection done");
- ssl->error = SOCKET_PEER_CLOSED_E;
- WOLFSSL_ERROR(ssl->error);
+ error = SOCKET_PEER_CLOSED_E;
+ ssl->error = error;
+ WOLFSSL_ERROR(error);
return 0; /* peer reset or closed */
}
}
- WOLFSSL_ERROR(ssl->error);
- return ssl->error;
+ ssl->error = error;
+ WOLFSSL_ERROR(error);
+ return error;
}
-#ifdef WOLFSSL_DTLS13
+#ifndef WOLFSSL_RW_THREADED
+ #ifdef WOLFSSL_DTLS13
if (ssl->options.dtls) {
/* Dtls13DoScheduledWork(ssl) may return WANT_WRITE */
- if ((ssl->error = Dtls13DoScheduledWork(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return ssl->error;
+ if ((error = Dtls13DoScheduledWork(ssl)) < 0) {
+ ssl->error = error;
+ WOLFSSL_ERROR(error);
+ return error;
}
}
-#endif /* WOLFSSL_DTLS13 */
+ #endif /* WOLFSSL_DTLS13 */
+#endif
+
#ifdef HAVE_SECURE_RENEGOTIATION
if (ssl->secure_renegotiation &&
ssl->secure_renegotiation->startScr) {
@@ -24462,7 +26267,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) {
#ifdef WOLFSSL_ASYNC_CRYPT
/* if async would block return WANT_WRITE */
- if (ssl->error == WC_PENDING_E) {
+ if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return WOLFSSL_CBIO_ERR_WANT_READ;
}
#endif
@@ -24495,12 +26300,13 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek)
#endif
}
- size = min(sz, (int)ssl->buffers.clearOutputBuffer.length);
+ size = (sz < (size_t)ssl->buffers.clearOutputBuffer.length) ?
+ (int)sz : (int)ssl->buffers.clearOutputBuffer.length;
- XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size);
+ XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, (size_t)(size));
if (peek == 0) {
- ssl->buffers.clearOutputBuffer.length -= size;
+ ssl->buffers.clearOutputBuffer.length -= (word32)size;
ssl->buffers.clearOutputBuffer.buffer += size;
}
@@ -24519,10 +26325,19 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type)
int ret;
int outputSz;
int dtlsExtra = 0;
+ const char* alert_str = NULL;
WOLFSSL_ENTER("SendAlert");
- WOLFSSL_MSG_EX("SendAlert: %d %s", type, AlertTypeToString(type));
+ alert_str = AlertTypeToString(type);
+ if (alert_str != NULL)
+ {
+ WOLFSSL_MSG_EX("SendAlert: %d %s", type, alert_str);
+ }
+ else
+ {
+ WOLFSSL_MSG_EX("SendAlert: %d", type);
+ }
#ifdef WOLFSSL_QUIC
if (WOLFSSL_IS_QUIC(ssl)) {
@@ -24559,7 +26374,7 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type)
#ifdef OPENSSL_EXTRA
if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_CB_ALERT, type);
+ ssl->CBIS(ssl, WOLFSSL_CB_ALERT, type);
}
#endif
#ifdef WOLFSSL_DTLS
@@ -24574,7 +26389,7 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type)
/* If CheckAvailableSize returned WANT_WRITE due to a blocking write
* then discard pending output and just send the alert. */
if (ssl->options.dtls) {
- if (ret != WANT_WRITE || severity != alert_fatal)
+ if (ret != WC_NO_ERR_TRACE(WANT_WRITE) || severity != alert_fatal)
return ret;
ShrinkOutputBuffer(ssl);
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) {
@@ -24637,6 +26452,11 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type)
#endif /* WOLFSSL_DTLS13 */
{
AddRecordHeader(output, ALERT_SIZE, alert, ssl, CUR_ORDER);
+#ifdef WOLFSSL_DTLS
+ /* AddRecordHeader doesn't increment the seq number */
+ if (ssl->options.dtls)
+ DtlsSEQIncrement(ssl, CUR_ORDER);
+#endif
}
output += RECORD_HEADER_SZ;
@@ -24666,7 +26486,7 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type)
}
#endif
- ssl->buffers.outputBuffer.length += sendSz;
+ ssl->buffers.outputBuffer.length += (word32)sendSz;
ret = SendBuffered(ssl);
@@ -24678,8 +26498,11 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type)
return ret;
}
+#endif /* !NO_TLS */
+
int RetrySendAlert(WOLFSSL* ssl)
{
+ int ret = 0;
int type;
int severity;
WOLFSSL_ENTER("RetrySendAlert");
@@ -24697,12 +26520,18 @@ int RetrySendAlert(WOLFSSL* ssl)
ssl->pendingAlert.code = 0;
ssl->pendingAlert.level = alert_none;
- return SendAlert_ex(ssl, severity, type);
+#ifndef NO_TLS
+ ret = SendAlert_ex(ssl, severity, type);
+#else
+ (void)type;
+#endif
+ return ret;
}
/* send alert message */
int SendAlert(WOLFSSL* ssl, int severity, int type)
{
+ int ret = 0;
WOLFSSL_ENTER("SendAlert");
if (ssl == NULL) {
@@ -24710,7 +26539,7 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
}
if (ssl->pendingAlert.level != alert_none) {
- int ret = RetrySendAlert(ssl);
+ ret = RetrySendAlert(ssl);
if (ret != 0) {
if (ssl->pendingAlert.level == alert_none ||
(ssl->pendingAlert.level != alert_fatal &&
@@ -24723,10 +26552,17 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
return ret;
}
}
-
- return SendAlert_ex(ssl, severity, type);
+#ifndef NO_TLS
+ ret = SendAlert_ex(ssl, severity, type);
+#endif /* !NO_TLS */
+ return ret;
}
+
+#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES_H
+#include
+#endif
+
const char* wolfSSL_ERR_reason_error_string(unsigned long e)
{
#ifdef NO_ERROR_STRINGS
@@ -24744,16 +26580,21 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
}
/* pass to wolfCrypt */
- if (error < MAX_CODE_E && error > MIN_CODE_E) {
+ if ((error <= WC_SPAN1_FIRST_E && error >= WC_SPAN1_MIN_CODE_E) ||
+ (error <= WC_SPAN2_FIRST_E && error >= WC_SPAN2_MIN_CODE_E))
+ {
return wc_GetErrorString(error);
}
- switch (error) {
-
+ if (error == 0) {
#ifdef OPENSSL_EXTRA
- case 0 :
return "ok";
+#else
+ return "unknown error number";
#endif
+ }
+
+ switch ((enum wolfSSL_ErrorCodes)error) { /* // NOLINT(clang-analyzer-optin.core.EnumCastOutOfRange) */
case UNSUPPORTED_SUITE :
return "unsupported cipher suite";
@@ -24840,7 +26681,7 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
return "peer ip address mismatch";
case WANT_READ :
- case -WOLFSSL_ERROR_WANT_READ :
+ case WOLFSSL_ERROR_WANT_READ_E :
return "non-blocking socket wants data to be read";
case NOT_READY_ERROR :
@@ -24850,22 +26691,19 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
return "record layer version error";
case WANT_WRITE :
- case -WOLFSSL_ERROR_WANT_WRITE :
+ case WOLFSSL_ERROR_WANT_WRITE_E :
return "non-blocking socket write buffer full";
- case -WOLFSSL_ERROR_WANT_CONNECT:
- case -WOLFSSL_ERROR_WANT_ACCEPT:
+ case WOLFSSL_ERROR_WANT_CONNECT_E :
+ case WOLFSSL_ERROR_WANT_ACCEPT_E :
return "The underlying BIO was not yet connected";
- case -WOLFSSL_ERROR_SYSCALL:
+ case WOLFSSL_ERROR_SYSCALL_E :
return "fatal I/O error in TLS layer";
- case -WOLFSSL_ERROR_WANT_X509_LOOKUP:
+ case WOLFSSL_ERROR_WANT_X509_LOOKUP_E :
return "application client cert callback asked to be called again";
- case -WOLFSSL_ERROR_SSL:
- return "fatal TLS protocol error";
-
case BUFFER_ERROR :
return "malformed buffer input error";
@@ -24903,7 +26741,7 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
return "can't decode peer key";
case ZERO_RETURN:
- case -WOLFSSL_ERROR_ZERO_RETURN:
+ case WOLFSSL_ERROR_ZERO_RETURN_E :
return "peer sent close notify alert";
case ECC_CURVETYPE_ERROR:
@@ -24943,6 +26781,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case CRL_MISSING:
return "CRL missing, not loaded";
+ case CRYPTO_POLICY_FORBIDDEN:
+ return "Operation forbidden by system crypto-policy";
+
case MONITOR_SETUP_E:
return "CRL monitor setup error";
@@ -24961,6 +26802,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case MAX_CHAIN_ERROR:
return "Maximum Chain Depth Exceeded";
+ case MAX_CERT_EXTENSIONS_ERR:
+ return "Maximum Cert Extension Exceeded";
+
case COOKIE_ERROR:
return "DTLS Cookie Error";
@@ -25021,6 +26865,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case SESSION_TICKET_EXPECT_E:
return "Session Ticket Error";
+ case SCR_DIFFERENT_CERT_E:
+ return "SCR Different cert error";
+
case SESSION_SECRET_CB_E:
return "Session Secret Callback Error";
@@ -25186,85 +27033,168 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case UNSUPPORTED_CERTIFICATE:
return "Unsupported certificate type";
-#ifdef HAVE_HTTP_CLIENT
case HTTP_TIMEOUT:
return "HTTP timeout for OCSP or CRL req";
+
case HTTP_RECV_ERR:
return "HTTP Receive error";
+
case HTTP_HEADER_ERR:
return "HTTP Header error";
+
case HTTP_PROTO_ERR:
return "HTTP Protocol error";
+
case HTTP_STATUS_ERR:
return "HTTP Status error";
+
case HTTP_VERSION_ERR:
return "HTTP Version error";
+
case HTTP_APPSTR_ERR:
return "HTTP Application string error";
-#endif
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
+
+ case UNSUPPORTED_PROTO_VERSION:
+ #ifdef OPENSSL_EXTRA
+ return "WRONG_SSL_VERSION";
+ #else
+ return "bad/unsupported protocol version";
+ #endif
+
+ case FALCON_KEY_SIZE_E:
+ return "Wrong key size for Falcon.";
+
+ case DILITHIUM_KEY_SIZE_E:
+ return "Wrong key size for Dilithium.";
+
+ case QUIC_TP_MISSING_E:
+ return "QUIC transport parameter not set";
+
+ case QUIC_WRONG_ENC_LEVEL:
+ return "QUIC data received at wrong encryption level";
+
+ case DTLS_CID_ERROR:
+ return "DTLS ConnectionID mismatch or missing";
+
+ case DTLS_TOO_MANY_FRAGMENTS_E:
+ return "Received too many fragmented messages from peer error";
+
+ case DUPLICATE_TLS_EXT_E:
+ return "Duplicate TLS extension in message.";
+
+ case WOLFSSL_ALPN_NOT_FOUND:
+ return "TLS extension not found";
+
+ case WOLFSSL_BAD_CERTTYPE:
+ return "Certificate type not supported";
+
+ case WOLFSSL_BAD_STAT:
+ return "bad status";
+
+ case WOLFSSL_BAD_PATH:
+ return "No certificates found at designated path";
+
+ case WOLFSSL_BAD_FILETYPE:
+ return "Data format not supported";
+
+ case WOLFSSL_BAD_FILE:
+ return "Input/output error on file";
+
+ case WOLFSSL_NOT_IMPLEMENTED:
+ return "Function not implemented";
+
+ case WOLFSSL_UNKNOWN:
+ return "Unknown algorithm (EVP)";
+
+ case WOLFSSL_FATAL_ERROR:
+ return "fatal error";
+
+ case WOLFSSL_PEM_R_NO_START_LINE_E:
+ return "No more matching objects found (PEM)";
+
+ case WOLFSSL_PEM_R_PROBLEMS_GETTING_PASSWORD_E:
+ return "Error getting password (PEM)";
+
+ case WOLFSSL_PEM_R_BAD_PASSWORD_READ_E:
+ return "Bad password (PEM)";
+
+ case WOLFSSL_PEM_R_BAD_DECRYPT_E :
+ return "Decryption failed (PEM)";
+
+ case WOLFSSL_ASN1_R_HEADER_TOO_LONG_E:
+ return "ASN header too long (compat)";
+
+ case WOLFSSL_EVP_R_BAD_DECRYPT_E :
+ return "Decryption failed (EVP)";
+
+ case WOLFSSL_EVP_R_BN_DECODE_ERROR:
+ return "Bignum decode error (EVP)";
+
+ case WOLFSSL_EVP_R_DECODE_ERROR :
+ return "Decode error (EVP)";
+
+ case WOLFSSL_EVP_R_PRIVATE_KEY_DECODE_ERROR:
+ return "Private key decode error (EVP)";
+ }
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+ defined(HAVE_WEBSERVER) || defined(HAVE_MEMCACHED)
+
+ switch (error) {
/* TODO: -WOLFSSL_X509_V_ERR_CERT_SIGNATURE_FAILURE. Conflicts with
- * -WOLFSSL_ERROR_WANT_CONNECT. */
+ * -WOLFSSL_ERROR_WANT_CONNECT.
+ */
+
case -WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID:
return "certificate not yet valid";
+
case -WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED:
return "certificate has expired";
+
case -WOLFSSL_X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
return "certificate signature failure";
+
case -WOLFSSL_X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
return "format error in certificate's notAfter field";
+
case -WOLFSSL_X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
return "self-signed certificate in certificate chain";
+
case -WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
return "unable to get local issuer certificate";
+
case -WOLFSSL_X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
return "unable to verify the first certificate";
+
case -WOLFSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG:
return "certificate chain too long";
+
case -WOLFSSL_X509_V_ERR_CERT_REVOKED:
return "certificate revoked";
+
case -WOLFSSL_X509_V_ERR_INVALID_CA:
return "invalid CA certificate";
+
case -WOLFSSL_X509_V_ERR_PATH_LENGTH_EXCEEDED:
return "path length constraint exceeded";
+
case -WOLFSSL_X509_V_ERR_CERT_REJECTED:
return "certificate rejected";
+
case -WOLFSSL_X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
return "subject issuer mismatch";
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER */
- case UNSUPPORTED_PROTO_VERSION:
- #ifdef OPENSSL_EXTRA
- return "WRONG_SSL_VERSION";
- #else
- return "bad/unsupported protocol version";
- #endif
-
- case FALCON_KEY_SIZE_E:
- return "Wrong key size for Falcon.";
- case DILITHIUM_KEY_SIZE_E:
- return "Wrong key size for Dilithium.";
-
-#ifdef WOLFSSL_QUIC
- case QUIC_TP_MISSING_E:
- return "QUIC transport parameter not set";
- case QUIC_WRONG_ENC_LEVEL:
- return "QUIC data received at wrong encryption level";
-#endif
- case DTLS_CID_ERROR:
- return "DTLS ConnectionID mismatch or missing";
- case DTLS_TOO_MANY_FRAGMENTS_E:
- return "Received too many fragmented messages from peer error";
-
- case DUPLICATE_TLS_EXT_E:
- return "Duplicate TLS extension in message.";
-
- default :
- return "unknown error number";
}
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER || HAVE_MEMCACHED */
+
+ return "unknown error number";
#endif /* NO_ERROR_STRINGS */
}
+#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES
+#include
+#endif
+
const char* wolfSSL_ERR_func_error_string(unsigned long e)
{
(void)e;
@@ -25289,9 +27219,9 @@ const char* wolfSSL_ERR_lib_error_string(unsigned long e)
#if defined(OPENSSL_EXTRA)
libe = wolfSSL_ERR_GET_LIB(e);
switch (libe) {
- case ERR_LIB_PEM:
+ case WOLFSSL_ERR_LIB_PEM:
return "wolfSSL PEM routines";
- case ERR_LIB_EVP:
+ case WOLFSSL_ERR_LIB_EVP:
return "wolfSSL digital envelope routines";
default:
return "";
@@ -25303,7 +27233,7 @@ const char* wolfSSL_ERR_lib_error_string(unsigned long e)
void SetErrorString(int error, char* str)
{
- XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ);
+ XSTRNCPY(str, wolfSSL_ERR_reason_error_string((unsigned long)error), WOLFSSL_MAX_ERROR_SZ);
str[WOLFSSL_MAX_ERROR_SZ-1] = 0;
}
@@ -25333,7 +27263,7 @@ void SetErrorString(int error, char* str)
*/
#ifndef NO_ERROR_STRINGS
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \
+ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_QT) || \
defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)
#define SUITE_INFO(x,y,z,w,v,u) {(x),(y),(z),(w),(v),(u),WOLFSSL_CIPHER_SUITE_FLAG_NONE}
#define SUITE_ALIAS(x,z,w,v,u) {(x),"",(z),(w),(v),(u),WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS},
@@ -25342,7 +27272,7 @@ void SetErrorString(int error, char* str)
#define SUITE_ALIAS(x,z,w,v,u) {(x),"",(z),(w),WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS},
#endif
#else
- #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \
+ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_QT) || \
defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)
#define SUITE_INFO(x,y,z,w,v,u) {(x),(z),(w),(v),(u),WOLFSSL_CIPHER_SUITE_FLAG_NONE}
#define SUITE_ALIAS(x,z,w,v,u) {(x),(z),(w),(v),(u),WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS},
@@ -25353,6 +27283,7 @@ void SetErrorString(int error, char* str)
#endif
#endif /* NO_CIPHER_SUITE_ALIASES */
+#ifndef NO_TLS
static const CipherSuiteInfo cipher_names[] =
{
@@ -25832,6 +27763,14 @@ static const CipherSuiteInfo cipher_names[] =
#endif /* WOLFSSL_NO_TLS12 */
};
+#else /* NO_TLS */
+
+static const CipherSuiteInfo cipher_names[] =
+{
+ SUITE_INFO("NO-TLS","NO-TLS", 0, 0, 0, 0),
+};
+
+#endif /* NO_TLS */
/* returns the cipher_names array */
const CipherSuiteInfo* GetCipherNames(void)
@@ -25843,7 +27782,11 @@ const CipherSuiteInfo* GetCipherNames(void)
/* returns the number of elements in the cipher_names array */
int GetCipherNamesSize(void)
{
+#ifdef NO_TLS
+ return 0;
+#else
return (int)(sizeof(cipher_names) / sizeof(CipherSuiteInfo));
+#endif
}
@@ -26136,7 +28079,7 @@ const char* GetCipherMacStr(char n[][MAX_SEGMENT_SZ]) {
/* Returns the number of bits based on the cipher enc string, or 0 on failure */
int SetCipherBits(const char* enc) {
- int ret = WOLFSSL_FAILURE;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
if ((XSTRCMP(enc,"AESGCM(256)") == 0) ||
(XSTRCMP(enc,"AES(256)") == 0) ||
@@ -26204,13 +28147,16 @@ const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl)
}
int GetCipherSuiteFromName(const char* name, byte* cipherSuite0,
- byte* cipherSuite, int* flags)
+ byte* cipherSuite, byte* major, byte* minor, int* flags)
{
- int ret = BAD_FUNC_ARG;
+ int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
int i;
unsigned long len;
const char* nameDelim;
+ (void)major;
+ (void)minor;
+
/* Support trailing : */
nameDelim = XSTRSTR(name, ":");
if (nameDelim)
@@ -26228,9 +28174,19 @@ int GetCipherSuiteFromName(const char* name, byte* cipherSuite0,
#endif
if (found) {
- *cipherSuite0 = cipher_names[i].cipherSuite0;
- *cipherSuite = cipher_names[i].cipherSuite;
- *flags = cipher_names[i].flags;
+ if (cipherSuite0 != NULL)
+ *cipherSuite0 = cipher_names[i].cipherSuite0;
+ if (cipherSuite != NULL)
+ *cipherSuite = cipher_names[i].cipherSuite;
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_QT) || \
+ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)
+ if (major != NULL)
+ *major = cipher_names[i].major;
+ if (minor != NULL)
+ *minor = cipher_names[i].minor;
+#endif
+ if (flags != NULL)
+ *flags = cipher_names[i].flags;
ret = 0;
break;
}
@@ -26268,6 +28224,9 @@ static int ParseCipherList(Suites* suites,
word16 haveNull = 1; /* allowed by default if compiled in */
int callInitSuites = 0;
word16 havePSK = 0;
+ word16 haveAES128 = 1; /* allowed by default if compiled in */
+ word16 haveSHA1 = 1; /* allowed by default if compiled in */
+ word16 haveRC4 = 1; /* allowed by default if compiled in */
#endif
const int suiteSz = GetCipherNamesSize();
const char* next = list;
@@ -26277,8 +28236,11 @@ static int ParseCipherList(Suites* suites,
return 0;
}
- if (next[0] == 0 || XSTRCMP(next, "ALL") == 0 ||
- XSTRCMP(next, "DEFAULT") == 0 || XSTRCMP(next, "HIGH") == 0) {
+ if (next[0] == '\0' ||
+ XSTRCMP(next, "ALL") == 0 ||
+ XSTRCMP(next, "DEFAULT") == 0 ||
+ XSTRCMP(next, "HIGH") == 0)
+ {
/* Add all ciphersuites except anonymous and null ciphers. Prefer RSA */
#ifndef NO_RSA
haveRSA = 1;
@@ -26289,8 +28251,9 @@ static int ParseCipherList(Suites* suites,
#else
0,
#endif
- haveRSA, 1, 1, !haveRSA, 1, haveRSA, !haveRSA, 1, 1, 0, 0,
- side);
+ haveRSA, 1, 1, !haveRSA, 1, haveRSA, !haveRSA, 0, 0, 1,
+ 1, 1, side
+ );
return 1; /* wolfSSL default */
}
@@ -26310,6 +28273,9 @@ static int ParseCipherList(Suites* suites,
if (length > currLen) {
length = currLen;
}
+ if (currLen == 0)
+ break;
+ ++next; /* increment to skip ':' */
}
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
@@ -26340,7 +28306,7 @@ static int ParseCipherList(Suites* suites,
substrCurrent[length] = '\0';
}
else {
- length = (int)XSTRLEN(substrCurrent);
+ length = (word32)XSTRLEN(substrCurrent);
}
/* check if is a public key type */
@@ -26488,6 +28454,29 @@ static int ParseCipherList(Suites* suites,
continue;
}
+ #if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (XSTRCMP(name, "AES128") == 0) {
+ haveAES128 = allowing;
+ callInitSuites = 1;
+ ret = 1;
+ continue;
+ }
+
+ if (XSTRCMP(name, "SHA1") == 0) {
+ haveSHA1 = allowing;
+ callInitSuites = 1;
+ ret = 1;
+ continue;
+ }
+
+ if (XSTRCMP(name, "RC4") == 0) {
+ haveRC4 = allowing;
+ callInitSuites = 1;
+ ret = 1;
+ continue;
+ }
+ #endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
if (XSTRCMP(name, "LOW") == 0 || XSTRCMP(name, "MEDIUM") == 0) {
/* No way to limit or allow low bit sizes */
if (allowing) {
@@ -26509,6 +28498,14 @@ static int ParseCipherList(Suites* suites,
/* wolfSSL doesn't support "export" ciphers. We can skip this */
continue;
}
+
+ #if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (XSTRNCMP(name, WOLFSSL_SECLEVEL_STR,
+ strlen(WOLFSSL_SECLEVEL_STR)) == 0) {
+ /* Skip the "@SECLEVEL=N" string, we'll process it elsewhere. */
+ continue;
+ }
+ #endif /* WOLFSSL_SYS_CRYPTO_POLICY */
#endif /* OPENSSL_EXTRA */
for (i = 0; i < suiteSz; i++) {
@@ -26563,14 +28560,12 @@ static int ParseCipherList(Suites* suites,
defined(HAVE_ED448)
haveSig |= SIG_ECDSA;
#endif
- #if defined(HAVE_PQC)
#ifdef HAVE_FALCON
haveSig |= SIG_FALCON;
#endif /* HAVE_FALCON */
#ifdef HAVE_DILITHIUM
haveSig |= SIG_DILITHIUM;
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
}
else
#ifdef BUILD_TLS_SM4_GCM_SM3
@@ -26632,8 +28627,7 @@ static int ParseCipherList(Suites* suites,
break;
}
}
- }
- while (next++); /* ++ needed to skip ':' */
+ } while (next);
if (ret) {
int keySz = 0;
@@ -26650,10 +28644,9 @@ static int ParseCipherList(Suites* suites,
(word16)((haveSig & SIG_ECDSA) != 0),
(word16)haveECC, (word16)haveStaticRSA,
(word16)haveStaticECC,
- (word16)((haveSig & SIG_FALCON) != 0),
- (word16)((haveSig & SIG_DILITHIUM) != 0),
(word16)((haveSig & SIG_ANON) != 0),
- (word16)haveNull, side);
+ (word16)haveNull, (word16)haveAES128,
+ (word16)haveSHA1, (word16)haveRC4, side);
/* Restore user ciphers ahead of defaults */
XMEMMOVE(suites->suites + idx, suites->suites,
min(suites->suiteSz, WOLFSSL_MAX_SUITE_SZ-idx));
@@ -26663,8 +28656,8 @@ static int ParseCipherList(Suites* suites,
#endif
{
suites->suiteSz = (word16)idx;
- InitSuitesHashSigAlgo_ex2(suites->hashSigAlgo, haveSig, 1, keySz,
- &suites->hashSigAlgoSz);
+ InitSuitesHashSigAlgo(suites->hashSigAlgo, haveSig, 1, keySz,
+ &suites->hashSigAlgoSz);
}
#ifdef HAVE_RENEGOTIATION_INDICATION
@@ -26682,7 +28675,9 @@ static int ParseCipherList(Suites* suites,
suites->setSuites = 1;
}
+#ifdef NO_CERTS
(void)privateKeySz;
+#endif
return ret;
}
@@ -26800,14 +28795,12 @@ int SetCipherListFromBytes(WOLFSSL_CTX* ctx, Suites* suites, const byte* list,
#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
haveECDSAsig = 1;
#endif
- #if defined(HAVE_PQC)
#ifdef HAVE_FALCON
haveFalconSig = 1;
#endif /* HAVE_FALCON */
#ifdef HAVE_DILITHIUM
haveDilithiumSig = 1;
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
}
else
#endif /* WOLFSSL_TLS13 */
@@ -26847,7 +28840,7 @@ int SetCipherListFromBytes(WOLFSSL_CTX* ctx, Suites* suites, const byte* list,
haveSig |= haveFalconSig ? SIG_FALCON : 0;
haveSig |= haveDilithiumSig ? SIG_DILITHIUM : 0;
haveSig |= haveAnon ? SIG_ANON : 0;
- InitSuitesHashSigAlgo_ex2(suites->hashSigAlgo, haveSig, 1, keySz,
+ InitSuitesHashSigAlgo(suites->hashSigAlgo, haveSig, 1, keySz,
&suites->hashSigAlgoSz);
#ifdef HAVE_RENEGOTIATION_INDICATION
if (ctx->method->side == WOLFSSL_CLIENT_END) {
@@ -26868,7 +28861,7 @@ int SetCipherListFromBytes(WOLFSSL_CTX* ctx, Suites* suites, const byte* list,
return ret;
}
-#endif /* OPENSSL_EXTRA */
+#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */
#ifdef OPENSSL_EXTRA
@@ -26982,10 +28975,6 @@ int SetSuitesHashSigAlgo(Suites* suites, const char* list)
do {
if (*list == '+') {
- if (mac_alg != 0) {
- ret = 0;
- break;
- }
sig_alg = GetSigAlgFromName(s, (int)(list - s));
if (sig_alg == 0) {
ret = 0;
@@ -27048,7 +29037,6 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo)
return sigAlgo == ed448_sa_algo;
}
#endif
-#ifdef HAVE_PQC
#ifdef HAVE_FALCON
if (ssl->pkCurveOID == CTC_FALCON_LEVEL1) {
/* Certificate has Falcon level 1 key, only match with Falcon level 1
@@ -27062,6 +29050,7 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo)
}
#endif /* HAVE_FALCON */
#ifdef HAVE_DILITHIUM
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
if (ssl->pkCurveOID == CTC_DILITHIUM_LEVEL2) {
/* Certificate has Dilithium level 2 key, only match with it. */
return sigAlgo == dilithium_level2_sa_algo;
@@ -27074,8 +29063,20 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo)
/* Certificate has Dilithium level 5 key, only match with it. */
return sigAlgo == dilithium_level5_sa_algo;
}
+ #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
+ if (ssl->pkCurveOID == CTC_ML_DSA_LEVEL2) {
+ /* Certificate has ML-DSA level 2 key, only match with it. */
+ return sigAlgo == dilithium_level2_sa_algo;
+ }
+ if (ssl->pkCurveOID == CTC_ML_DSA_LEVEL3) {
+ /* Certificate has ML-DSA level 3 key, only match with it. */
+ return sigAlgo == dilithium_level3_sa_algo;
+ }
+ if (ssl->pkCurveOID == CTC_ML_DSA_LEVEL5) {
+ /* Certificate has ML-DSA level 5 key, only match with it. */
+ return sigAlgo == dilithium_level5_sa_algo;
+ }
#endif /* HAVE_DILITHIUM */
-#endif /* HAVE_PQC */
#ifdef WC_RSA_PSS
/* RSA certificate and PSS sig alg. */
if (ssl->options.sigAlgo == rsa_sa_algo) {
@@ -27093,13 +29094,13 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo)
return sigAlgo == ssl->options.sigAlgo;
}
-#if defined(HAVE_ECC) && defined(WOLFSSL_TLS13) || \
- defined(USE_ECDSA_KEYSZ_HASH_ALGO)
+#if defined(HAVE_ECC) && \
+ (defined(WOLFSSL_TLS13) || defined(USE_ECDSA_KEYSZ_HASH_ALGO))
static int CmpEccStrength(int hashAlgo, int curveSz)
{
int dgstSz = GetMacDigestSize((byte)hashAlgo);
if (dgstSz <= 0)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
return dgstSz - (curveSz & (~0x3));
}
#endif
@@ -27126,10 +29127,43 @@ static byte MinHashAlgo(WOLFSSL* ssl)
return sha_mac;
}
-int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz)
+/* Check if a given peer hashSigAlgo is supported in our ssl->suites or
+ * ssl->ctx->suites.
+ *
+ * Returns 1 on match.
+ * Returns 0 otherwise.
+ * */
+static int SupportedHashSigAlgo(WOLFSSL* ssl, const byte * hashSigAlgo)
+{
+ const Suites * suites = NULL;
+ word32 i = 0;
+
+ if (ssl == NULL || hashSigAlgo == NULL) {
+ return 0;
+ }
+
+ suites = WOLFSSL_SUITES(ssl);
+
+ if (suites == NULL || suites->hashSigAlgoSz == 0) {
+ return 0;
+ }
+
+ for (i = 0; (i+1) < suites->hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) {
+ if (XMEMCMP(&suites->hashSigAlgo[i], hashSigAlgo,
+ HELLO_EXT_SIGALGO_SZ) == 0) {
+ /* Match found. */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz,
+ int matchSuites)
{
word32 i;
- int ret = MATCH_SUITE_ERROR;
+ int ret = WC_NO_ERR_TRACE(MATCH_SUITE_ERROR);
byte minHash;
/* set defaults */
@@ -27167,6 +29201,14 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz)
if (!MatchSigAlgo(ssl, sigAlgo))
continue;
+ if (matchSuites) {
+ /* Keep looking if peer algorithm isn't supported in our ssl->suites
+ * or ssl->ctx->suites. */
+ if (!SupportedHashSigAlgo(ssl, &hashSigAlgo[i])) {
+ continue;
+ }
+ }
+
#ifdef HAVE_ED25519
if (ssl->pkCurveOID == ECC_ED25519_OID) {
/* Matched Ed25519 - set chosen and finished. */
@@ -27185,7 +29227,6 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz)
break;
}
#endif
- #if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
if (ssl->pkCurveOID == CTC_FALCON_LEVEL1 ||
ssl->pkCurveOID == CTC_FALCON_LEVEL5 ) {
@@ -27197,17 +29238,22 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz)
}
#endif /* HAVE_FALCON */
#if defined(HAVE_DILITHIUM)
- if (ssl->pkCurveOID == CTC_DILITHIUM_LEVEL2 ||
- ssl->pkCurveOID == CTC_DILITHIUM_LEVEL3 ||
- ssl->pkCurveOID == CTC_DILITHIUM_LEVEL5) {
- /* Matched Dilithium - set chosen and finished. */
+ if (ssl->pkCurveOID == CTC_ML_DSA_LEVEL2 ||
+ ssl->pkCurveOID == CTC_ML_DSA_LEVEL3 ||
+ ssl->pkCurveOID == CTC_ML_DSA_LEVEL5
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ || ssl->pkCurveOID == CTC_DILITHIUM_LEVEL2
+ || ssl->pkCurveOID == CTC_DILITHIUM_LEVEL3
+ || ssl->pkCurveOID == CTC_DILITHIUM_LEVEL5
+ #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
+ ) {
+ /* Matched ML-DSA or Dilithium - set chosen and finished. */
ssl->options.sigAlgo = sigAlgo;
ssl->options.hashAlgo = hashAlgo;
ret = 0;
break;
}
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
#if defined(WOLFSSL_ECDSA_MATCH_HASH) && defined(USE_ECDSA_KEYSZ_HASH_ALGO)
#error "WOLFSSL_ECDSA_MATCH_HASH and USE_ECDSA_KEYSZ_HASH_ALGO cannot "
@@ -27547,7 +29593,7 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz)
return 0;
}
-#endif /* WOLFSSL_CALLBACKS */
+#endif /* WOLFSSL_CALLBACKS || OPENSSL_EXTRA */
#if !defined(NO_CERTS)
@@ -27568,7 +29614,7 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz)
int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType,
int label, int id, void* heap, int devId)
{
- int ret = NOT_COMPILED_IN;
+ int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
if (hsType == DYNAMIC_TYPE_RSA) {
#ifndef NO_RSA
@@ -27583,7 +29629,7 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType,
ret = wc_InitRsaKey_Label(rsaKey, (char*)data, heap, devId);
}
else if (id) {
- ret = wc_InitRsaKey_Id(rsaKey, data, length, heap, devId);
+ ret = wc_InitRsaKey_Id(rsaKey, data, (int)length, heap, devId);
}
if (ret == 0) {
*pkey = (void*)rsaKey;
@@ -27606,7 +29652,7 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType,
ret = wc_ecc_init_label(ecKey, (char*)data, heap, devId);
}
else if (id) {
- ret = wc_ecc_init_id(ecKey, data, length, heap, devId);
+ ret = wc_ecc_init_id(ecKey, data, (int)length, heap, devId);
}
if (ret == 0) {
*pkey = (void*)ecKey;
@@ -27617,7 +29663,7 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType,
#endif
}
else if (hsType == DYNAMIC_TYPE_DILITHIUM) {
-#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
+#if defined(HAVE_DILITHIUM)
dilithium_key* dilithiumKey;
dilithiumKey = (dilithium_key*)XMALLOC(sizeof(dilithium_key), heap,
@@ -27642,7 +29688,7 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType,
#endif
}
else if (hsType == DYNAMIC_TYPE_FALCON) {
-#if defined(HAVE_PQC) && defined(HAVE_FALCON)
+#if defined(HAVE_FALCON)
falcon_key* falconKey;
falconKey = (falcon_key*)XMALLOC(sizeof(falcon_key), heap,
@@ -27680,9 +29726,9 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType,
* length The length of a signature.
* returns 0 on success, otherwise failure.
*/
-int DecodePrivateKey(WOLFSSL *ssl, word16* length)
+int DecodePrivateKey(WOLFSSL *ssl, word32* length)
{
- int ret = BAD_FUNC_ARG;
+ int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
int keySz;
word32 idx;
@@ -27695,7 +29741,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
|| wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)
#endif
) {
- *length = (word16)GetPrivateKeySigSize(ssl);
+ *length = (word32)GetPrivateKeySigSize(ssl);
return 0;
}
else
@@ -27713,11 +29759,14 @@ 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);
+ ret = AllocKey(ssl, (int)(ssl->hsType), &ssl->hsKey);
if (ret != 0) {
goto exit_dpk;
}
@@ -27731,9 +29780,10 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
else if (ssl->buffers.keyId) {
ret = wc_InitRsaKey_Id((RsaKey*)ssl->hsKey,
- ssl->buffers.key->buffer,
- ssl->buffers.key->length, ssl->heap,
- ssl->buffers.keyDevId);
+ (ssl->buffers.key->buffer),
+ (int)(ssl->buffers.key->length),
+ ssl->heap,
+ ssl->buffers.keyDevId);
}
if (ret == 0) {
if (ssl->buffers.keySz < ssl->options.minRsaKeySz) {
@@ -27742,7 +29792,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
/* Return the maximum signature length. */
- *length = (word16)ssl->buffers.keySz;
+ *length = (word32)ssl->buffers.keySz;
}
#else
ret = NOT_COMPILED_IN;
@@ -27757,7 +29807,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
else if (ssl->buffers.keyId) {
ret = wc_ecc_init_id((ecc_key*)ssl->hsKey,
- ssl->buffers.key->buffer,
+ (ssl->buffers.key->buffer),
ssl->buffers.key->length, ssl->heap,
ssl->buffers.keyDevId);
}
@@ -27768,14 +29818,15 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
/* Return the maximum signature length. */
- *length = (word16)wc_ecc_sig_size_calc(ssl->buffers.keySz);
+ *length = (word32)wc_ecc_sig_size_calc(ssl->buffers.keySz);
}
#else
ret = NOT_COMPILED_IN;
#endif
}
- else if (ssl->buffers.keyType == falcon_level5_sa_algo) {
- #if defined(HAVE_PQC) && defined(HAVE_FALCON)
+ else if ((ssl->buffers.keyType == falcon_level1_sa_algo) ||
+ (ssl->buffers.keyType == falcon_level5_sa_algo)) {
+ #if defined(HAVE_FALCON)
if (ssl->buffers.keyLabel) {
ret = wc_falcon_init_label((falcon_key*)ssl->hsKey,
(char*)ssl->buffers.key->buffer,
@@ -27787,6 +29838,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");
@@ -27794,14 +29853,16 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
/* Return the maximum signature length. */
- *length = (word16)wc_falcon_sig_size((falcon_key*)ssl->hsKey);
+ *length = wc_falcon_sig_size((falcon_key*)ssl->hsKey);
}
#else
ret = NOT_COMPILED_IN;
#endif
}
- else if (ssl->buffers.keyType == dilithium_level5_sa_algo) {
- #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
+ else if ((ssl->buffers.keyType == dilithium_level2_sa_algo) ||
+ (ssl->buffers.keyType == dilithium_level3_sa_algo) ||
+ (ssl->buffers.keyType == dilithium_level5_sa_algo)) {
+ #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN)
if (ssl->buffers.keyLabel) {
ret = wc_dilithium_init_label((dilithium_key*)ssl->hsKey,
(char*)ssl->buffers.key->buffer,
@@ -27813,6 +29874,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, WC_ML_DSA_44);
+ }
+ else if (ssl->buffers.keyType == dilithium_level3_sa_algo) {
+ ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, WC_ML_DSA_65);
+ }
+ else if (ssl->buffers.keyType == dilithium_level5_sa_algo) {
+ ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, WC_ML_DSA_87);
+ }
+ }
if (ret == 0) {
if (ssl->buffers.keySz < ssl->options.minDilithiumKeySz) {
WOLFSSL_MSG("Dilithium key size too small");
@@ -27820,7 +29892,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
@@ -27834,7 +29906,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
#ifndef NO_RSA
if (ssl->buffers.keyType == rsa_sa_algo || ssl->buffers.keyType == 0) {
ssl->hsType = DYNAMIC_TYPE_RSA;
- ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ ret = AllocKey(ssl, (int)ssl->hsType, &ssl->hsKey);
if (ret != 0) {
goto exit_dpk;
}
@@ -27874,7 +29946,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
/* Return the maximum signature length. */
- *length = (word16)keySz;
+ *length = (word32)keySz;
goto exit_dpk;
}
@@ -27883,7 +29955,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
#ifdef HAVE_ECC
#ifndef NO_RSA
- FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
+ FreeKey(ssl, (int)ssl->hsType, (void**)&ssl->hsKey);
#endif /* !NO_RSA */
if (ssl->buffers.keyType == ecc_dsa_sa_algo || ssl->buffers.keyType == 0
@@ -27892,7 +29964,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
#endif
) {
ssl->hsType = DYNAMIC_TYPE_ECC;
- ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ ret = AllocKey(ssl, (int)ssl->hsType, &ssl->hsKey);
if (ret != 0) {
goto exit_dpk;
}
@@ -27922,6 +29994,12 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
(ecc_key*)ssl->hsKey,
ssl->buffers.key->length);
}
+ #endif
+ #ifdef WOLFSSL_SM2
+ if ((ret == 0) && (ssl->buffers.keyType == sm2_sa_algo)) {
+ ret = wc_ecc_set_curve((ecc_key*)ssl->hsKey,
+ WOLFSSL_SM2_KEY_BITS / 8, ECC_SM2P256V1);
+ }
#endif
if (ret == 0) {
WOLFSSL_MSG("Using ECC private key");
@@ -27934,7 +30012,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
/* Return the maximum signature length. */
- *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsKey);
+ *length = (word32)wc_ecc_sig_size((ecc_key*)ssl->hsKey);
goto exit_dpk;
}
@@ -28054,7 +30132,6 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
}
#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */
-#if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
#if !defined(NO_RSA) || defined(HAVE_ECC)
FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
@@ -28108,19 +30185,21 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
WOLFSSL_MSG("Using Falcon private key");
/* Check it meets the minimum Falcon key size requirements. */
- if (FALCON_MAX_KEY_SIZE < ssl->options.minFalconKeySz) {
+ keySz = wc_falcon_size((falcon_key*)ssl->hsKey);
+ if (keySz < ssl->options.minFalconKeySz) {
WOLFSSL_MSG("Falcon key size too small");
ERROR_OUT(FALCON_KEY_SIZE_E, exit_dpk);
}
/* Return the maximum signature length. */
- *length = FALCON_MAX_SIG_SIZE;
+ *length = wc_falcon_sig_size((falcon_key*)ssl->hsKey);
goto exit_dpk;
}
}
#endif /* HAVE_FALCON */
-#if defined(HAVE_DILITHIUM)
+#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \
+ !defined(WOLFSSL_DILITHIUM_NO_ASN1)
#if !defined(NO_RSA) || defined(HAVE_ECC)
FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
#endif
@@ -28137,13 +30216,13 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
if (ssl->buffers.keyType == dilithium_level2_sa_algo) {
- ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, 2);
+ ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, WC_ML_DSA_44);
}
else if (ssl->buffers.keyType == dilithium_level3_sa_algo) {
- ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, 3);
+ ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, WC_ML_DSA_65);
}
else if (ssl->buffers.keyType == dilithium_level5_sa_algo) {
- ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, 5);
+ ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, WC_ML_DSA_87);
}
else {
/* What if ssl->buffers.keyType is 0? We might want to do something
@@ -28172,26 +30251,27 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
/* Set start of data to beginning of buffer. */
idx = 0;
/* Decode the key assuming it is a Dilithium private key. */
- ret = wc_dilithium_import_private_only(ssl->buffers.key->buffer,
- ssl->buffers.key->length,
- (dilithium_key*)ssl->hsKey);
+ ret = wc_Dilithium_PrivateKeyDecode(ssl->buffers.key->buffer,
+ &idx,
+ (dilithium_key*)ssl->hsKey,
+ ssl->buffers.key->length);
if (ret == 0) {
WOLFSSL_MSG("Using Dilithium private key");
/* Check it meets the minimum Dilithium key size requirements. */
- if (DILITHIUM_MAX_KEY_SIZE < ssl->options.minDilithiumKeySz) {
+ keySz = wc_dilithium_size((dilithium_key*)ssl->hsKey);
+ if (keySz < ssl->options.minDilithiumKeySz) {
WOLFSSL_MSG("Dilithium key size too small");
ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dpk);
}
/* Return the maximum signature length. */
- *length = DILITHIUM_MAX_SIG_SIZE;
+ *length = wc_dilithium_sig_size((dilithium_key*)ssl->hsKey);
goto exit_dpk;
}
}
#endif /* HAVE_DILITHIUM */
-#endif /* HAVE_PQC */
(void)idx;
(void)keySz;
@@ -28205,12 +30285,15 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
return ret;
}
-#if defined(HAVE_PQC) && defined(WOLFSSL_DUAL_ALG_CERTS)
-/* This is just like the above, but only consider Falcon and Dilthium and
- * only for the alternative key; not the native key. */
-int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
+#if defined(WOLFSSL_DUAL_ALG_CERTS)
+/* This is just like the above, but only consider RSA, ECC, Falcon and
+ * Dilthium; Furthermore, use the alternative key, not the native key.
+ */
+int DecodeAltPrivateKey(WOLFSSL *ssl, word32* length)
{
- int ret = BAD_FUNC_ARG;
+ int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
+ int keySz;
+ word32 idx;
/* make sure alt private key exists */
if (ssl->buffers.altKey == NULL || ssl->buffers.altKey->buffer == NULL) {
@@ -28218,8 +30301,282 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
ERROR_OUT(NO_PRIVATE_KEY, exit_dapk);
}
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_blind_toggle(ssl->buffers.altKey, ssl->buffers.altKeyMask);
+#endif
+
+#ifdef WOLF_PRIVATE_KEY_ID
+ if (ssl->buffers.altKeyDevId != INVALID_DEVID &&
+ (ssl->buffers.altKeyId || ssl->buffers.altKeyLabel)) {
+ if (ssl->buffers.altKeyType == rsa_sa_algo)
+ ssl->hsAltType = DYNAMIC_TYPE_RSA;
+ else if (ssl->buffers.altKeyType == ecc_dsa_sa_algo)
+ ssl->hsAltType = DYNAMIC_TYPE_ECC;
+ else if ((ssl->buffers.altKeyType == falcon_level1_sa_algo) ||
+ (ssl->buffers.altKeyType == falcon_level5_sa_algo))
+ ssl->hsAltType = DYNAMIC_TYPE_FALCON;
+ else if ((ssl->buffers.altKeyType == dilithium_level2_sa_algo) ||
+ (ssl->buffers.altKeyType == dilithium_level3_sa_algo) ||
+ (ssl->buffers.altKeyType == dilithium_level5_sa_algo))
+ ssl->hsAltType = DYNAMIC_TYPE_DILITHIUM;
+ ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
+ if (ret != 0) {
+ goto exit_dapk;
+ }
+
+ if (ssl->buffers.altKeyType == rsa_sa_algo) {
+ #ifndef NO_RSA
+ if (ssl->buffers.altKeyLabel) {
+ ret = wc_InitRsaKey_Label((RsaKey*)ssl->hsAltKey,
+ (char*)ssl->buffers.altKey->buffer,
+ ssl->heap, ssl->buffers.altKeyDevId);
+ }
+ else if (ssl->buffers.altKeyId) {
+ ret = wc_InitRsaKey_Id((RsaKey*)ssl->hsAltKey,
+ ssl->buffers.altKey->buffer,
+ ssl->buffers.altKey->length, ssl->heap,
+ ssl->buffers.altKeyDevId);
+ }
+ if (ret == 0) {
+ if (ssl->buffers.altKeySz < ssl->options.minRsaKeySz) {
+ WOLFSSL_MSG("RSA key size too small");
+ ERROR_OUT(RSA_KEY_SIZE_E, exit_dapk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = ssl->buffers.altKeySz;
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+ else if (ssl->buffers.altKeyType == ecc_dsa_sa_algo) {
+ #ifdef HAVE_ECC
+ if (ssl->buffers.altKeyLabel) {
+ ret = wc_ecc_init_label((ecc_key*)ssl->hsAltKey,
+ (char*)ssl->buffers.altKey->buffer,
+ ssl->heap, ssl->buffers.altKeyDevId);
+ }
+ else if (ssl->buffers.altKeyId) {
+ ret = wc_ecc_init_id((ecc_key*)ssl->hsAltKey,
+ ssl->buffers.altKey->buffer,
+ ssl->buffers.altKey->length, ssl->heap,
+ ssl->buffers.altKeyDevId);
+ }
+ if (ret == 0) {
+ if (ssl->buffers.altKeySz < ssl->options.minEccKeySz) {
+ WOLFSSL_MSG("ECC key size too small");
+ ERROR_OUT(ECC_KEY_SIZE_E, exit_dapk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = wc_ecc_sig_size_calc(ssl->buffers.altKeySz);
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+ else if ((ssl->buffers.altKeyType == falcon_level1_sa_algo) ||
+ (ssl->buffers.altKeyType == falcon_level5_sa_algo)) {
+ #if defined(HAVE_FALCON)
+ if (ssl->buffers.altKeyLabel) {
+ ret = wc_falcon_init_label((falcon_key*)ssl->hsAltKey,
+ (char*)ssl->buffers.altKey->buffer,
+ ssl->heap, ssl->buffers.altKeyDevId);
+ }
+ else if (ssl->buffers.altKeyId) {
+ ret = wc_falcon_init_id((falcon_key*)ssl->hsAltKey,
+ ssl->buffers.altKey->buffer,
+ ssl->buffers.altKey->length, ssl->heap,
+ ssl->buffers.altKeyDevId);
+ }
+ if (ret == 0) {
+ if (ssl->buffers.altKeyType == falcon_level1_sa_algo) {
+ ret = wc_falcon_set_level((falcon_key*)ssl->hsAltKey, 1);
+ }
+ else if (ssl->buffers.altKeyType == falcon_level5_sa_algo) {
+ ret = wc_falcon_set_level((falcon_key*)ssl->hsAltKey, 5);
+ }
+ }
+ if (ret == 0) {
+ if (ssl->buffers.altKeySz < ssl->options.minFalconKeySz) {
+ WOLFSSL_MSG("Falcon key size too small");
+ ERROR_OUT(FALCON_KEY_SIZE_E, exit_dapk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = wc_falcon_sig_size((falcon_key*)ssl->hsAltKey);
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+ else if ((ssl->buffers.altKeyType == dilithium_level2_sa_algo) ||
+ (ssl->buffers.altKeyType == dilithium_level3_sa_algo) ||
+ (ssl->buffers.altKeyType == dilithium_level5_sa_algo)) {
+ #if defined(HAVE_DILITHIUM)
+ if (ssl->buffers.altKeyLabel) {
+ ret = wc_dilithium_init_label((dilithium_key*)ssl->hsAltKey,
+ (char*)ssl->buffers.altKey->buffer,
+ ssl->heap, ssl->buffers.altKeyDevId);
+ }
+ else if (ssl->buffers.altKeyId) {
+ ret = wc_dilithium_init_id((dilithium_key*)ssl->hsAltKey,
+ ssl->buffers.altKey->buffer,
+ ssl->buffers.altKey->length, ssl->heap,
+ ssl->buffers.altKeyDevId);
+ }
+ if (ret == 0) {
+ if (ssl->buffers.altKeyType == dilithium_level2_sa_algo) {
+ ret = wc_dilithium_set_level(
+ (dilithium_key*)ssl->hsAltKey, WC_ML_DSA_44);
+ }
+ else if (ssl->buffers.altKeyType == dilithium_level3_sa_algo) {
+ ret = wc_dilithium_set_level(
+ (dilithium_key*)ssl->hsAltKey, WC_ML_DSA_65);
+ }
+ else if (ssl->buffers.altKeyType == dilithium_level5_sa_algo) {
+ ret = wc_dilithium_set_level(
+ (dilithium_key*)ssl->hsAltKey, WC_ML_DSA_87);
+ }
+ }
+ if (ret == 0) {
+ if (ssl->buffers.altKeySz < ssl->options.minDilithiumKeySz) {
+ WOLFSSL_MSG("Dilithium key size too small");
+ ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dapk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = wc_dilithium_sig_size(
+ (dilithium_key*)ssl->hsAltKey);
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+ goto exit_dapk;
+ }
+#endif /* WOLF_PRIVATE_KEY_ID */
+
+#ifndef NO_RSA
+ if (ssl->buffers.altKeyType == rsa_sa_algo ||
+ ssl->buffers.altKeyType == 0) {
+ ssl->hsAltType = DYNAMIC_TYPE_RSA;
+ ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
+ if (ret != 0) {
+ goto exit_dapk;
+ }
+
+ WOLFSSL_MSG("Trying RSA private key");
+
+ /* Set start of data to beginning of buffer. */
+ idx = 0;
+ /* Decode the key assuming it is an RSA private key. */
+ ret = wc_RsaPrivateKeyDecode(ssl->buffers.altKey->buffer, &idx,
+ (RsaKey*)ssl->hsAltKey, ssl->buffers.altKey->length);
+ #ifdef WOLF_PRIVATE_KEY_ID
+ /* if using external key then allow using a public key */
+ if (ret != 0 && (ssl->devId != INVALID_DEVID
+ #ifdef HAVE_PK_CALLBACKS
+ || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)
+ #endif
+ )) {
+ WOLFSSL_MSG("Trying RSA public key with crypto callbacks");
+ idx = 0;
+ ret = wc_RsaPublicKeyDecode(ssl->buffers.altKey->buffer, &idx,
+ (RsaKey*)ssl->hsAltKey, ssl->buffers.altKey->length);
+ }
+ #endif
+ if (ret == 0) {
+ WOLFSSL_MSG("Using RSA private key");
+
+ /* It worked so check it meets minimum key size requirements. */
+ keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsAltKey);
+ if (keySz < 0) { /* check if keySz has error case */
+ ERROR_OUT(keySz, exit_dapk);
+ }
+
+ if (keySz < ssl->options.minRsaKeySz) {
+ WOLFSSL_MSG("RSA key size too small");
+ ERROR_OUT(RSA_KEY_SIZE_E, exit_dapk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = keySz;
+
+ goto exit_dapk;
+ }
+ }
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
+#ifndef NO_RSA
+ FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey);
+#endif /* !NO_RSA */
+
+ if (ssl->buffers.altKeyType == ecc_dsa_sa_algo ||
+ ssl->buffers.altKeyType == 0
+ #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+ || ssl->buffers.altKeyType == sm2_sa_algo
+ #endif
+ ) {
+ ssl->hsAltType = DYNAMIC_TYPE_ECC;
+ ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
+ if (ret != 0) {
+ goto exit_dapk;
+ }
+
+ #ifndef NO_RSA
+ WOLFSSL_MSG("Trying ECC private key, RSA didn't work");
+ #else
+ WOLFSSL_MSG("Trying ECC private key");
+ #endif
+
+ /* Set start of data to beginning of buffer. */
+ idx = 0;
+ /* Decode the key assuming it is an ECC private key. */
+ ret = wc_EccPrivateKeyDecode(ssl->buffers.altKey->buffer, &idx,
+ (ecc_key*)ssl->hsAltKey,
+ ssl->buffers.altKey->length);
+ #ifdef WOLF_PRIVATE_KEY_ID
+ /* if using external key then allow using a public key */
+ if (ret != 0 && (ssl->devId != INVALID_DEVID
+ #ifdef HAVE_PK_CALLBACKS
+ || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)
+ #endif
+ )) {
+ WOLFSSL_MSG("Trying ECC public key with crypto callbacks");
+ idx = 0;
+ ret = wc_EccPublicKeyDecode(ssl->buffers.altKey->buffer, &idx,
+ (ecc_key*)ssl->hsAltKey,
+ ssl->buffers.altKey->length);
+ }
+ #endif
+ if (ret == 0) {
+ WOLFSSL_MSG("Using ECC private key");
+
+ /* Check it meets the minimum ECC key size requirements. */
+ keySz = wc_ecc_size((ecc_key*)ssl->hsAltKey);
+ if (keySz < ssl->options.minEccKeySz) {
+ WOLFSSL_MSG("ECC key size too small");
+ ERROR_OUT(ECC_KEY_SIZE_E, exit_dapk);
+ }
+
+ /* Return the maximum signature length. */
+ *length = wc_ecc_sig_size((ecc_key*)ssl->hsAltKey);
+
+ goto exit_dapk;
+ }
+ }
+#endif
+#if defined(HAVE_FALCON)
+ #if !defined(NO_RSA) || defined(HAVE_ECC)
+ FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey);
+ #endif
+
if (ssl->buffers.altKeyType == falcon_level1_sa_algo ||
- ssl->buffers.altKeyType == falcon_level5_sa_algo) {
+ ssl->buffers.altKeyType == falcon_level5_sa_algo ||
+ ssl->buffers.altKeyType == 0) {
ssl->hsAltType = DYNAMIC_TYPE_FALCON;
ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
@@ -28234,14 +30591,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,
@@ -28250,21 +30618,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);
@@ -28273,15 +30648,17 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
}
if (ssl->buffers.altKeyType == dilithium_level2_sa_algo) {
- ret = wc_dilithium_set_level((dilithium_key*)ssl->hsAltKey, 2);
+ ret = wc_dilithium_set_level((dilithium_key*)ssl->hsAltKey, WC_ML_DSA_44);
}
else if (ssl->buffers.altKeyType == dilithium_level3_sa_algo) {
- ret = wc_dilithium_set_level((dilithium_key*)ssl->hsAltKey, 3);
+ ret = wc_dilithium_set_level((dilithium_key*)ssl->hsAltKey, WC_ML_DSA_65);
}
else if (ssl->buffers.altKeyType == dilithium_level5_sa_algo) {
- ret = wc_dilithium_set_level((dilithium_key*)ssl->hsAltKey, 5);
+ ret = wc_dilithium_set_level((dilithium_key*)ssl->hsAltKey, WC_ML_DSA_87);
}
else {
+ /* What if ssl->buffers.keyType is 0? We might want to do something
+ * more graceful here. */
ret = ALGO_ID_E;
}
@@ -28289,36 +30666,65 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
goto exit_dapk;
}
- WOLFSSL_MSG("Trying Dilithium private key");
+ #if defined(HAVE_FALCON)
+ WOLFSSL_MSG("Trying Dilithium private key, Falcon didn't work");
+ #elif defined(HAVE_ECC)
+ WOLFSSL_MSG("Trying Dilithium private key, ECC didn't work");
+ #elif !defined(NO_RSA)
+ WOLFSSL_MSG("Trying Dilithium private key, RSA didn't work");
+ #else
+ WOLFSSL_MSG("Trying Dilithium private key");
+ #endif
+ /* Set start of data to beginning of buffer. */
+ idx = 0;
/* Decode the key assuming it is a Dilithium private key. */
- ret = wc_dilithium_import_private_only(ssl->buffers.altKey->buffer,
- ssl->buffers.altKey->length,
- (dilithium_key*)ssl->hsAltKey);
+ ret = wc_Dilithium_PrivateKeyDecode(ssl->buffers.altKey->buffer,
+ &idx,
+ (dilithium_key*)ssl->hsAltKey,
+ ssl->buffers.altKey->length);
if (ret == 0) {
WOLFSSL_MSG("Using Dilithium private key");
/* Check it meets the minimum Dilithium key size requirements. */
- if (DILITHIUM_MAX_KEY_SIZE < ssl->options.minDilithiumKeySz) {
+ keySz = wc_dilithium_size((dilithium_key*)ssl->hsAltKey);
+ if (keySz < ssl->options.minDilithiumKeySz) {
WOLFSSL_MSG("Dilithium key size too small");
ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dapk);
}
+ /* Return the maximum signature length. */
*length = wc_dilithium_sig_size((dilithium_key*)ssl->hsAltKey);
goto exit_dapk;
}
}
+#endif /* HAVE_DILITHIUM */
+
+ (void)idx;
+ (void)keySz;
+ (void)length;
exit_dapk:
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ if (ret == 0) {
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey,
+ &ssl->buffers.altKeyMask);
+ }
+ else {
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key, ssl->buffers.keyMask);
+ }
+#endif
+
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(ret);
}
return ret;
}
-#endif /* HAVE_PQC && WOLFSSL_DUAL_ALG_CERTS */
-#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
+#endif /* WOLFSSL_DUAL_ALG_CERTS */
+
+#endif /* !NO_CERTS */
#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_TLS12)
/* returns 1 if able to do TLS 1.3 otherwise 0 */
@@ -28343,7 +30749,7 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
}
#endif /* WOLFSSL_TLS13 */
-#ifndef WOLFSSL_NO_TLS12
+#if !defined(NO_TLS) && !defined(WOLFSSL_NO_TLS12)
#if (!defined(NO_WOLFSSL_CLIENT) && (!defined(NO_DH) || defined(HAVE_ECC) || \
defined(HAVE_CURVE25519) || defined(HAVE_CURVE448))) || \
(!defined(NO_WOLFSSL_SERVER) && (defined(HAVE_ECC) || \
@@ -28388,7 +30794,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);
@@ -28398,11 +30804,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) {
@@ -28419,11 +30830,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
ssl->buffers.digest.length = (unsigned int)digest_sz;
/* buffer for hash */
- if (!ssl->buffers.digest.buffer) {
- if (!ssl->options.dontFreeDigest) {
- XFREE(ssl->buffers.digest.buffer, ssl->heap,
- DYNAMIC_TYPE_DIGEST);
- }
+ if (!ssl->options.dontFreeDigest) {
+ XFREE(ssl->buffers.digest.buffer, ssl->heap,
+ DYNAMIC_TYPE_DIGEST);
}
ssl->options.dontFreeDigest = 0;
@@ -28451,11 +30860,11 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
return ret;
}
-#endif
-#endif /* !WOLFSSL_NO_TLS12 */
+#endif /* !NO_WOLFSSL_CLIENT [...etc] || !NO_WOLFSSL_SERVER [...etc] */
+#endif /* !NO_TLS && !WOLFSSL_NO_TLS12 */
/* client only parts */
-#ifndef NO_WOLFSSL_CLIENT
+#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
int HaveUniqueSessionObj(WOLFSSL* ssl)
{
@@ -28481,7 +30890,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) {
@@ -28528,9 +30937,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
idSz = 0;
}
-#endif
+#endif /* HAVE_SESSION_TICKET */
length = VERSION_SZ + RAN_LEN
- + idSz + ENUM_LEN
+ + (word32)idSz + ENUM_LEN
+ SUITE_LEN
+ COMP_LEN + ENUM_LEN;
#ifndef NO_FORCE_SCR_SAME_SUITE
@@ -28559,8 +30968,8 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
#endif
if (extSz != 0)
length += extSz + HELLO_EXT_SZ_SZ;
-#endif
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+#endif /* HAVE_TLS_EXTENSIONS */
+ sendSz = (int)length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
if (ssl->arrays == NULL) {
return BAD_FUNC_ARG;
@@ -28570,7 +30979,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
if (ssl->options.dtls) {
length += ENUM_LEN; /* cookie */
if (ssl->arrays->cookieSz != 0) length += ssl->arrays->cookieSz;
- sendSz = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
+ sendSz = (int)length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
}
#endif
@@ -28631,7 +31040,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
idx += cookieSz;
}
}
-#endif
+#endif /* WOLFSSL_DTLS */
#ifndef NO_FORCE_SCR_SAME_SUITE
if (IsSCR(ssl)) {
@@ -28641,7 +31050,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
output[idx++] = ssl->options.cipherSuite;
}
else
-#endif
+#endif /* NO_FORCE_SCR_SAME_SUITE */
{
/* then cipher suites */
c16toa(suites->suiteSz, output + idx);
@@ -28667,7 +31076,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
(void)idx; /* suppress analyzer warning, keep idx current */
#else
if (extSz != 0) {
- c16toa(extSz, output + idx);
+ c16toa((word16)(extSz), output + idx);
idx += HELLO_EXT_SZ_SZ;
if (IsAtLeastTLSv1_2(ssl)) {
@@ -28697,69 +31106,20 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
}
#endif
}
-#endif
-
- if (IsEncryptionOn(ssl, 1)) {
- byte* input;
- int inputSz = idx; /* build msg adds rec hdr */
- int recordHeaderSz = RECORD_HEADER_SZ;
-
- if (ssl->options.dtls)
- recordHeaderSz += DTLS_RECORD_EXTRA;
- inputSz -= recordHeaderSz;
- input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- if (input == NULL)
- return MEMORY_E;
-
- XMEMCPY(input, output + recordHeaderSz, inputSz);
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl) &&
- (ret = DtlsMsgPoolSave(ssl, input, inputSz, client_hello)) != 0) {
- XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- return ret;
- }
- #endif
- sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
- handshake, 1, 0, 0, CUR_ORDER);
- XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+#endif /* HAVE_TLS_EXTENSIONS */
- if (sendSz < 0)
- return sendSz;
- } else {
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl)) {
- if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, client_hello)) != 0)
- return ret;
- }
- if (ssl->options.dtls)
- DtlsSEQIncrement(ssl, CUR_ORDER);
- #endif
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0)
- return ret;
- }
+ ret = BuildMsgOrHashOutput(ssl, output, &sendSz, idx, client_hello,
+ "ClientHello");
+ if (ret != 0)
+ return ret;
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
#ifdef OPENSSL_EXTRA
- ssl->cbmode = SSL_CB_MODE_WRITE;
+ ssl->cbmode = WOLFSSL_CB_MODE_WRITE;
if (ssl->CBIS != NULL)
- ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_CONNECT_LOOP, WOLFSSL_SUCCESS);
#endif
-#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
- if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello");
- if (ssl->toInfoOn) {
- ret = AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz,
- WRITE_PROTO, 0, ssl->heap);
- if (ret != 0)
- return ret;
- }
-#endif
-
- ssl->options.buildingMsg = 0;
-
- ssl->buffers.outputBuffer.length += sendSz;
-
ret = SendBuffered(ssl);
WOLFSSL_LEAVE("SendClientHello", ret);
@@ -28783,9 +31143,8 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
#endif
#ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
+ if (ssl->options.dtls)
DtlsMsgPoolReset(ssl);
- }
#endif
if (OPAQUE16_LEN + OPAQUE8_LEN > size)
@@ -28822,6 +31181,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) */
@@ -28843,7 +31205,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
&& ssl->session->ticketLen > 0
#endif
);
-#endif
+#endif /* HAVE_SECRET_CALLBACK */
#ifdef HAVE_SESSION_TICKET
/* server may send blank ticket which may not be expected to indicate
@@ -28852,8 +31214,10 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
#endif
ret = ret ||
- (ssl->options.haveSessionId && XMEMCMP(ssl->arrays->sessionID,
- ssl->session->sessionID, ID_LEN) == 0);
+ (ssl->options.haveSessionId && ssl->arrays->sessionIDSz == ID_LEN
+ && ssl->session->sessionIDSz == ID_LEN
+ && XMEMCMP(ssl->arrays->sessionID,
+ ssl->session->sessionID, ID_LEN) == 0);
return ret;
}
@@ -28875,11 +31239,11 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
}
#endif
- #ifdef OPENSSL_EXTRA
+ #ifdef OPENSSL_EXTRA
if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_CB_HANDSHAKE_START, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_HANDSHAKE_START, WOLFSSL_SUCCESS);
}
- #endif
+ #endif
if (ssl->options.dtls) {
if (pv.major != DTLS_MAJOR || pv.minor == DTLS_BOGUS_MINOR) {
@@ -28927,7 +31291,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
return VERSION_ERROR;
}
- #endif
+ #endif /* HAVE_SECURE_RENEGOTIATION */
/* Checks made - OK to downgrade. */
ssl->version.minor = pv.minor;
@@ -29091,7 +31455,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
}
}
else
-#endif
+#endif /* HAVE_SECURE_RENEGOTIATION && !NO_FORCE_SCR_SAME_SUITE */
{
word32 idx, found = 0;
const Suites* suites = WOLFSSL_SUITES(ssl);
@@ -29161,6 +31525,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
else
ssl->options.haveEMS = 0; /* If no extensions, no EMS */
#else
+ /* !HAVE_TLS_EXTENSIONS */
{
byte pendingEMS = 0;
@@ -29208,7 +31573,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
else
i += extSz;
- totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
+ totalExtSz -= (word16)(OPAQUE16_LEN) +
+ (word16)(OPAQUE16_LEN) +
+ extSz;
}
*inOutIdx = i;
@@ -29220,7 +31587,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
if (!pendingEMS && ssl->options.haveEMS)
ssl->options.haveEMS = 0;
}
-#endif
+#endif /* HAVE_TLS_EXTENSIONS */
#if defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
if (ssl->secure_renegotiation == NULL ||
@@ -29236,15 +31603,8 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
ssl->options.serverState = SERVER_HELLO_COMPLETE;
- if (IsEncryptionOn(ssl, 0)) {
+ if (IsEncryptionOn(ssl, 0))
*inOutIdx += ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMWrite &&
- ssl->specs.cipher_type == block) {
- *inOutIdx += MacSize(ssl);
- }
- #endif
- }
#ifdef HAVE_SECRET_CALLBACK
if (ssl->sessionSecretCb != NULL
@@ -29292,7 +31652,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
}
}
else
- #endif
+ #endif /* WOLFSSL_TLS13 */
if (ssl->ctx->method->version.major == SSLv3_MAJOR &&
ssl->ctx->method->version.minor == TLSv1_2_MINOR &&
(wolfSSL_get_options(ssl) & WOLFSSL_OP_NO_TLSv1_2) == 0) {
@@ -29383,7 +31743,8 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
word16 len;
word32 begin = *inOutIdx;
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \
- defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)
+ defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
+ defined(WOLFSSL_CERT_SETUP_CB)
int ret;
#endif
#ifdef OPENSSL_EXTRA
@@ -29423,7 +31784,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
if ((len > size) || ((*inOutIdx - begin) + len > size))
return BUFFER_ERROR;
- if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 &&
+ if (PickHashSigAlgo(ssl, input + *inOutIdx, len, 0) != 0 &&
ssl->buffers.certificate &&
ssl->buffers.certificate->buffer) {
#ifdef HAVE_PK_CALLBACKS
@@ -29458,10 +31819,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
return BUFFER_ERROR;
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)
- 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 = wolfSSL_sk_X509_NAME_new(NULL);
- if (ssl->client_ca_names == NULL) {
+ wolfSSL_sk_X509_NAME_pop_free(ssl->peer_ca_names, NULL);
+ ssl->peer_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+ if (ssl->peer_ca_names == NULL) {
return MEMORY_ERROR;
}
#endif
@@ -29494,7 +31854,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
InitDecodedCert(cert, input + *inOutIdx, dnSz, ssl->heap);
- ret = GetName(cert, SUBJECT, dnSz);
+ ret = GetName(cert, ASN_SUBJECT, dnSz);
if (ret == 0) {
if ((name = wolfSSL_X509_NAME_new_ex(cert->heap)) == NULL)
@@ -29502,12 +31862,12 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
}
if (ret == 0) {
- CopyDecodedName(name, cert, SUBJECT);
+ CopyDecodedName(name, cert, ASN_SUBJECT);
}
if (ret == 0) {
- if (wolfSSL_sk_X509_NAME_push(ssl->client_ca_names, name)
- == WOLFSSL_FAILURE)
+ if (wolfSSL_sk_X509_NAME_push(ssl->peer_ca_names, name)
+ <= 0)
{
ret = MEMORY_ERROR;
}
@@ -29515,9 +31875,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
FreeDecodedCert(cert);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
-#endif
+ WC_FREE_VAR_EX(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
if (ret != 0) {
if (name != NULL)
wolfSSL_X509_NAME_free(name);
@@ -29527,9 +31885,10 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
#endif
*inOutIdx += dnSz;
- len -= OPAQUE16_LEN + dnSz;
+ len -= (word16)(OPAQUE16_LEN) + dnSz;
}
+ #ifdef WOLFSSL_CERT_SETUP_CB
#ifdef OPENSSL_EXTRA
/* call client cert callback if no cert has been loaded */
if ((ssl->ctx->CBClientCert != NULL) &&
@@ -29543,6 +31902,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
return CLIENT_CERT_CB_ERROR;
}
wolfSSL_X509_free(x509);
+ x509 = NULL;
wolfSSL_EVP_PKEY_free(pkey);
}
@@ -29550,6 +31910,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
return WOLFSSL_ERROR_WANT_X509_LOOKUP;
}
}
+ #endif
if ((ret = CertSetupCbWrapper(ssl)) != 0)
return ret;
#endif
@@ -29576,13 +31937,8 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
ssl->options.sendVerify = SEND_BLANK_CERT;
}
- if (IsEncryptionOn(ssl, 0)) {
+ if (IsEncryptionOn(ssl, 0))
*inOutIdx += ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- *inOutIdx += MacSize(ssl);
- #endif
- }
WOLFSSL_LEAVE("DoCertificateRequest", 0);
WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
@@ -29596,7 +31952,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
static int CheckCurveId(int tlsCurveId)
{
- int ret = ECC_CURVE_ERROR;
+ int ret = WC_NO_ERR_TRACE(ECC_CURVE_ERROR);
switch (tlsCurveId) {
#if (defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 160
@@ -29664,7 +32020,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID;
#endif /* !NO_ECC_SECP */
#endif
- default: break;
+ default:
+ ret = WC_NO_ERR_TRACE(ECC_CURVE_ERROR);
+ break;
}
return ret;
@@ -29700,10 +32058,8 @@ static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs)
#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
defined(HAVE_CURVE448)
- if (args->verifySig) {
- XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
- args->verifySig = NULL;
- }
+ XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ args->verifySig = NULL;
#endif
}
@@ -29960,6 +32316,188 @@ static int GetDhPublicKey(WOLFSSL* ssl, const byte* input, word32 size,
return ret;
}
#endif
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+static int GetEcDiffieHellmanKea(WOLFSSL *ssl,
+ const byte *input, word32 size, DskeArgs *args)
+{
+ int ret;
+ byte b;
+#ifdef HAVE_ECC
+ int curveId;
+#endif
+ int curveOid;
+ word16 length;
+
+ if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
+ OPAQUE8_LEN > size) {
+ return BUFFER_ERROR;
+ }
+
+ b = input[args->idx++];
+ if (b != named_curve) {
+ return ECC_CURVETYPE_ERROR;
+ }
+
+ args->idx += 1; /* curve type, eat leading 0 */
+ b = input[args->idx++];
+ if ((curveOid = CheckCurveId(b)) < 0) {
+ return ECC_CURVE_ERROR;
+ }
+ ssl->ecdhCurveOID = (word32) curveOid;
+#if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
+ ssl->namedGroup = 0;
+#endif
+
+ length = input[args->idx++];
+ if ((args->idx - args->begin) + length > size) {
+ return BUFFER_ERROR;
+ }
+#ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ if (ssl->peerX25519Key == NULL) {
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void **)&ssl->peerX25519Key);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ else if (ssl->peerX25519KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ if ((ret = wc_curve25519_check_public(input + args->idx, length,
+ EC25519_LITTLE_ENDIAN)) != 0) {
+#ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == WC_NO_ERR_TRACE(BUFFER_E))
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E))
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ }
+#else
+ (void)ret;
+#endif
+ return ECC_PEERKEY_ERROR;
+ }
+
+ if (wc_curve25519_import_public_ex(input + args->idx,
+ length, ssl->peerX25519Key,
+ EC25519_LITTLE_ENDIAN) != 0) {
+ return ECC_PEERKEY_ERROR;
+ }
+
+ args->idx += length;
+ ssl->peerX25519KeyPresent = 1;
+ return 0;
+ }
+#endif
+#ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ if (ssl->peerX448Key == NULL) {
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void **)&ssl->peerX448Key);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ else if (ssl->peerX448KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448, ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ if ((ret = wc_curve448_check_public(input + args->idx, length,
+ EC448_LITTLE_ENDIAN)) != 0) {
+#ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == WC_NO_ERR_TRACE(BUFFER_E))
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E))
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ }
+#else
+ (void)ret;
+#endif
+ return ECC_PEERKEY_ERROR;
+ }
+
+ if (wc_curve448_import_public_ex(input + args->idx,
+ length, ssl->peerX448Key,
+ EC448_LITTLE_ENDIAN) != 0) {
+ return ECC_PEERKEY_ERROR;
+ }
+
+ args->idx += length;
+ ssl->peerX448KeyPresent = 1;
+ return 0;
+ }
+#endif
+#ifdef HAVE_ECC
+ if (ssl->peerEccKey == NULL) {
+ ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, (void **)&ssl->peerEccKey);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ else if (ssl->peerEccKeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ curveId = wc_ecc_get_oid((word32) curveOid, NULL, NULL);
+ if (wc_ecc_import_x963_ex(input + args->idx, length,
+ ssl->peerEccKey, curveId) != 0) {
+#ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+#endif
+ return ECC_PEERKEY_ERROR;
+ }
+
+ args->idx += length;
+ ssl->peerEccKeyPresent = 1;
+#endif
+ return 0;
+}
+#endif /* def(HAVE_ECC) || def(HAVE_CURVE25519) || def(HAVE_CURVE448)) */
+
+#if !defined(NO_PSK)
+static int GetPSKServerHint(WOLFSSL *ssl, const byte *input, word32 size,
+ DskeArgs *args)
+{
+ int srvHintLen;
+ word16 length;
+
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ return BUFFER_ERROR;
+ }
+
+ ato16(input + args->idx, &length);
+ args->idx += OPAQUE16_LEN;
+
+ if ((args->idx - args->begin) + length > size) {
+ return BUFFER_ERROR;
+ }
+
+ /* get PSK server hint from the wire */
+ srvHintLen = (int)min(length, MAX_PSK_ID_LEN);
+ XMEMCPY(ssl->arrays->server_hint, input + args->idx, (size_t)(srvHintLen));
+ ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
+
+ args->idx += length;
+ return 0;
+}
+#endif /* !defined(NO_PSK) */
/* handle processing of server_key_exchange (12) */
static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
@@ -29990,7 +32528,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
args = (DskeArgs*)ssl->async->args;
ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* Check for error */
if (ret < 0)
goto exit_dske;
@@ -30027,26 +32565,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
#ifndef NO_PSK
case psk_kea:
{
- int srvHintLen;
- word16 length;
-
- if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- ato16(input + args->idx, &length);
- args->idx += OPAQUE16_LEN;
-
- if ((args->idx - args->begin) + length > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- /* get PSK server hint from the wire */
- srvHintLen = min(length, MAX_PSK_ID_LEN);
- XMEMCPY(ssl->arrays->server_hint, input + args->idx,
- srvHintLen);
- ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
- args->idx += length;
+ ret = GetPSKServerHint(ssl, input, size, args);
break;
}
#endif /* !NO_PSK */
@@ -30054,8 +32573,6 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
case diffie_hellman_kea:
{
ret = GetDhPublicKey(ssl, input, size, args);
- if (ret != 0)
- goto exit_dske;
break;
}
#endif /* !NO_DH */
@@ -30063,181 +32580,16 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
defined(HAVE_CURVE448)
case ecc_diffie_hellman_kea:
{
- byte b;
- #ifdef HAVE_ECC
- int curveId;
- #endif
- int curveOid;
- word16 length;
-
- if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
- OPAQUE8_LEN > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- b = input[args->idx++];
- if (b != named_curve) {
- ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
- }
-
- args->idx += 1; /* curve type, eat leading 0 */
- b = input[args->idx++];
- if ((curveOid = CheckCurveId(b)) < 0) {
- ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
- }
- ssl->ecdhCurveOID = curveOid;
- #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
- ssl->namedGroup = 0;
- #endif
-
- length = input[args->idx++];
- if ((args->idx - args->begin) + length > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- #ifdef HAVE_CURVE25519
- if (ssl->ecdhCurveOID == ECC_X25519_OID) {
- if (ssl->peerX25519Key == NULL) {
- ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
- (void**)&ssl->peerX25519Key);
- if (ret != 0) {
- goto exit_dske;
- }
- } else if (ssl->peerX25519KeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
- ssl->peerX25519Key);
- ssl->peerX25519KeyPresent = 0;
- if (ret != 0) {
- goto exit_dske;
- }
- }
-
- if ((ret = wc_curve25519_check_public(
- input + args->idx, length,
- EC25519_LITTLE_ENDIAN)) != 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- if (ret == BUFFER_E)
- SendAlert(ssl, alert_fatal, decode_error);
- else if (ret == ECC_OUT_OF_RANGE_E)
- SendAlert(ssl, alert_fatal, bad_record_mac);
- else {
- SendAlert(ssl, alert_fatal, illegal_parameter);
- }
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- if (wc_curve25519_import_public_ex(input + args->idx,
- length, ssl->peerX25519Key,
- EC25519_LITTLE_ENDIAN) != 0) {
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- args->idx += length;
- ssl->peerX25519KeyPresent = 1;
- break;
- }
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->ecdhCurveOID == ECC_X448_OID) {
- if (ssl->peerX448Key == NULL) {
- ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
- (void**)&ssl->peerX448Key);
- if (ret != 0) {
- goto exit_dske;
- }
- } else if (ssl->peerX448KeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
- ssl->peerX448Key);
- ssl->peerX448KeyPresent = 0;
- if (ret != 0) {
- goto exit_dske;
- }
- }
-
- if ((ret = wc_curve448_check_public(
- input + args->idx, length,
- EC448_LITTLE_ENDIAN)) != 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- if (ret == BUFFER_E)
- SendAlert(ssl, alert_fatal, decode_error);
- else if (ret == ECC_OUT_OF_RANGE_E)
- SendAlert(ssl, alert_fatal, bad_record_mac);
- else {
- SendAlert(ssl, alert_fatal, illegal_parameter);
- }
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- if (wc_curve448_import_public_ex(input + args->idx,
- length, ssl->peerX448Key,
- EC448_LITTLE_ENDIAN) != 0) {
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- args->idx += length;
- ssl->peerX448KeyPresent = 1;
- break;
- }
- #endif
- #ifdef HAVE_ECC
- if (ssl->peerEccKey == NULL) {
- ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
- (void**)&ssl->peerEccKey);
- if (ret != 0) {
- goto exit_dske;
- }
- } else if (ssl->peerEccKeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
- ssl->peerEccKeyPresent = 0;
- if (ret != 0) {
- goto exit_dske;
- }
- }
-
- curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
- if (wc_ecc_import_x963_ex(input + args->idx, length,
- ssl->peerEccKey, curveId) != 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- SendAlert(ssl, alert_fatal, illegal_parameter);
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- args->idx += length;
- ssl->peerEccKeyPresent = 1;
- #endif
+ ret = GetEcDiffieHellmanKea(ssl, input, size, args);
break;
}
#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
#if !defined(NO_DH) && !defined(NO_PSK)
case dhe_psk_kea:
{
- int srvHintLen;
- word16 length;
-
- if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- ato16(input + args->idx, &length);
- args->idx += OPAQUE16_LEN;
-
- if ((args->idx - args->begin) + length > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- /* get PSK server hint from the wire */
- srvHintLen = min(length, MAX_PSK_ID_LEN);
- XMEMCPY(ssl->arrays->server_hint, input + args->idx,
- srvHintLen);
- ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
- args->idx += length;
-
- ret = GetDhPublicKey(ssl, input, size, args);
- if (ret != 0)
- goto exit_dske;
+ ret = GetPSKServerHint(ssl, input, size, args);
+ if (ret == 0)
+ ret = GetDhPublicKey(ssl, input, size, args);
break;
}
#endif /* !NO_DH && !NO_PSK */
@@ -30245,162 +32597,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
defined(HAVE_CURVE448)) && !defined(NO_PSK)
case ecdhe_psk_kea:
{
- byte b;
- int curveOid, curveId;
- int srvHintLen;
- word16 length;
-
- if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- ato16(input + args->idx, &length);
- args->idx += OPAQUE16_LEN;
-
- if ((args->idx - args->begin) + length > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- /* get PSK server hint from the wire */
- srvHintLen = min(length, MAX_PSK_ID_LEN);
- XMEMCPY(ssl->arrays->server_hint, input + args->idx,
- srvHintLen);
- ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */
-
- args->idx += length;
-
- if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN +
- OPAQUE8_LEN > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- /* Check curve name and ID */
- b = input[args->idx++];
- if (b != named_curve) {
- ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske);
- }
-
- args->idx += 1; /* curve type, eat leading 0 */
- b = input[args->idx++];
- if ((curveOid = CheckCurveId(b)) < 0) {
- ERROR_OUT(ECC_CURVE_ERROR, exit_dske);
- }
- ssl->ecdhCurveOID = curveOid;
-
- length = input[args->idx++];
- if ((args->idx - args->begin) + length > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dske);
- }
-
- #ifdef HAVE_CURVE25519
- if (ssl->ecdhCurveOID == ECC_X25519_OID) {
- if (ssl->peerX25519Key == NULL) {
- ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
- (void**)&ssl->peerX25519Key);
- if (ret != 0) {
- goto exit_dske;
- }
- } else if (ssl->peerEccKeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
- ssl->peerX25519Key);
- ssl->peerX25519KeyPresent = 0;
- if (ret != 0) {
- goto exit_dske;
- }
- }
-
- if ((ret = wc_curve25519_check_public(
- input + args->idx, length,
- EC25519_LITTLE_ENDIAN)) != 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- if (ret == BUFFER_E)
- SendAlert(ssl, alert_fatal, decode_error);
- else if (ret == ECC_OUT_OF_RANGE_E)
- SendAlert(ssl, alert_fatal, bad_record_mac);
- else {
- SendAlert(ssl, alert_fatal, illegal_parameter);
- }
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- if (wc_curve25519_import_public_ex(input + args->idx,
- length, ssl->peerX25519Key,
- EC25519_LITTLE_ENDIAN) != 0) {
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- args->idx += length;
- ssl->peerX25519KeyPresent = 1;
- break;
- }
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->ecdhCurveOID == ECC_X448_OID) {
- if (ssl->peerX448Key == NULL) {
- ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
- (void**)&ssl->peerX448Key);
- if (ret != 0) {
- goto exit_dske;
- }
- } else if (ssl->peerEccKeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
- ssl->peerX448Key);
- ssl->peerX448KeyPresent = 0;
- if (ret != 0) {
- goto exit_dske;
- }
- }
-
- if ((ret = wc_curve448_check_public(
- input + args->idx, length,
- EC448_LITTLE_ENDIAN)) != 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- if (ret == BUFFER_E)
- SendAlert(ssl, alert_fatal, decode_error);
- else if (ret == ECC_OUT_OF_RANGE_E)
- SendAlert(ssl, alert_fatal, bad_record_mac);
- else {
- SendAlert(ssl, alert_fatal, illegal_parameter);
- }
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- if (wc_curve448_import_public_ex(input + args->idx,
- length, ssl->peerX448Key,
- EC448_LITTLE_ENDIAN) != 0) {
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- args->idx += length;
- ssl->peerX448KeyPresent = 1;
- break;
- }
- #endif
-
- if (ssl->peerEccKey == NULL) {
- ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
- (void**)&ssl->peerEccKey);
- if (ret != 0) {
- goto exit_dske;
- }
- } else if (ssl->peerEccKeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
- ssl->peerEccKeyPresent = 0;
- if (ret != 0) {
- goto exit_dske;
- }
- }
-
- curveId = wc_ecc_get_oid(curveOid, NULL, NULL);
- if (wc_ecc_import_x963_ex(input + args->idx, length,
- ssl->peerEccKey, curveId) != 0) {
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske);
- }
-
- args->idx += length;
- ssl->peerEccKeyPresent = 1;
+ ret = GetPSKServerHint(ssl, input, size, args);
+ if (ret == 0)
+ ret = GetEcDiffieHellmanKea(ssl, input, size, args);
break;
}
#endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
@@ -30438,14 +32637,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);
}
@@ -30456,6 +32655,15 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
ERROR_OUT(BUFFER_ERROR, exit_dske);
}
+ /* Check if hashSigAlgo in Server Key Exchange is supported
+ * in our ssl->suites or ssl->ctx->suites. */
+ if (!SupportedHashSigAlgo(ssl, &input[args->idx])) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, handshake_failure);
+ #endif
+ ERROR_OUT(MATCH_SUITE_ERROR, exit_dske);
+ }
+
DecodeSigAlg(&input[args->idx], &ssl->options.peerHashAlgo,
&sigAlgo);
#ifndef NO_RSA
@@ -30465,6 +32673,13 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
}
else
#endif
+ #ifdef WC_RSA_PSS
+ if (sigAlgo == rsa_pss_pss_algo &&
+ ssl->options.peerSigAlgo == rsa_sa_algo) {
+ ssl->options.peerSigAlgo = sigAlgo;
+ }
+ else
+ #endif
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
if (sigAlgo == sm2_sa_algo &&
ssl->options.peerSigAlgo == ecc_dsa_sa_algo) {
@@ -30531,6 +32746,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
#ifndef NO_RSA
#ifdef WC_RSA_PSS
case rsa_pss_sa_algo:
+ case rsa_pss_pss_algo:
#endif
case rsa_sa_algo:
{
@@ -30631,6 +32847,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
#ifndef NO_RSA
#ifdef WC_RSA_PSS
case rsa_pss_sa_algo:
+ case rsa_pss_pss_algo:
#endif
case rsa_sa_algo:
{
@@ -30654,7 +32871,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
ret = 0;
}
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret != WC_PENDING_E)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
/* peerRsaKey */
@@ -30682,7 +32899,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
(ssl->buffers.sig.length - SEED_LEN));
}
#endif /* HAVE_PK_CALLBACKS */
- if (ret == NOT_COMPILED_IN) {
+ if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) {
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
if (ssl->options.peerSigAlgo == sm2_sa_algo) {
ret = Sm2wSm3Verify(ssl,
@@ -30716,7 +32933,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
}
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret != WC_PENDING_E)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
/* peerEccDsaKey */
@@ -30746,7 +32963,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret != WC_PENDING_E)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
/* peerEccDsaKey */
@@ -30776,7 +32993,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret != WC_PENDING_E)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
/* peerEccDsaKey */
@@ -30842,6 +33059,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
#ifndef NO_RSA
#ifdef WC_RSA_PSS
case rsa_pss_sa_algo:
+ case rsa_pss_pss_algo:
#ifdef HAVE_SELFTEST
ret = wc_RsaPSS_CheckPadding(
ssl->buffers.digest.buffer,
@@ -30875,20 +33093,14 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
}
#endif
if (IsAtLeastTLSv1_2(ssl)) {
- #ifdef WOLFSSL_SMALL_STACK
- byte* encodedSig;
- #else
- byte encodedSig[MAX_ENCODED_SIG_SZ];
- #endif
+ WC_DECLARE_VAR(encodedSig, byte,
+ MAX_ENCODED_SIG_SZ, 0);
word32 encSigSz;
- #ifdef WOLFSSL_SMALL_STACK
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
- ssl->heap, DYNAMIC_TYPE_SIGNATURE);
- if (encodedSig == NULL) {
- ERROR_OUT(MEMORY_E, exit_dske);
- }
- #endif
+ WC_ALLOC_VAR_EX(encodedSig, byte,
+ MAX_ENCODED_SIG_SZ, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE,
+ ERROR_OUT(MEMORY_E,exit_dske));
encSigSz = wc_EncodeSignature(encodedSig,
ssl->buffers.digest.buffer,
@@ -30899,9 +33111,8 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) {
ret = VERIFY_SIGN_ERROR;
}
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
- #endif
+ WC_FREE_VAR_EX(encodedSig, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
if (ret != 0) {
goto exit_dske;
}
@@ -30961,13 +33172,8 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
case TLS_ASYNC_FINALIZE:
{
- if (IsEncryptionOn(ssl, 0)) {
+ if (IsEncryptionOn(ssl, 0))
args->idx += ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- args->idx += MacSize(ssl);
- #endif
- }
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_END;
@@ -30993,7 +33199,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input,
#ifdef WOLFSSL_ASYNC_CRYPT
/* Handle async operation */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* Mark message as not received so it can process again */
ssl->msgsReceived.got_server_key_exchange = 0;
@@ -31030,15 +33236,201 @@ static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs)
(void)ssl;
- if (args->encSecret) {
- XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
- args->encSecret = NULL;
+ XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
+ args->encSecret = NULL;
+ XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ args->input = NULL;
+}
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
+static int EcExportHsKey(WOLFSSL* ssl, byte* out, word32* len)
+{
+ int ret = 0;
+#ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X25519SharedSecretCb != NULL)
+ return 0;
+ #endif
+ if (wc_curve25519_export_public_ex((curve25519_key*)ssl->hsKey,
+ out + OPAQUE8_LEN, len, EC25519_LITTLE_ENDIAN))
+ ret = ECC_EXPORT_ERROR;
+ } else
+#endif
+#ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X448SharedSecretCb != NULL)
+ return 0;
+ #endif
+ if (wc_curve448_export_public_ex((curve448_key*)ssl->hsKey,
+ out + OPAQUE8_LEN, len, EC448_LITTLE_ENDIAN))
+ ret = ECC_EXPORT_ERROR;
+ } else
+#endif
+ {
+#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
+#ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->EccSharedSecretCb != NULL)
+ return 0;
+#endif
+ /* Place ECC key in output buffer, leaving room for size */
+ PRIVATE_KEY_UNLOCK();
+ ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey, out + OPAQUE8_LEN, len);
+ PRIVATE_KEY_LOCK();
+ if (ret != 0)
+ ret = ECC_EXPORT_ERROR;
+#endif
}
- if (args->input) {
- XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- args->input = NULL;
+ return ret;
+}
+#endif /*HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448*/
+
+#ifndef NO_PSK
+static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
+{
+ int ret = 0;
+ /* Use the PSK hint to look up the PSK and add it to the
+ * preMasterSecret here. */
+ ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
+ ssl->arrays->client_identity, ssl->arrays->psk_key,
+ MAX_PSK_KEY_LEN);
+
+ if (ssl->arrays->psk_keySz == 0 ||
+ (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN &&
+ (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) {
+ #if defined(WOLFSSL_EXTRA_ALERTS) || defined(WOLFSSL_PSK_IDENTITY_ALERT)
+ SendAlert(ssl, alert_fatal, unknown_psk_identity);
+ #endif
+ ret = 1;
+ }
+ if (ret == 0)
+ /* Pre-shared Key for peer authentication. */
+ ssl->options.peerAuthGood = 1;
+ return ret;
+}
+
+static void MakePSKPreMasterSecret(Arrays* arrays, byte use_psk_key)
+{
+ byte* pms = arrays->preMasterSecret;
+ word16 sz;
+
+ /* sz + (use_psk_key ? sz 0s : sz unaltered) + length of psk + psk */
+ if (!use_psk_key) {
+ sz = (word16)arrays->preMasterSz;
+ c16toa(sz, pms);
+ pms += OPAQUE16_LEN + sz;
+ }
+ if ((int)arrays->psk_keySz > 0) {
+ if (use_psk_key) {
+ sz = (word16)arrays->psk_keySz;
+ c16toa(sz, pms);
+ pms += OPAQUE16_LEN;
+ XMEMSET(pms, 0, sz);
+ pms += sz;
+ }
+ c16toa(arrays->psk_keySz, pms);
+ pms += OPAQUE16_LEN;
+ XMEMCPY(pms, arrays->psk_key, arrays->psk_keySz);
+ arrays->preMasterSz = sz + arrays->psk_keySz + OPAQUE16_LEN * 2;
+ ForceZero(arrays->psk_key, arrays->psk_keySz);
+ }
+ arrays->psk_keySz = 0; /* no further need */
+}
+#endif /*!NO_PSK*/
+
+#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448))
+static int EcMakeKey(WOLFSSL* ssl)
+{
+ int ret = 0;
+#ifdef HAVE_ECC
+ int kea = ssl->specs.kea;
+ ecc_key* peerKey;
+#endif
+#ifdef HAVE_CURVE25519
+ if (ssl->peerX25519KeyPresent) {
+ /* Check client ECC public key */
+ if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
+ return NO_PEER_KEY;
+ }
+ /* if callback then use it for shared secret */
+ #ifdef HAVE_PK_CALLBACKS
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ if (ssl->ctx->X25519SharedSecretCb != NULL)
+ return 0;
+ }
+ #endif
+ /* create private key */
+ ssl->hsType = DYNAMIC_TYPE_CURVE25519;
+ ret = AllocKey(ssl, (int)(ssl->hsType), &ssl->hsKey);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
+ ssl->peerX25519Key);
+ return ret;
+ }
+#endif
+#ifdef HAVE_CURVE448
+ if (ssl->peerX448KeyPresent) {
+ /* Check client ECC public key */
+ if (!ssl->peerX448Key) {
+ return NO_PEER_KEY;
+ }
+ #ifdef HAVE_PK_CALLBACKS
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ if (ssl->ctx->X448SharedSecretCb != NULL)
+ return 0;
+ }
+ #endif
+ /* create private key */
+ ssl->hsType = DYNAMIC_TYPE_CURVE448;
+ ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = X448MakeKey(ssl, (curve448_key*)ssl->hsKey,
+ ssl->peerX448Key);
+ return ret;
}
+#endif
+#ifdef HAVE_ECC
+ if (kea == ecc_diffie_hellman_kea && ssl->specs.static_ecdh) {
+ /* Note: EccDsa is really fixed Ecc key here */
+ if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent) {
+ return NO_PEER_KEY;
+ }
+ peerKey = ssl->peerEccDsaKey;
+ }
+ else {
+ /* Check client ECC public key */
+ if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
+ !ssl->peerEccKey->dp) {
+ return NO_PEER_KEY;
+ }
+ peerKey = ssl->peerEccKey;
+ }
+ if (peerKey == NULL) {
+ return NO_PEER_KEY;
+ }
+#ifdef HAVE_PK_CALLBACKS
+ if (ssl->ctx->EccSharedSecretCb != NULL) {
+ return 0;
+ }
+#endif /* HAVE_PK_CALLBACKS*/
+ /* create ephemeral private key */
+ ssl->hsType = DYNAMIC_TYPE_ECC;
+ ret = AllocKey(ssl, (int)(ssl->hsType), &ssl->hsKey);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey);
+#endif /*HAVE_ECC*/
+ return ret;
}
+#endif /*defined(HAVE_ECC)||defined(HAVE_CURVE25519)||defined(HAVE_CURVE448)*/
/* handle generation client_key_exchange (16) */
int SendClientKeyExchange(WOLFSSL* ssl)
@@ -31056,9 +33448,9 @@ int SendClientKeyExchange(WOLFSSL* ssl)
#ifdef OPENSSL_EXTRA
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
- ssl->cbmode = SSL_CB_MODE_WRITE;
+ ssl->cbmode = WOLFSSL_CB_MODE_WRITE;
if (ssl->CBIS != NULL)
- ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, WOLFSSL_SUCCESS);
+ ssl->CBIS(ssl, WOLFSSL_CB_CONNECT_LOOP, WOLFSSL_SUCCESS);
#endif
#ifdef WOLFSSL_ASYNC_IO
@@ -31074,7 +33466,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
#ifdef WOLFSSL_ASYNC_CRYPT
ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* Check for error */
if (ret < 0)
goto exit_scke;
@@ -31153,181 +33545,18 @@ int SendClientKeyExchange(WOLFSSL* ssl)
WOLFSSL_MSG("No client PSK callback set");
ERROR_OUT(PSK_KEY_ERROR, exit_scke);
}
-
- #ifdef HAVE_CURVE25519
- if (ssl->peerX25519KeyPresent) {
- /* Check client ECC public key */
- if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
- ERROR_OUT(NO_PEER_KEY, exit_scke);
- }
-
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X25519SharedSecretCb != NULL) {
- break;
- }
- #endif
-
- /* create private key */
- ssl->hsType = DYNAMIC_TYPE_CURVE25519;
- ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
- if (ret != 0) {
- goto exit_scke;
- }
-
- ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
- ssl->peerX25519Key);
- break;
- }
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->peerX448KeyPresent) {
- /* Check client ECC public key */
- if (!ssl->peerX448Key) {
- ERROR_OUT(NO_PEER_KEY, exit_scke);
- }
-
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X448SharedSecretCb != NULL) {
- break;
- }
- #endif
-
- /* create private key */
- ssl->hsType = DYNAMIC_TYPE_CURVE448;
- ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
- if (ret != 0) {
- goto exit_scke;
- }
-
- ret = X448MakeKey(ssl, (curve448_key*)ssl->hsKey,
- ssl->peerX448Key);
- break;
- }
- #endif
- /* Check client ECC public key */
- if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
- !ssl->peerEccKey->dp) {
- ERROR_OUT(NO_PEER_KEY, exit_scke);
- }
-
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->EccSharedSecretCb != NULL) {
- break;
- }
- #endif
-
- /* create ephemeral private key */
- ssl->hsType = DYNAMIC_TYPE_ECC;
- ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
- if (ret != 0) {
- goto exit_scke;
- }
-
- ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey);
-
+ ret = EcMakeKey(ssl);
+ if (ret)
+ ERROR_OUT(ret, exit_scke);
break;
- #endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
+ #endif /* (HAVE_ECC||HAVE_CURVE25519||HAVE_CURVE448) && !NO_PSK */
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
defined(HAVE_CURVE448)
case ecc_diffie_hellman_kea:
{
- #ifdef HAVE_ECC
- ecc_key* peerKey;
- #endif
-
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- #ifdef HAVE_CURVE25519
- if (ssl->ecdhCurveOID == ECC_X25519_OID) {
- if (ssl->ctx->X25519SharedSecretCb != NULL)
- break;
- }
- else
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->ecdhCurveOID == ECC_X448_OID) {
- if (ssl->ctx->X448SharedSecretCb != NULL)
- break;
- }
- else
- #endif
- #ifdef HAVE_ECC
- if (ssl->ctx->EccSharedSecretCb != NULL) {
- break;
- }
- else
- #endif
- {
- }
- #endif /* HAVE_PK_CALLBACKS */
-
- #ifdef HAVE_CURVE25519
- if (ssl->peerX25519KeyPresent) {
- if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) {
- ERROR_OUT(NO_PEER_KEY, exit_scke);
- }
-
- /* create private key */
- ssl->hsType = DYNAMIC_TYPE_CURVE25519;
- ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
- if (ret != 0) {
- goto exit_scke;
- }
-
- ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey,
- ssl->peerX25519Key);
- break;
- }
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->peerX448KeyPresent) {
- if (!ssl->peerX448Key) {
- ERROR_OUT(NO_PEER_KEY, exit_scke);
- }
-
- /* create private key */
- ssl->hsType = DYNAMIC_TYPE_CURVE448;
- ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
- if (ret != 0) {
- goto exit_scke;
- }
-
- ret = X448MakeKey(ssl, (curve448_key*)ssl->hsKey,
- ssl->peerX448Key);
- break;
- }
- #endif
- #ifdef HAVE_ECC
- if (ssl->specs.static_ecdh) {
- /* Note: EccDsa is really fixed Ecc key here */
- if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent) {
- ERROR_OUT(NO_PEER_KEY, exit_scke);
- }
- peerKey = ssl->peerEccDsaKey;
- }
- else {
- if (!ssl->peerEccKey || !ssl->peerEccKeyPresent) {
- ERROR_OUT(NO_PEER_KEY, exit_scke);
- }
- peerKey = ssl->peerEccKey;
- }
- if (peerKey == NULL) {
- ERROR_OUT(NO_PEER_KEY, exit_scke);
- }
-
- /* create ephemeral private key */
- ssl->hsType = DYNAMIC_TYPE_ECC;
- ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
- if (ret != 0) {
- goto exit_scke;
- }
-
- ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey);
- #endif /* HAVE_ECC */
-
+ ret = EcMakeKey(ssl);
+ if (ret)
+ ERROR_OUT(ret, exit_scke);
break;
}
#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
@@ -31374,11 +33603,13 @@ int SendClientKeyExchange(WOLFSSL* ssl)
void* ctx = wolfSSL_GetGenPreMasterCtx(ssl);
ret = ssl->ctx->GenPreMasterCb(ssl,
ssl->arrays->preMasterSecret, ENCRYPT_LEN, ctx);
- if (ret != 0 && ret != PROTOCOLCB_UNAVAILABLE) {
+ if (ret != 0 &&
+ ret != WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) {
goto exit_scke;
}
}
- if (!ssl->ctx->GenPreMasterCb || ret == PROTOCOLCB_UNAVAILABLE)
+ if (!ssl->ctx->GenPreMasterCb ||
+ ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE))
#endif
{
/* build PreMasterSecret with RNG data */
@@ -31467,24 +33698,13 @@ int SendClientKeyExchange(WOLFSSL* ssl)
#ifndef NO_PSK
case psk_kea:
{
- byte* pms = ssl->arrays->preMasterSecret;
- int cbret = (int)ssl->options.client_psk_cb(ssl,
+ ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
ssl->arrays->server_hint, ssl->arrays->client_identity,
MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
-
- if (cbret == 0 || cbret > MAX_PSK_KEY_LEN) {
- if (cbret != USE_HW_PSK) {
- ERROR_OUT(PSK_KEY_ERROR, exit_scke);
- }
- }
-
- if (cbret == USE_HW_PSK) {
- /* USE_HW_PSK indicates that the hardware has the PSK
- * and generates the premaster secret. */
- ssl->arrays->psk_keySz = 0;
- }
- else {
- ssl->arrays->psk_keySz = (word32)cbret;
+ if (ssl->arrays->psk_keySz == 0 ||
+ (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN &&
+ (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) {
+ ERROR_OUT(PSK_KEY_ERROR, exit_scke);
}
/* Ensure the buffer is null-terminated. */
@@ -31496,24 +33716,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
XMEMCPY(args->encSecret, ssl->arrays->client_identity,
args->encSz);
ssl->options.peerAuthGood = 1;
- if (cbret != USE_HW_PSK) {
- /* CLIENT: Pre-shared Key for peer authentication. */
-
- /* make psk pre master secret */
- /* length of key + length 0s + length of key + key */
- c16toa((word16)ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
- XMEMSET(pms, 0, ssl->arrays->psk_keySz);
- pms += ssl->arrays->psk_keySz;
- c16toa((word16)ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
- XMEMCPY(pms, ssl->arrays->psk_key,
- ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2)
- + (2 * OPAQUE16_LEN);
- ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->psk_keySz = 0; /* No further need */
- }
+ MakePSKPreMasterSecret(ssl->arrays, 1);
break;
}
#endif /* !NO_PSK */
@@ -31524,12 +33727,14 @@ int SendClientKeyExchange(WOLFSSL* ssl)
args->output = args->encSecret;
ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
- ssl->arrays->server_hint, ssl->arrays->client_identity,
- MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+ ssl->arrays->server_hint, ssl->arrays->client_identity,
+ MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
if (ssl->arrays->psk_keySz == 0 ||
- ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+ (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN &&
+ (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) {
ERROR_OUT(PSK_KEY_ERROR, exit_scke);
}
+
ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
@@ -31605,12 +33810,14 @@ int SendClientKeyExchange(WOLFSSL* ssl)
/* Send PSK client identity */
ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
- ssl->arrays->server_hint, ssl->arrays->client_identity,
- MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
+ ssl->arrays->server_hint, ssl->arrays->client_identity,
+ MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
if (ssl->arrays->psk_keySz == 0 ||
- ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+ (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN &&
+ (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) {
ERROR_OUT(PSK_KEY_ERROR, exit_scke);
}
+
ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */
esSz = (word32)XSTRLEN(ssl->arrays->client_identity);
if (esSz > MAX_PSK_ID_LEN) {
@@ -31630,65 +33837,9 @@ int SendClientKeyExchange(WOLFSSL* ssl)
args->length = MAX_ENCRYPT_SZ;
/* Create shared ECC key leaving room at the beginning
- of buffer for size of shared key. */
+ * of buffer for size of shared key. */
ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN;
-
- #ifdef HAVE_CURVE25519
- if (ssl->ecdhCurveOID == ECC_X25519_OID) {
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X25519SharedSecretCb != NULL) {
- break;
- }
- #endif
-
- ret = wc_curve25519_export_public_ex(
- (curve25519_key*)ssl->hsKey,
- args->output + OPAQUE8_LEN, &args->length,
- EC25519_LITTLE_ENDIAN);
- if (ret != 0) {
- ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
- }
-
- break;
- }
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->ecdhCurveOID == ECC_X448_OID) {
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X448SharedSecretCb != NULL) {
- break;
- }
- #endif
-
- ret = wc_curve448_export_public_ex(
- (curve448_key*)ssl->hsKey,
- args->output + OPAQUE8_LEN, &args->length,
- EC448_LITTLE_ENDIAN);
- if (ret != 0) {
- ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
- }
-
- break;
- }
- #endif
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->EccSharedSecretCb != NULL) {
- break;
- }
- #endif
-
- /* Place ECC key in output buffer, leaving room for size */
- PRIVATE_KEY_UNLOCK();
- ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
- args->output + OPAQUE8_LEN, &args->length);
- PRIVATE_KEY_LOCK();
- if (ret != 0) {
- ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
- }
-
+ ret = EcExportHsKey(ssl, args->output, &args->length);
break;
}
#endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
@@ -31697,64 +33848,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
case ecc_diffie_hellman_kea:
{
ssl->arrays->preMasterSz = ENCRYPT_LEN;
-
- #ifdef HAVE_CURVE25519
- if (ssl->hsType == DYNAMIC_TYPE_CURVE25519) {
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X25519SharedSecretCb != NULL) {
- break;
- }
- #endif
-
- ret = wc_curve25519_export_public_ex(
- (curve25519_key*)ssl->hsKey,
- args->encSecret + OPAQUE8_LEN, &args->encSz,
- EC25519_LITTLE_ENDIAN);
- if (ret != 0) {
- ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
- }
-
- break;
- }
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->hsType == DYNAMIC_TYPE_CURVE448) {
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X448SharedSecretCb != NULL) {
- break;
- }
- #endif
-
- ret = wc_curve448_export_public_ex(
- (curve448_key*)ssl->hsKey,
- args->encSecret + OPAQUE8_LEN, &args->encSz,
- EC448_LITTLE_ENDIAN);
- if (ret != 0) {
- ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
- }
-
- break;
- }
- #endif
- #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->EccSharedSecretCb != NULL) {
- break;
- }
- #endif
-
- /* Place ECC key in buffer, leaving room for size */
- PRIVATE_KEY_UNLOCK();
- ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey,
- args->encSecret + OPAQUE8_LEN, &args->encSz);
- PRIVATE_KEY_LOCK();
- if (ret != 0) {
- ERROR_OUT(ECC_EXPORT_ERROR, exit_scke);
- }
- #endif /* HAVE_ECC */
+ ret = EcExportHsKey(ssl, args->encSecret, &args->encSz);
break;
}
#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
@@ -31777,7 +33871,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
{
switch(ssl->specs.kea)
{
- #ifndef NO_RSA
+ #if !defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)
case rsa_kea:
{
ret = RsaEnc(ssl,
@@ -31793,7 +33887,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
break;
}
- #endif /* !NO_RSA */
+ #endif /* !NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY */
#ifndef NO_DH
case diffie_hellman_kea:
{
@@ -31834,16 +33928,18 @@ int SendClientKeyExchange(WOLFSSL* ssl)
{
#ifdef HAVE_CURVE25519
if (ssl->peerX25519KeyPresent) {
- ret = X25519SharedSecret(ssl,
+ ret = X25519SharedSecret(
+ ssl,
(curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
- args->output + OPAQUE8_LEN, &args->length,
+ args->output ? args->output + OPAQUE8_LEN : NULL,
+ &args->length,
ssl->arrays->preMasterSecret + OPAQUE16_LEN,
&ssl->arrays->preMasterSz,
WOLFSSL_CLIENT_END
);
if (!ssl->specs.static_ecdh
#ifdef WOLFSSL_ASYNC_CRYPT
- && ret != WC_PENDING_E
+ && ret != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
) {
FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
@@ -31855,16 +33951,18 @@ int SendClientKeyExchange(WOLFSSL* ssl)
#endif
#ifdef HAVE_CURVE448
if (ssl->peerX448KeyPresent) {
- ret = X448SharedSecret(ssl,
+ ret = X448SharedSecret(
+ ssl,
(curve448_key*)ssl->hsKey, ssl->peerX448Key,
- args->output + OPAQUE8_LEN, &args->length,
+ args->output ? args->output + OPAQUE8_LEN : NULL,
+ &args->length,
ssl->arrays->preMasterSecret + OPAQUE16_LEN,
&ssl->arrays->preMasterSz,
WOLFSSL_CLIENT_END
);
if (!ssl->specs.static_ecdh
#ifdef WOLFSSL_ASYNC_CRYPT
- && ret != WC_PENDING_E
+ && ret != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
) {
FreeKey(ssl, DYNAMIC_TYPE_CURVE448,
@@ -31874,15 +33972,17 @@ int SendClientKeyExchange(WOLFSSL* ssl)
break;
}
#endif
- ret = EccSharedSecret(ssl,
+ ret = EccSharedSecret(
+ ssl,
(ecc_key*)ssl->hsKey, ssl->peerEccKey,
- args->output + OPAQUE8_LEN, &args->length,
+ args->output ? args->output + OPAQUE8_LEN : NULL,
+ &args->length,
ssl->arrays->preMasterSecret + OPAQUE16_LEN,
&ssl->arrays->preMasterSz,
WOLFSSL_CLIENT_END
);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret != WC_PENDING_E)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
FreeKey(ssl, DYNAMIC_TYPE_ECC,
@@ -31902,16 +34002,18 @@ int SendClientKeyExchange(WOLFSSL* ssl)
#ifdef HAVE_CURVE25519
if (ssl->peerX25519KeyPresent) {
- ret = X25519SharedSecret(ssl,
+ ret = X25519SharedSecret(
+ ssl,
(curve25519_key*)ssl->hsKey, ssl->peerX25519Key,
- args->encSecret + OPAQUE8_LEN, &args->encSz,
+ args->encSecret ? args->encSecret + OPAQUE8_LEN : NULL,
+ &args->encSz,
ssl->arrays->preMasterSecret,
&ssl->arrays->preMasterSz,
WOLFSSL_CLIENT_END
);
if (!ssl->specs.static_ecdh
#ifdef WOLFSSL_ASYNC_CRYPT
- && ret != WC_PENDING_E
+ && ret != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
) {
FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
@@ -31923,16 +34025,18 @@ int SendClientKeyExchange(WOLFSSL* ssl)
#endif
#ifdef HAVE_CURVE448
if (ssl->peerX448KeyPresent) {
- ret = X448SharedSecret(ssl,
+ ret = X448SharedSecret(
+ ssl,
(curve448_key*)ssl->hsKey, ssl->peerX448Key,
- args->encSecret + OPAQUE8_LEN, &args->encSz,
+ args->encSecret ? args->encSecret + OPAQUE8_LEN : NULL,
+ &args->encSz,
ssl->arrays->preMasterSecret,
&ssl->arrays->preMasterSz,
WOLFSSL_CLIENT_END
);
if (!ssl->specs.static_ecdh
#ifdef WOLFSSL_ASYNC_CRYPT
- && ret != WC_PENDING_E
+ && ret != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
) {
FreeKey(ssl, DYNAMIC_TYPE_CURVE448,
@@ -31946,16 +34050,18 @@ int SendClientKeyExchange(WOLFSSL* ssl)
peerKey = (ssl->specs.static_ecdh) ?
ssl->peerEccDsaKey : ssl->peerEccKey;
- ret = EccSharedSecret(ssl,
- (ecc_key*)ssl->hsKey, peerKey,
- args->encSecret + OPAQUE8_LEN, &args->encSz,
- ssl->arrays->preMasterSecret,
- &ssl->arrays->preMasterSz,
- WOLFSSL_CLIENT_END);
+ ret = EccSharedSecret(
+ ssl,
+ (ecc_key*)ssl->hsKey, peerKey,
+ args->encSecret ? args->encSecret + OPAQUE8_LEN : NULL,
+ &args->encSz,
+ ssl->arrays->preMasterSecret,
+ &ssl->arrays->preMasterSz,
+ WOLFSSL_CLIENT_END);
if (!ssl->specs.static_ecdh
#ifdef WOLFSSL_ASYNC_CRYPT
- && ret != WC_PENDING_E
+ && ret != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
&& !ssl->options.keepResources) {
FreeKey(ssl, DYNAMIC_TYPE_ECC,
@@ -32007,8 +34113,6 @@ int SendClientKeyExchange(WOLFSSL* ssl)
#if !defined(NO_DH) && !defined(NO_PSK)
case dhe_psk_kea:
{
- byte* pms = ssl->arrays->preMasterSecret;
-
/* validate args */
if (args->output == NULL || args->length == 0) {
ERROR_OUT(BAD_FUNC_ARG, exit_scke);
@@ -32016,19 +34120,8 @@ int SendClientKeyExchange(WOLFSSL* ssl)
c16toa((word16)args->length, args->output);
args->encSz += args->length + OPAQUE16_LEN;
- c16toa((word16)ssl->arrays->preMasterSz, pms);
- ssl->arrays->preMasterSz += OPAQUE16_LEN;
- pms += ssl->arrays->preMasterSz;
-
- /* make psk pre master secret */
- /* length of key + length 0s + length of key + key */
- c16toa((word16)ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
- XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz +=
- ssl->arrays->psk_keySz + OPAQUE16_LEN;
- ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->psk_keySz = 0; /* No further need */
+
+ MakePSKPreMasterSecret(ssl->arrays, 0);
break;
}
#endif /* !NO_DH && !NO_PSK */
@@ -32036,8 +34129,6 @@ int SendClientKeyExchange(WOLFSSL* ssl)
defined(HAVE_CURVE448)) && !defined(NO_PSK)
case ecdhe_psk_kea:
{
- byte* pms = ssl->arrays->preMasterSecret;
-
/* validate args */
if (args->output == NULL || args->length > ENCRYPT_LEN) {
ERROR_OUT(BAD_FUNC_ARG, exit_scke);
@@ -32048,19 +34139,8 @@ int SendClientKeyExchange(WOLFSSL* ssl)
args->encSz += args->length + OPAQUE8_LEN;
/* Create pre master secret is the concatenation of
- eccSize + eccSharedKey + pskSize + pskKey */
- c16toa((word16)ssl->arrays->preMasterSz, pms);
- ssl->arrays->preMasterSz += OPAQUE16_LEN;
- pms += ssl->arrays->preMasterSz;
-
- c16toa((word16)ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
- XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz +=
- ssl->arrays->psk_keySz + OPAQUE16_LEN;
-
- ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->psk_keySz = 0; /* No further need */
+ * eccSize + eccSharedKey + pskSize + pskKey */
+ MakePSKPreMasterSecret(ssl->arrays, 0);
break;
}
#endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) && !NO_PSK */
@@ -32111,7 +34191,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
}
idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
- args->sendSz = args->encSz + tlsSz + idx;
+ args->sendSz = (int)(args->encSz + tlsSz + idx);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
@@ -32145,8 +34225,8 @@ int SendClientKeyExchange(WOLFSSL* ssl)
if (ssl->options.dtls)
recordHeaderSz += DTLS_RECORD_EXTRA;
- args->inputSz = idx - recordHeaderSz; /* buildmsg adds rechdr */
- args->input = (byte*)XMALLOC(args->inputSz, ssl->heap,
+ args->inputSz = (int)idx - recordHeaderSz; /* buildmsg adds rechdr */
+ args->input = (byte*)XMALLOC((size_t)args->inputSz, ssl->heap,
DYNAMIC_TYPE_IN_BUFFER);
if (args->input == NULL) {
ERROR_OUT(MEMORY_E, exit_scke);
@@ -32209,12 +34289,12 @@ int SendClientKeyExchange(WOLFSSL* ssl)
}
#endif
- ssl->buffers.outputBuffer.length += args->sendSz;
+ ssl->buffers.outputBuffer.length += (word32)args->sendSz;
if (!ssl->options.groupMessages) {
ret = SendBuffered(ssl);
}
- if (ret == 0 || ret == WANT_WRITE) {
+ if (ret == 0 || ret == WC_NO_ERR_TRACE(WANT_WRITE)) {
int tmpRet = MakeMasterSecret(ssl);
if (tmpRet != 0) {
ret = tmpRet; /* save WANT_WRITE unless more serious */
@@ -32244,7 +34324,9 @@ int SendClientKeyExchange(WOLFSSL* ssl)
#ifdef WOLFSSL_ASYNC_IO
/* Handle async operation */
- if (ret == WC_PENDING_E || ret == WANT_WRITE) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) ||
+ ret == WC_NO_ERR_TRACE(WANT_WRITE))
+ {
if (ssl->options.buildingMsg)
return ret;
/* If we have completed all states then we will not enter this function
@@ -32292,7 +34374,7 @@ typedef struct ScvArgs {
word32 sigSz;
int sendSz;
int inputSz;
- word16 length;
+ word32 length;
byte sigAlgo;
} ScvArgs;
@@ -32303,15 +34385,11 @@ static void FreeScvArgs(WOLFSSL* ssl, void* pArgs)
(void)ssl;
#ifndef NO_RSA
- if (args->verifySig) {
- XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
- args->verifySig = NULL;
- }
+ XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ args->verifySig = NULL;
#endif
- if (args->input) {
- XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- args->input = NULL;
- }
+ XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ args->input = NULL;
}
/* handle generation of certificate_verify (15) */
@@ -32328,6 +34406,10 @@ int SendCertificateVerify(WOLFSSL* ssl)
WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND);
WOLFSSL_ENTER("SendCertificateVerify");
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key, ssl->buffers.keyMask);
+#endif
+
#ifdef WOLFSSL_ASYNC_IO
if (ssl->async == NULL) {
ssl->async = (struct WOLFSSL_ASYNC*)
@@ -32340,10 +34422,10 @@ int SendCertificateVerify(WOLFSSL* ssl)
args = (ScvArgs*)ssl->async->args;
#ifdef WOLFSSL_ASYNC_CRYPT
/* BuildMessage does its own Pop */
- if (ssl->error != WC_PENDING_E ||
+ if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E) ||
ssl->options.asyncState != TLS_ASYNC_END)
ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* Check for error */
if (ret < 0)
goto exit_scv;
@@ -32374,16 +34456,20 @@ int SendCertificateVerify(WOLFSSL* ssl)
case TLS_ASYNC_BEGIN:
{
if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key,
+ ssl->buffers.keyMask);
+ #endif
return 0; /* sent blank cert, can't verify */
}
- args->sendSz = MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA;
+ args->sendSz = WC_MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA;
if (IsEncryptionOn(ssl, 1)) {
args->sendSz += MAX_MSG_EXTRA;
}
/* Use tmp buffer */
- args->input = (byte*)XMALLOC(args->sendSz,
+ args->input = (byte*)XMALLOC((size_t)args->sendSz,
ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
if (args->input == NULL)
ERROR_OUT(MEMORY_E, exit_scv);
@@ -32511,7 +34597,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) {
@@ -32521,7 +34607,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 */
@@ -32615,7 +34701,8 @@ int SendCertificateVerify(WOLFSSL* ssl)
);
}
#endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
- #ifndef NO_RSA
+ #if !defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \
+ !defined(WOLFSSL_RSA_VERIFY_ONLY)
if (ssl->hsType == DYNAMIC_TYPE_RSA) {
RsaKey* key = (RsaKey*)ssl->hsKey;
@@ -32629,7 +34716,7 @@ int SendCertificateVerify(WOLFSSL* ssl)
ssl->buffers.key
);
}
- #endif /* !NO_RSA */
+ #endif /* !NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY && !WOLFSSL_RSA_VERIFY_ONLY */
/* Check for error */
if (ret != 0) {
@@ -32656,13 +34743,20 @@ int SendCertificateVerify(WOLFSSL* ssl)
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
if (ssl->buffers.keyType == sm2_sa_algo) {
+ #ifdef HAVE_PK_CALLBACKS
+ buffer tmp;
+
+ tmp.length = ssl->buffers.key->length;
+ tmp.buffer = ssl->buffers.key->buffer;
+ #endif
+
ret = Sm3wSm2Verify(ssl,
TLS12_SM2_SIG_ID, TLS12_SM2_SIG_ID_SZ,
ssl->buffers.sig.buffer, ssl->buffers.sig.length,
ssl->buffers.digest.buffer,
ssl->buffers.digest.length, key,
#ifdef HAVE_PK_CALLBACKS
- ssl->buffers.key
+ &tmp
#else
NULL
#endif
@@ -32671,12 +34765,19 @@ int SendCertificateVerify(WOLFSSL* ssl)
else
#endif
{
+ #ifdef HAVE_PK_CALLBACKS
+ buffer tmp;
+
+ tmp.length = ssl->buffers.key->length;
+ tmp.buffer = ssl->buffers.key->buffer;
+ #endif
+
ret = EccVerify(ssl,
ssl->buffers.sig.buffer, ssl->buffers.sig.length,
ssl->buffers.digest.buffer,
ssl->buffers.digest.length, key,
#ifdef HAVE_PK_CALLBACKS
- ssl->buffers.key
+ &tmp
#else
NULL
#endif
@@ -32700,7 +34801,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;
@@ -32729,7 +34830,7 @@ int SendCertificateVerify(WOLFSSL* ssl)
);
/* free temporary buffer now */
- if (ret != WC_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) {
XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
args->verifySig = NULL;
}
@@ -32778,15 +34879,24 @@ int SendCertificateVerify(WOLFSSL* ssl)
} /* switch(ssl->options.asyncState) */
exit_scv:
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ if (ret == 0) {
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key,
+ &ssl->buffers.keyMask);
+ }
+ else {
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key, ssl->buffers.keyMask);
+ }
+#endif
WOLFSSL_LEAVE("SendCertificateVerify", ret);
WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND);
#ifdef WOLFSSL_ASYNC_IO
/* Handle async operation */
- if (ret == WANT_WRITE
+ if (ret == WC_NO_ERR_TRACE(WANT_WRITE)
#ifdef WOLFSSL_ASYNC_CRYPT
- || ret == WC_PENDING_E
+ || ret == WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
)
return ret;
@@ -32920,13 +35030,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
}
- if (IsEncryptionOn(ssl, 0)) {
+ if (IsEncryptionOn(ssl, 0))
*inOutIdx += ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- *inOutIdx += MacSize(ssl);
- #endif
- }
ssl->expect_session_ticket = 0;
@@ -32937,11 +35042,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif /* HAVE_SESSION_TICKET */
-#endif /* NO_WOLFSSL_CLIENT */
+#endif /* !NO_WOLFSSL_CLIENT && !NO_TLS */
+/* end client only parts */
+
#ifndef NO_CERTS
-#ifdef WOLF_PRIVATE_KEY_ID
+#if defined(WOLF_PRIVATE_KEY_ID) || defined(HAVE_PK_CALLBACKS)
int GetPrivateKeySigSize(WOLFSSL* ssl)
{
int sigSz = 0;
@@ -32982,9 +35089,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
return sigSz;
}
-#endif /* HAVE_PK_CALLBACKS */
+#endif /* WOLF_PRIVATE_KEY_ID || HAVE_PK_CALLBACKS */
-#endif /* NO_CERTS */
+#endif /* !NO_CERTS */
#ifdef HAVE_ECC
/* returns the WOLFSSL_* version of the curve from the OID sum */
@@ -33071,37 +35178,136 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
#endif /* HAVE_ECC */
+#ifdef WOLFSSL_HAVE_MLKEM
+ /* Returns 1 when the given group is a PQC group, 0 otherwise. */
+ int NamedGroupIsPqc(int group)
+ {
+ switch (group) {
+ #ifndef WOLFSSL_NO_ML_KEM
+ case WOLFSSL_ML_KEM_512:
+ case WOLFSSL_ML_KEM_768:
+ case WOLFSSL_ML_KEM_1024:
+ #endif
+ #ifdef WOLFSSL_MLKEM_KYBER
+ case WOLFSSL_KYBER_LEVEL1:
+ case WOLFSSL_KYBER_LEVEL3:
+ case WOLFSSL_KYBER_LEVEL5:
+ #endif
+ return 1;
+ default:
+ return 0;
+ }
+ }
+
+ /* Returns 1 when the given group is a PQC hybrid group, 0 otherwise. */
+ int NamedGroupIsPqcHybrid(int group)
+ {
+ switch (group) {
+ #ifndef WOLFSSL_NO_ML_KEM
+ case WOLFSSL_SECP256R1MLKEM768:
+ case WOLFSSL_X25519MLKEM768:
+ case WOLFSSL_SECP384R1MLKEM1024:
+ case WOLFSSL_SECP256R1MLKEM512:
+ case WOLFSSL_SECP384R1MLKEM768:
+ case WOLFSSL_SECP521R1MLKEM1024:
+ case WOLFSSL_X25519MLKEM512:
+ case WOLFSSL_X448MLKEM768:
+#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS
+ case WOLFSSL_P256_ML_KEM_512_OLD:
+ case WOLFSSL_P384_ML_KEM_768_OLD:
+ case WOLFSSL_P521_ML_KEM_1024_OLD:
+#endif
+ #endif
+ #ifdef WOLFSSL_MLKEM_KYBER
+ case WOLFSSL_P256_KYBER_LEVEL3:
+ case WOLFSSL_X25519_KYBER_LEVEL3:
+ case WOLFSSL_P256_KYBER_LEVEL1:
+ case WOLFSSL_P384_KYBER_LEVEL3:
+ case WOLFSSL_P521_KYBER_LEVEL5:
+ case WOLFSSL_X25519_KYBER_LEVEL1:
+ case WOLFSSL_X448_KYBER_LEVEL3:
+ #endif
+ return 1;
+ default:
+ return 0;
+ }
+ }
+#endif /* WOLFSSL_HAVE_MLKEM */
+
int TranslateErrorToAlert(int err)
{
switch (err) {
- case BUFFER_ERROR:
+ case WC_NO_ERR_TRACE(BUFFER_ERROR):
return decode_error;
- case EXT_NOT_ALLOWED:
- case PEER_KEY_ERROR:
- case ECC_PEERKEY_ERROR:
- case BAD_KEY_SHARE_DATA:
- case PSK_KEY_ERROR:
- case INVALID_PARAMETER:
- case HRR_COOKIE_ERROR:
- case BAD_BINDER:
+ case WC_NO_ERR_TRACE(EXT_NOT_ALLOWED):
+ case WC_NO_ERR_TRACE(PEER_KEY_ERROR):
+ case WC_NO_ERR_TRACE(ECC_PEERKEY_ERROR):
+ case WC_NO_ERR_TRACE(BAD_KEY_SHARE_DATA):
+ case WC_NO_ERR_TRACE(PSK_KEY_ERROR):
+ case WC_NO_ERR_TRACE(INVALID_PARAMETER):
+ case WC_NO_ERR_TRACE(HRR_COOKIE_ERROR):
+ case WC_NO_ERR_TRACE(BAD_BINDER):
return illegal_parameter;
- case INCOMPLETE_DATA:
+ case WC_NO_ERR_TRACE(INCOMPLETE_DATA):
return missing_extension;
- case MATCH_SUITE_ERROR:
- case MISSING_HANDSHAKE_DATA:
+ case WC_NO_ERR_TRACE(MATCH_SUITE_ERROR):
+ case WC_NO_ERR_TRACE(MISSING_HANDSHAKE_DATA):
return handshake_failure;
- case VERSION_ERROR:
+ case WC_NO_ERR_TRACE(VERSION_ERROR):
return wolfssl_alert_protocol_version;
+ case WC_NO_ERR_TRACE(BAD_CERTIFICATE_STATUS_ERROR):
+ return bad_certificate_status_response;
default:
return invalid_alert;
}
}
+ /* search suites for specific one, idx on success, negative on error */
+ int FindSuite(const Suites* suites, byte first, byte second)
+ {
+ int i;
-#ifndef NO_WOLFSSL_SERVER
+ if (suites == NULL || suites->suiteSz == 0) {
+ WOLFSSL_MSG("Suites pointer error or suiteSz 0");
+ return SUITES_ERROR;
+ }
+
+ for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) {
+ if (suites->suites[i] == first &&
+ suites->suites[i+1] == second )
+ return i;
+ }
+
+ return MATCH_SUITE_ERROR;
+ }
+
+#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
#ifndef WOLFSSL_NO_TLS12
+ static int getSessionID(WOLFSSL* ssl)
+ {
+ int sessIdSz = 0;
+ (void)ssl;
+#ifndef NO_SESSION_CACHE
+ /* if no session cache don't send a session ID */
+ if (!ssl->options.sessionCacheOff)
+ sessIdSz = ID_LEN;
+#endif
+#ifdef HAVE_SESSION_TICKET
+ /* we may be echoing an ID as part of session tickets */
+ if (ssl->options.useTicket) {
+ /* echo session id sz can be 0,32 or bogus len in between */
+ sessIdSz = ssl->arrays->sessionIDSz;
+ if (sessIdSz > ID_LEN) {
+ WOLFSSL_MSG("Bad bogus session id len");
+ return BUFFER_ERROR;
+ }
+ }
+#endif /* HAVE_SESSION_TICKET */
+ return sessIdSz;
+ }
+
/* handle generation of server_hello (2) */
int SendServerHello(WOLFSSL* ssl)
{
@@ -33110,17 +35316,18 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word16 length;
word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
int sendSz;
- byte sessIdSz = ID_LEN;
- #if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SESSION_TICKET)
- byte echoId = 0; /* ticket echo id flag */
- #endif
- byte cacheOff = 0; /* session cache off flag */
+ byte sessIdSz;
WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
WOLFSSL_ENTER("SendServerHello");
+ ret = getSessionID(ssl);
+ if (ret < 0)
+ return ret;
+ sessIdSz = (byte)ret;
+
length = VERSION_SZ + RAN_LEN
- + ID_LEN + ENUM_LEN
+ + ENUM_LEN + sessIdSz
+ SUITE_LEN
+ ENUM_LEN;
@@ -33128,45 +35335,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ret = TLSX_GetResponseSize(ssl, server_hello, &length);
if (ret != 0)
return ret;
- #ifdef HAVE_SESSION_TICKET
- if (ssl->options.useTicket) {
- /* echo session id sz can be 0,32 or bogus len in between */
- sessIdSz = ssl->arrays->sessionIDSz;
- if (sessIdSz > ID_LEN) {
- WOLFSSL_MSG("Bad bogus session id len");
- return BUFFER_ERROR;
- }
- if (!IsAtLeastTLSv1_3(ssl->version))
- length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */
- echoId = 1;
- }
- #endif /* HAVE_SESSION_TICKET */
#else
if (ssl->options.haveEMS) {
length += HELLO_EXT_SZ_SZ + HELLO_EXT_SZ;
}
#endif
- /* is the session cache off at build or runtime */
-#ifdef NO_SESSION_CACHE
- cacheOff = 1;
-#else
- if (ssl->options.sessionCacheOff == 1) {
- cacheOff = 1;
- }
-#endif
-
- /* if no session cache don't send a session ID unless we're echoing
- * an ID as part of session tickets */
- if (cacheOff == 1
- #if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SESSION_TICKET)
- && echoId == 0
- #endif
- ) {
- length -= ID_LEN; /* adjust ID_LEN assumption */
- sessIdSz = 0;
- }
-
sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
@@ -33197,11 +35371,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* then random and session id */
if (!ssl->options.resuming) {
- /* generate random part and session id */
- ret = wc_RNG_GenerateBlock(ssl->rng, output + idx,
- RAN_LEN + sizeof(sessIdSz) + sessIdSz);
- if (ret != 0)
- return ret;
+ word32 genRanLen = RAN_LEN;
#ifdef WOLFSSL_TLS13
if (TLSv1_3_Capable(ssl)) {
@@ -33209,6 +35379,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
tls13Downgrade, TLS13_DOWNGRADE_SZ);
output[idx + RAN_LEN - 1] = (byte)IsAtLeastTLSv1_2(ssl);
+ genRanLen -= TLS13_DOWNGRADE_SZ + 1;
}
else
#endif
@@ -33220,12 +35391,21 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1),
tls13Downgrade, TLS13_DOWNGRADE_SZ);
output[idx + RAN_LEN - 1] = 0;
+ genRanLen -= TLS13_DOWNGRADE_SZ + 1;
}
- /* store info in SSL for later */
+ /* generate random part */
+ ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, genRanLen);
+ if (ret != 0)
+ return ret;
XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
idx += RAN_LEN;
+
+ /* generate session id */
output[idx++] = sessIdSz;
+ ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, sessIdSz);
+ if (ret != 0)
+ return ret;
XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz);
ssl->arrays->sessionIDSz = sessIdSz;
}
@@ -33283,60 +35463,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
#endif
- if (IsEncryptionOn(ssl, 1)) {
- byte* input;
- int inputSz = idx; /* build msg adds rec hdr */
- int recordHeaderSz = RECORD_HEADER_SZ;
-
- if (ssl->options.dtls)
- recordHeaderSz += DTLS_RECORD_EXTRA;
- inputSz -= recordHeaderSz;
- input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- if (input == NULL)
- return MEMORY_E;
-
- XMEMCPY(input, output + recordHeaderSz, inputSz);
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl) &&
- (ret = DtlsMsgPoolSave(ssl, input, inputSz, server_hello)) != 0) {
- XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- return ret;
- }
- #endif
- sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
- handshake, 1, 0, 0, CUR_ORDER);
- XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-
- if (sendSz < 0)
- return sendSz;
- } else {
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl)) {
- if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, server_hello)) != 0)
- return ret;
- }
- if (ssl->options.dtls)
- DtlsSEQIncrement(ssl, CUR_ORDER);
- #endif
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0)
- return ret;
- }
-
- #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
- if (ssl->hsInfoOn)
- AddPacketName(ssl, "ServerHello");
- if (ssl->toInfoOn) {
- ret = AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz,
- WRITE_PROTO, 0, ssl->heap);
- if (ret != 0)
- return ret;
- }
- #endif
+ ret = BuildMsgOrHashOutput(ssl, output, &sendSz, idx, server_hello,
+ "ServerHello");
+ if (ret != 0)
+ return ret;
ssl->options.serverState = SERVER_HELLO_COMPLETE;
- ssl->options.buildingMsg = 0;
- ssl->buffers.outputBuffer.length += sendSz;
if (ssl->options.groupMessages)
ret = 0;
@@ -33359,7 +35491,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return 0;
}
- return (byte)GetCurveByOID(key->dp->oidSum);
+ return (byte)GetCurveByOID((int)key->dp->oidSum);
}
#endif /* HAVE_ECC */
@@ -33384,7 +35516,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;
@@ -33394,19 +35526,22 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
(void)ssl;
+ if (args == NULL)
+ return;
+
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
- if (args->exportBuf) {
- XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER);
- args->exportBuf = NULL;
- }
+ XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER);
+ args->exportBuf = NULL;
#endif
#ifndef NO_RSA
- if (args->verifySig) {
- XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
- args->verifySig = NULL;
- }
+ XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
+ args->verifySig = NULL;
#endif
- (void)args;
+
+ if (args->input != NULL) {
+ XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ args->input = NULL;
+ }
}
/* handle generation of server_key_exchange (12) */
@@ -33423,6 +35558,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
WOLFSSL_ENTER("SendServerKeyExchange");
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key, ssl->buffers.keyMask);
+ #endif
+
#ifdef WOLFSSL_ASYNC_IO
if (ssl->async == NULL) {
ssl->async = (struct WOLFSSL_ASYNC*)
@@ -33435,7 +35574,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
args = (SskeArgs*)ssl->async->args;
#ifdef WOLFSSL_ASYNC_CRYPT
ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* Check for error */
if (ret < 0)
goto exit_sske;
@@ -33520,7 +35659,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_sske;
if (ssl->buffers.serverDH_Pub.buffer == NULL) {
- /* Free'd in SSL_ResourceFree and
+ /* Free'd in wolfSSL_ResourceFree and
* FreeHandshakeResources */
ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
@@ -33534,7 +35673,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
pSz = wc_DhGetNamedKeyMinSize(ssl->namedGroup);
if (ssl->buffers.serverDH_Priv.buffer == NULL) {
- /* Free'd in SSL_ResourceFree and
+ /* Free'd in wolfSSL_ResourceFree and
* FreeHandshakeResources */
ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
pSz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
@@ -33603,7 +35742,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
if (ssl->buffers.serverDH_Pub.buffer == NULL) {
- /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
+ /* Free'd in wolfSSL_ResourceFree
+ * and FreeHandshakeResources
+ */
ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(
ssl->buffers.serverDH_P.length,
ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
@@ -33615,7 +35756,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
if (ssl->buffers.serverDH_Priv.buffer == NULL) {
- /* Free'd in SSL_ResourceFree and FreeHandshakeResources */
+ /* Free'd in wolfSSL_ResourceFree
+ * and FreeHandshakeResources
+ */
ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC(
ssl->buffers.serverDH_P.length,
ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
@@ -33725,7 +35868,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ssl->eccTempKeyPresent == 0) {
ret = X25519MakeKey(ssl,
(curve25519_key*)ssl->eccTempKey, NULL);
- if (ret == 0 || ret == WC_PENDING_E) {
+ if (ret == 0 ||
+ ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ssl->eccTempKeyPresent =
DYNAMIC_TYPE_CURVE25519;
}
@@ -33752,7 +35896,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ssl->eccTempKeyPresent == 0) {
ret = X448MakeKey(ssl,
(curve448_key*)ssl->eccTempKey, NULL);
- if (ret == 0 || ret == WC_PENDING_E) {
+ if (ret == 0 ||
+ ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ssl->eccTempKeyPresent =
DYNAMIC_TYPE_CURVE448;
}
@@ -33777,7 +35922,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ssl->eccTempKeyPresent == 0) {
ret = EccMakeKey(ssl, ssl->eccTempKey, NULL);
- if (ret == 0 || ret == WC_PENDING_E) {
+ if (ret == 0 ||
+ ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ssl->eccTempKeyPresent = DYNAMIC_TYPE_ECC;
}
}
@@ -34101,7 +36247,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ssl->buffers.key == NULL) {
#ifdef HAVE_PK_CALLBACKS
if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) {
- args->tmpSigSz = GetPrivateKeySigSize(ssl);
+ args->tmpSigSz = (word32)GetPrivateKeySigSize(ssl);
if (args->tmpSigSz == 0) {
ERROR_OUT(NO_PRIVATE_KEY, exit_sske);
}
@@ -34118,7 +36264,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);
@@ -34136,9 +36282,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
case ecc_dsa_sa_algo:
{
- word16 keySz;
+ word32 keySz;
- ssl->buffers.keyType = ecc_dsa_sa_algo;
+ ssl->buffers.keyType = ssl->options.sigAlgo;
ret = DecodePrivateKey(ssl, &keySz);
if (ret != 0) {
goto exit_sske;
@@ -34151,7 +36297,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);
@@ -34167,7 +36313,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);
@@ -34370,7 +36516,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;
@@ -34587,7 +36733,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* Sign hash to create signature */
switch (ssl->options.sigAlgo)
{
- #ifndef NO_RSA
+ #if !defined(NO_RSA) && \
+ !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \
+ !defined(WOLFSSL_RSA_VERIFY_ONLY)
#ifdef WC_RSA_PSS
case rsa_pss_sa_algo:
#endif
@@ -34606,7 +36754,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
);
break;
}
- #endif /* !NO_RSA */
+ #endif /* !NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY
+ && !WOLFSSL_RSA_VERIFY_ONLY */
#ifdef HAVE_ECC
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
case sm2_sa_algo:
@@ -34700,7 +36849,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* Sign hash to create signature */
switch (ssl->options.sigAlgo)
{
- #ifndef NO_RSA
+ #if !defined(NO_RSA) && \
+ !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \
+ !defined(WOLFSSL_RSA_VERIFY_ONLY)
#ifdef WC_RSA_PSS
case rsa_pss_sa_algo:
#endif
@@ -34723,7 +36874,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
);
break;
}
- #endif /* NO_RSA */
+ #endif /* !NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY
+ && !WOLFSSL_RSA_VERIFY_ONLY */
default:
break;
} /* switch (ssl->options.sigAlgo) */
@@ -34837,6 +36989,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
else
#endif /* WOLFSSL_SM2 */
{
+ #ifdef HAVE_PK_CALLBACKS
+ buffer tmp;
+
+ tmp.length = ssl->buffers.key->length;
+ tmp.buffer = ssl->buffers.key->buffer;
+ #endif
+
ret = EccVerify(ssl,
args->output + LENGTH_SZ + args->idx,
args->sigSz,
@@ -34844,7 +37003,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ssl->buffers.digest.length,
key,
#ifdef HAVE_PK_CALLBACKS
- ssl->buffers.key
+ &tmp
#else
NULL
#endif
@@ -34856,7 +37015,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_sske;
}
}
- #if defined(HAVE_E25519) || defined(HAVE_ED448)
+ #if defined(HAVE_ED25519) || defined(HAVE_ED448)
FALL_THROUGH;
#endif
#endif /* WOLFSSL_CHECK_SIG_FAULTS */
@@ -34979,14 +37138,25 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
exit_sske:
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ if (ret == 0) {
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key,
+ &ssl->buffers.keyMask);
+ }
+ else {
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key,
+ ssl->buffers.keyMask);
+ }
+ #endif
+
WOLFSSL_LEAVE("SendServerKeyExchange", ret);
WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND);
#ifdef WOLFSSL_ASYNC_IO
/* Handle async operation */
- if (ret == WANT_WRITE
+ if (ret == WC_NO_ERR_TRACE(WANT_WRITE)
#ifdef WOLFSSL_ASYNC_CRYPT
- || ret == WC_PENDING_E
+ || ret == WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
)
return ret;
@@ -35016,31 +37186,38 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return ret;
}
-#if defined(HAVE_SERVER_RENEGOTIATION_INFO) || defined(HAVE_FALLBACK_SCSV) || \
- defined(OPENSSL_ALL)
+#endif /* !WOLFSSL_NO_TLS12 */
- /* search suites for specific one, idx on success, negative on error */
- static int FindSuite(Suites* suites, byte first, byte second)
+#ifdef WOLFSSL_TLS13
+ /* Check if a cipher suite is a TLS 1.3 cipher suite
+ * Returns 1 if TLS 1.3 cipher suite, 0 otherwise
+ */
+ static WC_INLINE int IsTls13CipherSuite(byte first, byte second)
{
- int i;
+ (void)second; /* Suppress unused parameter warning */
- if (suites == NULL || suites->suiteSz == 0) {
- WOLFSSL_MSG("Suites pointer error or suiteSz 0");
- return SUITES_ERROR;
- }
-
- for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) {
- if (suites->suites[i] == first &&
- suites->suites[i+1] == second )
- return i;
- }
+ /* TLS 1.3 cipher suites use TLS13_BYTE (0x13) as first byte */
+ if (first == TLS13_BYTE)
+ return 1;
- return MATCH_SUITE_ERROR;
- }
+#ifdef HAVE_NULL_CIPHER
+ /* Special cases for integrity-only cipher suites */
+ if (first == ECC_BYTE && (second == TLS_SHA256_SHA256 ||
+ second == TLS_SHA384_SHA384))
+ return 1;
+#endif
+#if (defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)) && \
+ defined(WOLFSSL_SM3)
+ /* SM4 cipher suites for TLS 1.3 */
+ if (first == CIPHER_BYTE && (second == TLS_SM4_GCM_SM3 ||
+ second == TLS_SM4_CCM_SM3))
+ return 1;
#endif
-#endif /* !WOLFSSL_NO_TLS12 */
+ return 0;
+ }
+#endif /* WOLFSSL_TLS13 */
/* Make sure server cert/key are valid for this suite, true on success
* Returns 1 for valid server suite or 0 if not found
@@ -35068,6 +37245,17 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
first = suites->suites[idx];
second = suites->suites[idx+1];
+#ifdef WOLFSSL_TLS13
+ /* When negotiating TLS 1.3, reject non-TLS 1.3 cipher suites */
+ if (IsAtLeastTLSv1_3(ssl->version) &&
+ ssl->options.side == WOLFSSL_SERVER_END) {
+ if (!IsTls13CipherSuite(first, second)) {
+ WOLFSSL_MSG("TLS 1.2 cipher suite not valid for TLS 1.3");
+ return 0;
+ }
+ }
+#endif /* WOLFSSL_TLS13 */
+
if (CipherRequires(first, second, REQUIRES_RSA)) {
WOLFSSL_MSG("Requires RSA");
if (ssl->options.haveRSA == 0) {
@@ -35149,7 +37337,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
int ret = TLSX_KeyShare_Choose(ssl, extensions, first, second,
&cs->clientKSE, &searched);
- if (ret == MEMORY_E) {
+ if (ret == WC_NO_ERR_TRACE(MEMORY_E)) {
WOLFSSL_MSG("TLSX_KeyShare_Choose() failed in "
"VerifyServerSuite() with MEMORY_E");
return 0;
@@ -35164,7 +37352,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
cs->doHelloRetry = 1;
}
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
#endif
if (!cs->doHelloRetry && ret != 0)
@@ -35185,6 +37373,74 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return 1;
}
+ void refineSuites(const Suites* sslSuites, const Suites* peerSuites,
+ Suites* outSuites, byte useClientOrder)
+ {
+ byte suites[WOLFSSL_MAX_SUITE_SZ];
+ word16 suiteSz = 0;
+ word16 i;
+ word16 j;
+
+ XMEMSET(suites, 0, sizeof(suites));
+
+ if (!useClientOrder) {
+ /* Server order refining. */
+ for (i = 0; i < sslSuites->suiteSz; i += 2) {
+ for (j = 0; j < peerSuites->suiteSz; j += 2) {
+ if ((sslSuites->suites[i+0] == peerSuites->suites[j+0]) &&
+ (sslSuites->suites[i+1] == peerSuites->suites[j+1])) {
+ suites[suiteSz++] = peerSuites->suites[j+0];
+ suites[suiteSz++] = peerSuites->suites[j+1];
+ break;
+ }
+ }
+ if (suiteSz == WOLFSSL_MAX_SUITE_SZ)
+ break;
+ }
+ }
+ else {
+ /* Client order refining. */
+ for (j = 0; j < peerSuites->suiteSz; j += 2) {
+ for (i = 0; i < sslSuites->suiteSz; i += 2) {
+ if ((sslSuites->suites[i+0] == peerSuites->suites[j+0]) &&
+ (sslSuites->suites[i+1] == peerSuites->suites[j+1])) {
+ suites[suiteSz++] = peerSuites->suites[j+0];
+ suites[suiteSz++] = peerSuites->suites[j+1];
+ break;
+ }
+ }
+ if (suiteSz == WOLFSSL_MAX_SUITE_SZ)
+ break;
+ }
+ }
+
+ outSuites->suiteSz = suiteSz;
+ XMEMCPY(outSuites->suites, &suites, sizeof(suites));
+ #ifdef WOLFSSL_DEBUG_TLS
+ {
+ word16 ii;
+ WOLFSSL_MSG("Refined Ciphers:");
+ for (ii = 0 ; ii < outSuites->suiteSz; ii += 2) {
+ WOLFSSL_MSG(GetCipherNameInternal(outSuites->suites[ii+0],
+ outSuites->suites[ii+1]));
+ }
+ }
+ #endif
+ }
+
+ /* Refine list of supported cipher suites to those common to server and client.
+ *
+ * ssl SSL/TLS object.
+ * peerSuites The peer's advertised list of supported cipher suites.
+ */
+ void sslRefineSuites(WOLFSSL* ssl, Suites* peerSuites)
+ {
+ if (AllocateSuites(ssl) != 0)
+ return;
+ refineSuites(ssl->suites, peerSuites, ssl->suites,
+ (byte)ssl->options.useClientOrder);
+ }
+
static int CompareSuites(const WOLFSSL* ssl, const Suites* suites,
Suites* peerSuites, word16 i, word16 j,
CipherSuite* cs, TLSX* extensions)
@@ -35231,7 +37487,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
for (i = 0; i < suites->suiteSz; i += 2) {
for (j = 0; j < peerSuites->suiteSz; j += 2) {
ret = CompareSuites(ssl, suites, peerSuites, i, j, cs, extensions);
- if (ret != MATCH_SUITE_ERROR)
+ if (ret != WC_NO_ERR_TRACE(MATCH_SUITE_ERROR))
return ret;
}
}
@@ -35241,7 +37497,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
for (j = 0; j < peerSuites->suiteSz; j += 2) {
for (i = 0; i < suites->suiteSz; i += 2) {
ret = CompareSuites(ssl, suites, peerSuites, i, j, cs, extensions);
- if (ret != MATCH_SUITE_ERROR)
+ if (ret != WC_NO_ERR_TRACE(MATCH_SUITE_ERROR))
return ret;
}
}
@@ -35280,7 +37536,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ret != 0)
return ret;
ret = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo,
- peerSuites->hashSigAlgoSz);
+ peerSuites->hashSigAlgoSz, 1);
if (ret != 0)
return ret;
@@ -35403,9 +37659,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
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);
+ ssl->options.useAnon,
+ TRUE, TRUE, TRUE, TRUE, ssl->options.side);
}
/* suite size */
@@ -35463,7 +37718,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ssl->options.usingCompression = 0; /* turn off */
ssl->options.clientState = CLIENT_HELLO_COMPLETE;
- ssl->cbmode = SSL_CB_MODE_WRITE;
+ ssl->cbmode = WOLFSSL_CB_MODE_WRITE;
*inOutIdx = idx;
ssl->options.haveSessionId = 1;
@@ -35532,6 +37787,47 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
{
int ret = 0;
WOLFSSL_SESSION* session;
+
+#ifdef HAVE_SECRET_CALLBACK
+ if (ssl->sessionSecretCb != NULL
+#ifdef HAVE_SESSION_TICKET
+ && ssl->session->ticketLen > 0
+#endif
+ ) {
+ int secretSz = SECRET_LEN;
+ WOLFSSL_MSG("Calling session secret callback");
+ ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
+ RAN_LEN);
+ if (ret == 0) {
+ ret = ssl->sessionSecretCb(ssl, ssl->arrays->masterSecret,
+ &secretSz, ssl->sessionSecretCtx);
+ if (secretSz != SECRET_LEN)
+ ret = SESSION_SECRET_CB_E;
+ }
+ if (ret == 0)
+ ret = MatchSuite(ssl, clSuites);
+ if (ret == 0) {
+ #ifdef NO_OLD_TLS
+ ret = DeriveTlsKeys(ssl);
+ #else
+ #ifndef NO_TLS
+ if (ssl->options.tls)
+ ret = DeriveTlsKeys(ssl);
+ #endif
+ if (!ssl->options.tls)
+ ret = DeriveKeys(ssl);
+ #endif
+ /* SERVER: peer auth based on session secret. */
+ ssl->options.peerAuthGood = (ret == 0);
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ }
+ if (ret != 0)
+ WOLFSSL_ERROR_VERBOSE(ret);
+ WOLFSSL_LEAVE("HandleTlsResumption", ret);
+ return ret;
+ }
+#endif /* HAVE_SECRET_CALLBACK */
+
#ifdef HAVE_SESSION_TICKET
if (ssl->options.useTicket == 1) {
session = ssl->session;
@@ -35602,7 +37898,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ret = SetCipherSpecs(ssl);
if (ret == 0) {
ret = PickHashSigAlgo(ssl, clSuites->hashSigAlgo,
- clSuites->hashSigAlgoSz);
+ clSuites->hashSigAlgoSz, 0);
}
}
else if (ret == 0) {
@@ -35637,18 +37933,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return ret;
}
-
/* handle processing of client_hello (1) */
int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32 helloSz)
{
byte b;
ProtocolVersion pv;
-#ifdef WOLFSSL_SMALL_STACK
- Suites* clSuites = NULL;
-#else
- Suites clSuites[1];
-#endif
word32 i = *inOutIdx;
word32 begin = i;
int ret = 0;
@@ -35678,7 +37968,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* propagate socket errors to avoid re-calling send alert */
err = SendAlert(ssl, alert_fatal, alertType);
- if (err == SOCKET_ERROR_E)
+ if (err == WC_NO_ERR_TRACE(SOCKET_ERROR_E))
ret = SOCKET_ERROR_E;
}
*inOutIdx += helloSz;
@@ -35716,8 +38006,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR)
pv.minor = TLSv1_2_MINOR;
- lesserVersion = !ssl->options.dtls && ssl->version.minor > pv.minor;
- lesserVersion |= ssl->options.dtls && ssl->version.minor < pv.minor;
+ lesserVersion = (byte)(!ssl->options.dtls &&
+ ssl->version.minor > pv.minor);
+ lesserVersion |= ssl->options.dtls &&ssl->version.minor < pv.minor;
if (lesserVersion) {
byte belowMinDowngrade;
@@ -35794,9 +38085,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
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);
+ ssl->options.useAnon,
+ TRUE, TRUE, TRUE, TRUE, ssl->options.side);
}
/* check if option is set to not allow the current version
@@ -35872,9 +38162,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
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);
+ ssl->options.useAnon,
+ TRUE, TRUE, TRUE, TRUE, ssl->options.side);
}
}
@@ -35948,46 +38237,50 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto out;
}
-#ifdef WOLFSSL_SMALL_STACK
- clSuites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
+ XFREE(ssl->clSuites, ssl->heap, DYNAMIC_TYPE_SUITES);
+ ssl->clSuites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap,
DYNAMIC_TYPE_SUITES);
- if (clSuites == NULL) {
+ if (ssl->clSuites == NULL) {
ret = MEMORY_E;
goto out;
}
-#endif
- XMEMSET(clSuites, 0, sizeof(Suites));
- ato16(&input[i], &clSuites->suiteSz);
+ XMEMSET(ssl->clSuites, 0, sizeof(Suites));
+ ato16(&input[i], &ssl->clSuites->suiteSz);
i += OPAQUE16_LEN;
/* Cipher suite lists are always multiples of two in length. */
- if (clSuites->suiteSz % 2 != 0) {
+ if (ssl->clSuites->suiteSz % 2 != 0) {
ret = BUFFER_ERROR;
goto out;
}
/* suites and compression length check */
- if ((i - begin) + clSuites->suiteSz + OPAQUE8_LEN > helloSz) {
+ if ((i - begin) + ssl->clSuites->suiteSz + OPAQUE8_LEN > helloSz) {
ret = BUFFER_ERROR;
goto out;
}
- if (clSuites->suiteSz > WOLFSSL_MAX_SUITE_SZ) {
+ if (ssl->clSuites->suiteSz > WOLFSSL_MAX_SUITE_SZ) {
ret = BUFFER_ERROR;
goto out;
}
- XMEMCPY(clSuites->suites, input + i, clSuites->suiteSz);
+ XMEMCPY(ssl->clSuites->suites, input + i, ssl->clSuites->suiteSz);
#ifdef HAVE_SERVER_RENEGOTIATION_INFO
/* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
- if (FindSuite(clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) {
+ if (FindSuite(ssl->clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >=
+ 0) {
TLSX* extension;
/* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */
ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
+ if (ret != WOLFSSL_SUCCESS) {
+ ret = SECURE_RENEGOTIATION_E;
goto out;
+ } else {
+ ret = 0;
+ }
extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
if (extension) {
@@ -35999,7 +38292,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
#if defined(HAVE_FALLBACK_SCSV) || defined(OPENSSL_ALL)
/* check for TLS_FALLBACK_SCSV suite */
- if (FindSuite(clSuites, TLS_FALLBACK_SCSV, 0) >= 0) {
+ if (FindSuite(ssl->clSuites, TLS_FALLBACK_SCSV, 0) >= 0) {
WOLFSSL_MSG("Found Fallback SCSV");
if (ssl->ctx->method->version.minor > pv.minor) {
WOLFSSL_MSG("Client trying to connect with lesser version");
@@ -36010,8 +38303,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
#endif
- i += clSuites->suiteSz;
- clSuites->hashSigAlgoSz = 0;
+ i += ssl->clSuites->suiteSz;
+ ssl->clSuites->hashSigAlgoSz = 0;
/* compression length */
b = input[i++];
@@ -36080,6 +38373,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* auto populate extensions supported unless user defined */
if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
goto out;
+#else
+ word32 extensions_seen = 0U;
#endif
if ((i - begin) + OPAQUE16_LEN > helloSz) {
@@ -36098,7 +38393,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#ifdef HAVE_TLS_EXTENSIONS
/* tls extensions */
if ((ret = TLSX_Parse(ssl, input + i, totalExtSz, client_hello,
- clSuites)))
+ ssl->clSuites)))
goto out;
#ifdef WOLFSSL_TLS13
if (TLSX_Find(ssl->extensions,
@@ -36133,6 +38428,17 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ato16(&input[i], &extSz);
i += OPAQUE16_LEN;
+ if (extId < (word16)(sizeof(extensions_seen) * 8U)) {
+ word32 mask = 1U << extId;
+ if ((extensions_seen & mask) != 0U) {
+ WOLFSSL_MSG(
+ "DoClientHello: duplicate extension found");
+ ret = DUPLICATE_TLS_EXT_E;
+ goto out;
+ }
+ extensions_seen |= mask;
+ }
+
if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz) {
ret = BUFFER_ERROR;
goto out;
@@ -36154,15 +38460,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto out;
}
- clSuites->hashSigAlgoSz = hashSigAlgoSz;
- if (clSuites->hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
+ ssl->clSuites->hashSigAlgoSz = hashSigAlgoSz;
+ if (ssl->clSuites->hashSigAlgoSz >
+ WOLFSSL_MAX_SIGALGO) {
WOLFSSL_MSG("ClientHello SigAlgo list exceeds max, "
"truncating");
- clSuites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
+ ssl->clSuites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
}
- XMEMCPY(clSuites->hashSigAlgo, &input[i],
- clSuites->hashSigAlgoSz);
+ XMEMCPY(ssl->clSuites->hashSigAlgo, &input[i],
+ ssl->clSuites->hashSigAlgoSz);
i += hashSigAlgoSz;
}
@@ -36173,7 +38480,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
else
i += extSz;
- totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz;
+ totalExtSz -= (word16)(OPAQUE16_LEN + OPAQUE16_LEN) + extSz;
}
#endif
*inOutIdx = i;
@@ -36191,8 +38498,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ssl->options.haveSessionId = 1;
/* ProcessOld uses same resume code */
+ WOLFSSL_MSG_EX("ssl->options.resuming %d", ssl->options.resuming);
if (ssl->options.resuming) {
- ret = HandleTlsResumption(ssl, clSuites);
+ ret = HandleTlsResumption(ssl, ssl->clSuites);
if (ret != 0)
goto out;
@@ -36227,20 +38535,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
#endif
-#ifdef OPENSSL_EXTRA
- ssl->clSuites = clSuites; /* cppcheck-suppress autoVariables
- *
- * (suppress warning that ssl, a persistent
- * non-local allocation, has its ->clSuites
- * set to clSuites, a local stack allocation.
- * we clear this assignment before returning.)
- */
+#ifdef WOLFSSL_CERT_SETUP_CB
/* Give user last chance to provide a cert for cipher selection */
if (ret == 0 && ssl->ctx->certSetupCb != NULL)
ret = CertSetupCbWrapper(ssl);
#endif
if (ret == 0)
- ret = MatchSuite(ssl, clSuites);
+ ret = MatchSuite(ssl, ssl->clSuites);
#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_ENCRYPT_THEN_MAC) && \
!defined(WOLFSSL_AEAD_ONLY)
@@ -36258,12 +38559,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
out:
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+#if !defined(OPENSSL_EXTRA)
+ XFREE(ssl->clSuites, ssl->heap, DYNAMIC_TYPE_SUITES);
ssl->clSuites = NULL;
-#endif
-#ifdef WOLFSSL_SMALL_STACK
- if (clSuites != NULL)
- XFREE(clSuites, ssl->heap, DYNAMIC_TYPE_SUITES);
#endif
WOLFSSL_LEAVE("DoClientHello", ret);
WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO);
@@ -36322,7 +38620,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
args = (DcvArgs*)ssl->async->args;
ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* Check for error */
if (ret < 0)
goto exit_dcv;
@@ -36362,58 +38660,86 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
case TLS_ASYNC_BUILD:
{
if (IsAtLeastTLSv1_2(ssl)) {
- if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) {
+ if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN >
+ size) {
ERROR_OUT(BUFFER_ERROR, exit_dcv);
}
+ /* Check if hashSigAlgo in CertificateVerify is supported
+ * in our ssl->suites or ssl->ctx->suites. */
+ if (!SupportedHashSigAlgo(ssl, &input[args->idx])) {
+ WOLFSSL_MSG("Signature algorithm was not in "
+ "CertificateRequest");
+ ERROR_OUT(INVALID_PARAMETER, exit_dcv);
+ }
+
DecodeSigAlg(&input[args->idx], &ssl->options.peerHashAlgo,
&ssl->options.peerSigAlgo);
args->idx += 2;
- }
- #ifndef NO_RSA
- else if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0)
- ssl->options.peerSigAlgo = rsa_sa_algo;
- #endif
- #ifdef HAVE_ECC
- else if (ssl->peerEccDsaKeyPresent) {
- #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
- if (ssl->peerEccDsaKey->dp->id == ECC_SM2P256V1) {
- ssl->options.peerSigAlgo = sm2_sa_algo;
+
+ #ifndef NO_RSA
+ if (ssl->peerRsaKeyPresent) {
+ if (ssl->options.peerSigAlgo != rsa_sa_algo
+ #ifdef WC_RSA_PSS
+ && ssl->options.peerSigAlgo != rsa_pss_sa_algo
+ #endif
+ ) {
+ WOLFSSL_MSG("Oops, peer sent RSA key but not in "
+ "verify");
+ ERROR_OUT(INVALID_PARAMETER, exit_dcv);
+ }
}
else
#endif
+ #ifdef HAVE_ECC
+ if (ssl->peerEccDsaKeyPresent) {
+ if (ssl->options.peerSigAlgo != ecc_dsa_sa_algo
+ #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+ && ssl->options.peerSigAlgo != sm2_sa_algo
+ #endif
+ ) {
+ WOLFSSL_MSG("Oops, peer sent ECC key but not in "
+ "verify");
+ ERROR_OUT(INVALID_PARAMETER, exit_dcv);
+ }
+ #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+ if (ssl->options.peerSigAlgo == sm2_sa_algo &&
+ ssl->options.peerHashAlgo != sm3_mac) {
+ WOLFSSL_MSG("SM2 with SM3 only");
+ ERROR_OUT(INVALID_PARAMETER, exit_dcv);
+ }
+ #endif
+ }
+ else
+ #endif
+ #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+ if (ssl->peerEd25519KeyPresent) {
+ if (ssl->options.peerSigAlgo != ed25519_sa_algo) {
+ WOLFSSL_MSG("Oops, peer sent Ed25519 key but not "
+ "in verify");
+ ERROR_OUT(INVALID_PARAMETER, exit_dcv);
+ }
+ }
+ else
+ #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+ #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+ if (ssl->peerEd448KeyPresent) {
+ if (ssl->options.peerSigAlgo != ed448_sa_algo) {
+ WOLFSSL_MSG("Oops, peer sent Ed448 key but not in "
+ "verify");
+ ERROR_OUT(INVALID_PARAMETER, exit_dcv);
+ }
+ }
+ else
+ #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
{
- ssl->options.peerSigAlgo = ecc_dsa_sa_algo;
+ ERROR_OUT(INVALID_PARAMETER, exit_dcv);
}
- }
- #endif
- #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
- else if (ssl->peerEd25519KeyPresent)
- ssl->options.peerSigAlgo = ed25519_sa_algo;
- #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
- #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
- else if (ssl->peerEd448KeyPresent)
- ssl->options.peerSigAlgo = ed448_sa_algo;
- #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
- if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dcv);
+ SetDigest(ssl, ssl->options.peerHashAlgo);
}
-
- ato16(input + args->idx, &args->sz);
- args->idx += OPAQUE16_LEN;
-
- if ((args->idx - args->begin) + args->sz > size ||
- args->sz > ENCRYPT_LEN) {
- ERROR_OUT(BUFFER_ERROR, exit_dcv);
- }
-
- #ifdef HAVE_ECC
- if (ssl->peerEccDsaKeyPresent) {
-
- WOLFSSL_MSG("Doing ECC peer cert verify");
-
- /* make sure a default is defined */
+ else {
+ /* make sure a default is defined */
#if !defined(NO_SHA)
SetDigest(ssl, sha_mac);
#elif !defined(NO_SHA256)
@@ -36428,39 +38754,51 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#error No digest enabled for ECC sig verify
#endif
- if (IsAtLeastTLSv1_2(ssl)) {
- if (ssl->options.peerSigAlgo != ecc_dsa_sa_algo
- #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
- && ssl->options.peerSigAlgo != sm2_sa_algo
- #endif
- ) {
- WOLFSSL_MSG("Oops, peer sent ECC key but not in verify");
+ #ifndef NO_RSA
+ if (ssl->peerRsaKeyPresent)
+ ssl->options.peerSigAlgo = rsa_sa_algo;
+ else
+ #endif
+ #ifdef HAVE_ECC
+ if (ssl->peerEccDsaKeyPresent) {
+ #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+ if (ssl->peerEccDsaKey->dp->id == ECC_SM2P256V1) {
+ ssl->options.peerSigAlgo = sm2_sa_algo;
+ }
+ else
+ #endif
+ {
+ ssl->options.peerSigAlgo = ecc_dsa_sa_algo;
}
-
- SetDigest(ssl, ssl->options.peerHashAlgo);
}
- }
- #endif /* HAVE_ECC */
- #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
- if (ssl->peerEd25519KeyPresent) {
- WOLFSSL_MSG("Doing ED25519 peer cert verify");
- if (IsAtLeastTLSv1_2(ssl) &&
- ssl->options.peerSigAlgo != ed25519_sa_algo) {
- WOLFSSL_MSG(
- "Oops, peer sent ED25519 key but not in verify");
+ else
+ #endif
+ #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)
+ if (ssl->peerEd25519KeyPresent)
+ ssl->options.peerSigAlgo = ed25519_sa_algo;
+ else
+ #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
+ #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
+ if (ssl->peerEd448KeyPresent)
+ ssl->options.peerSigAlgo = ed448_sa_algo;
+ else
+ #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
+ {
+ ERROR_OUT(NO_PEER_KEY, exit_dcv);
}
}
- #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */
- #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)
- if (ssl->peerEd448KeyPresent) {
- WOLFSSL_MSG("Doing ED448 peer cert verify");
- if (IsAtLeastTLSv1_2(ssl) &&
- ssl->options.peerSigAlgo != ed448_sa_algo) {
- WOLFSSL_MSG(
- "Oops, peer sent ED448 key but not in verify");
- }
+
+ if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcv);
+ }
+
+ ato16(input + args->idx, &args->sz);
+ args->idx += OPAQUE16_LEN;
+
+ if ((args->idx - args->begin) + args->sz > size ||
+ args->sz > ENCRYPT_LEN) {
+ ERROR_OUT(BUFFER_ERROR, exit_dcv);
}
- #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */
/* Advance state and proceed */
ssl->options.asyncState = TLS_ASYNC_DO;
@@ -36487,9 +38825,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
);
if (ret >= 0) {
if (ssl->options.peerSigAlgo == rsa_sa_algo)
- args->sendSz = ret;
+ args->sendSz = (word32)ret;
else {
- args->sigSz = ret;
+ args->sigSz = (word32)ret;
args->sendSz = ssl->buffers.digest.length;
}
ret = 0;
@@ -36575,7 +38913,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#ifdef WOLFSSL_ASYNC_CRYPT
/* handle async pending */
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
goto exit_dcv;
#endif
@@ -36597,8 +38935,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (IsAtLeastTLSv1_2(ssl)) {
#ifdef WC_RSA_PSS
if (ssl->options.peerSigAlgo == rsa_pss_sa_algo) {
- SetDigest(ssl, ssl->options.peerHashAlgo);
-
#ifdef HAVE_SELFTEST
ret = wc_RsaPSS_CheckPadding(
ssl->buffers.digest.buffer,
@@ -36631,12 +38967,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
#endif
- if (ssl->options.peerSigAlgo != rsa_sa_algo) {
- WOLFSSL_MSG("Oops, peer sent RSA key but not "
- "in verify");
- }
-
- SetDigest(ssl, ssl->options.peerHashAlgo);
args->sigSz = wc_EncodeSignature(encodedSig,
ssl->buffers.digest.buffer,
@@ -36649,10 +38979,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ret = VERIFY_CERT_ERROR;
}
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(encodedSig, ssl->heap,
- DYNAMIC_TYPE_SIGNATURE);
- #endif
+ WC_FREE_VAR_EX(encodedSig, ssl->heap,
+ DYNAMIC_TYPE_SIGNATURE);
}
}
else {
@@ -36679,13 +39007,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
case TLS_ASYNC_FINALIZE:
{
- if (IsEncryptionOn(ssl, 0)) {
+ if (IsEncryptionOn(ssl, 0))
args->idx += ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- args->idx += MacSize(ssl);
- #endif
- }
ssl->options.havePeerVerify = 1;
@@ -36713,7 +39036,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#ifdef WOLFSSL_ASYNC_CRYPT
/* Handle async operation */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* Mark message as not received so it can process again */
ssl->msgsReceived.got_certificate_verify = 0;
@@ -36721,9 +39044,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
#endif /* WOLFSSL_ASYNC_CRYPT */
#ifdef WOLFSSL_EXTRA_ALERTS
- if (ret == BUFFER_ERROR)
+ if (ret == WC_NO_ERR_TRACE(BUFFER_ERROR))
SendAlert(ssl, alert_fatal, decode_error);
- else if (ret == SIG_VERIFY_E)
+ else if (ret == WC_NO_ERR_TRACE(SIG_VERIFY_E))
SendAlert(ssl, alert_fatal, decrypt_error);
else if (ret != 0)
SendAlert(ssl, alert_fatal, bad_certificate);
@@ -36787,63 +39110,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* get output buffer */
output = GetOutputBuffer(ssl);
AddHeaders(output, 0, server_hello_done, ssl);
+ ret = BuildMsgOrHashOutput(ssl, output, &sendSz,
+ HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ +
+ (ssl->options.dtls ?
+ DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA : 0),
+ server_hello_done, "ServerHelloDone");
+ if (ret != 0)
+ return ret;
- if (IsEncryptionOn(ssl, 1)) {
- byte* input;
- int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */
- int recordHeaderSz = RECORD_HEADER_SZ;
-
- if (ssl->options.dtls) {
- recordHeaderSz += DTLS_RECORD_EXTRA;
- inputSz += DTLS_HANDSHAKE_EXTRA;
- }
-
- input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- if (input == NULL)
- return MEMORY_E;
-
- XMEMCPY(input, output + recordHeaderSz, inputSz);
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl) &&
- (ret = DtlsMsgPoolSave(ssl, input, inputSz, server_hello_done)) != 0) {
- XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
- return ret;
- }
- #endif
- sendSz = BuildMessage(ssl, output, sendSz, input, inputSz,
- handshake, 1, 0, 0, CUR_ORDER);
- XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
-
- if (sendSz < 0)
- return sendSz;
- } else {
- #ifdef WOLFSSL_DTLS
- if (IsDtlsNotSctpMode(ssl)) {
- if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, server_hello_done)) != 0)
- return ret;
- }
- if (ssl->options.dtls)
- DtlsSEQIncrement(ssl, CUR_ORDER);
- #endif
- ret = HashOutput(ssl, output, sendSz, 0);
- if (ret != 0)
- return ret;
- }
-
- #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA)
- if (ssl->hsInfoOn)
- AddPacketName(ssl, "ServerHelloDone");
- if (ssl->toInfoOn) {
- ret = AddPacketInfo(ssl, "ServerHelloDone", handshake, output,
- sendSz, WRITE_PROTO, 0, ssl->heap);
- if (ret != 0)
- return ret;
- }
- #endif
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
- ssl->options.buildingMsg = 0;
-
- ssl->buffers.outputBuffer.length += sendSz;
ret = SendBuffered(ssl);
@@ -36936,7 +39211,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
it = (InternalTicket*)et->enc_ticket;
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ssl->error != WC_PENDING_E)
+ if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
XMEMSET(et, 0, sizeof(*et));
@@ -37020,7 +39295,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ssl->ctx->ticketEncCb == NULL
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL)
||
- /* SSL_OP_NO_TICKET turns off tickets in <= 1.2. Forces
+ /* WOLFSSL_OP_NO_TICKET turns off tickets in <= 1.2. Forces
* "stateful" tickets for 1.3 so just use the regular
* stateless ones. */
(!IsAtLeastTLSv1_3(ssl->version) &&
@@ -37034,7 +39309,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
itHash = HashObject((byte*)it, sizeof(*it), &error);
if (error == 0) {
ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac,
- 1, et->enc_ticket, sizeof(InternalTicket), &encLen,
+ 1, et->enc_ticket, WOLFSSL_INTERNAL_TICKET_LEN, &encLen,
SSL_TICKET_CTX(ssl));
}
else {
@@ -37043,13 +39318,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
if (ret != WOLFSSL_TICKET_RET_OK) {
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return ret;
}
#endif
goto error;
}
- if (encLen < (int)sizeof(InternalTicket) ||
+ if (encLen < (int)WOLFSSL_INTERNAL_TICKET_LEN ||
encLen > (int)WOLFSSL_TICKET_ENC_SZ) {
WOLFSSL_MSG("Bad user ticket encrypt size");
ret = BAD_TICKET_KEY_CB_SZ;
@@ -37125,7 +39400,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
WOLFSSL_ENTER("DoDecryptTicket");
if (len > SESSION_TICKET_LEN ||
- len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) {
+ len < (word32)(WOLFSSL_INTERNAL_TICKET_LEN +
+ WOLFSSL_TICKET_FIXED_SZ)) {
WOLFSSL_ERROR_VERBOSE(BAD_TICKET_MSG_SZ);
return WOLFSSL_TICKET_RET_REJECT;
}
@@ -37143,7 +39419,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (ssl->ctx->ticketEncCb == NULL
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL)
||
- /* SSL_OP_NO_TICKET turns off tickets in < 1.2. Forces
+ /* WOLFSSL_OP_NO_TICKET turns off tickets in < 1.2. Forces
* "stateful" tickets for 1.3 so just use the regular
* stateless ones. */
(!IsAtLeastTLSv1_3(ssl->version) &&
@@ -37164,7 +39440,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
if (ret != WOLFSSL_TICKET_RET_OK) {
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return ret;
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -37173,7 +39449,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return WOLFSSL_TICKET_RET_REJECT;
}
}
- if (outLen > (int)inLen || outLen < (int)sizeof(InternalTicket)) {
+ if (outLen > (int)inLen || outLen < (int)WOLFSSL_INTERNAL_TICKET_LEN) {
WOLFSSL_MSG("Bad user ticket decrypt len");
WOLFSSL_ERROR_VERBOSE(BAD_TICKET_KEY_CB_SZ);
return BAD_TICKET_KEY_CB_SZ;
@@ -37241,7 +39517,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
diff -= ticketSeen;
if (diff > timeout * 1000 ||
diff > (sword64)TLS13_MAX_TICKET_AGE * 1000)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#else
sword64 diff;
sword64 ticketSeen; /* Time ticket seen (ms) */
@@ -37259,7 +39535,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
diff -= ticketSeen;
if (diff > timeout * 1000 ||
diff > (sword64)TLS13_MAX_TICKET_AGE * 1000)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#endif
ato32(psk->it->ageAdd, &ticketAdd);
/* Subtract client's ticket age and unobfuscate. */
@@ -37269,7 +39545,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
* Allow +/- 1000 milliseconds on ticket age.
*/
if (diff < -1000 || diff - MAX_TICKET_AGE_DIFF * 1000 > 1000)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#if !defined(WOLFSSL_PSK_ONE_ID) && !defined(WOLFSSL_PRIORITIZE_PSK)
/* Check whether resumption is possible based on suites in SSL and
@@ -37277,18 +39553,18 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
*/
(void)ssl;
if (XMEMCMP(suite, psk->it->suite, SUITE_LEN) != 0)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#else
(void)suite;
if (!FindSuiteSSL(ssl, psk->it->suite))
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#endif
#ifdef OPENSSL_EXTRA
if (ssl->sessionCtxSz > 0 &&
(psk->it->sessionCtxSz != ssl->sessionCtxSz ||
XMEMCMP(psk->it->sessionCtx, ssl->sessionCtx,
ssl->sessionCtxSz) != 0))
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#endif
return 0;
}
@@ -37450,7 +39726,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
if (sess == NULL) {
ret = TlsSessionCacheGetAndRdLock(id, &sess, &freeCtx->row,
- ssl->options.side);
+ (byte)ssl->options.side);
if (ret != 0)
sess = NULL;
}
@@ -37496,8 +39772,19 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
WOLFSSL_MSG("Found session matching the session id"
" found in the ticket");
/* Allocate and populate an InternalTicket */
+ #ifdef WOLFSSL_NO_REALLOC
+ tmp = (byte*)XMALLOC(sizeof(InternalTicket), ssl->heap,
+ DYNAMIC_TYPE_TLSX);
+ if (tmp != NULL && psk->identity != NULL)
+ {
+ XMEMCPY(tmp, psk->identity, psk->identityLen);
+ XFREE(psk->identity, ssl->heap, DYNAMIC_TYPE_TLSX);
+ psk->identity = NULL;
+ }
+ #else
tmp = (byte*)XREALLOC(psk->identity, sizeof(InternalTicket),
ssl->heap, DYNAMIC_TYPE_TLSX);
+ #endif
if (tmp != NULL) {
XMEMSET(tmp, 0, sizeof(InternalTicket));
psk->identity = tmp;
@@ -37572,6 +39859,22 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
WOLFSSL_START(WC_FUNC_TICKET_DO);
WOLFSSL_ENTER("DoClientTicket");
+#ifdef HAVE_SECRET_CALLBACK
+ if (ssl->ticketParseCb != NULL) {
+ decryptRet = WOLFSSL_TICKET_RET_OK;
+ if (!ssl->ticketParseCb(ssl, input, len, ssl->ticketParseCtx)) {
+ /* Failure kills the connection */
+ decryptRet = WOLFSSL_TICKET_RET_FATAL;
+ }
+ else {
+ if (wolfSSL_set_SessionTicket(ssl, input, len) !=
+ WOLFSSL_SUCCESS)
+ decryptRet = WOLFSSL_TICKET_RET_REJECT;
+ }
+ goto cleanup;
+ }
+ else
+#endif
#ifdef WOLFSSL_TLS13
if (len == ID_LEN && IsAtLeastTLSv1_3(ssl->version)) {
/* This is a stateful ticket. We can be sure about this because
@@ -37586,7 +39889,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
else
#endif
+ if (len >= sizeof(*it))
decryptRet = DoDecryptTicket(ssl, input, len, &it);
+ else
+ WOLFSSL_MSG("Ticket is smaller than InternalTicket. Rejecting.");
+
if (decryptRet != WOLFSSL_TICKET_RET_OK &&
decryptRet != WOLFSSL_TICKET_RET_CREATE) {
@@ -37662,7 +39969,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
length += ssl->session->ticketLen;
- sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ sendSz = (int)length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
if (!ssl->options.dtls) {
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
@@ -37704,7 +40011,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) {
byte* input;
- int inputSz = idx; /* build msg adds rec hdr */
+ int inputSz = (int)idx; /* build msg adds rec hdr */
int recordHeaderSz = RECORD_HEADER_SZ;
if (ssl->options.dtls)
@@ -37725,7 +40032,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
else {
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
- if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, session_ticket)) != 0)
+ if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, session_ticket)) != 0)
return ret;
DtlsSEQIncrement(ssl, CUR_ORDER);
@@ -37748,7 +40055,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
return ret;
}
-#ifndef WOLFSSL_NO_DEF_TICKET_ENC_CB
+#if !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && !defined(NO_TLS)
/* Initialize the context for session ticket encryption.
*
@@ -37847,7 +40154,121 @@ static void TicketEncCbCtx_Free(TicketEncCbCtx* keyCtx)
wc_FreeRng(&keyCtx->rng);
}
-#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
+#ifdef WOLFSSL_TICKET_ENC_CBC_HMAC
+/* Ticket encryption/decryption implementation.
+ *
+ * @param [in] key Key for encryption/decryption and HMAC.
+ * @param [in] keyLen Length of key in bytes.
+ * @param [in] iv IV/Nonce for encryption/decryption.
+ * @param [in] aad Additional authentication data.
+ * @param [in] aadSz Length of additional authentication data.
+ * @param [in] in Data to encrypt/decrypt.
+ * @param [in] inLen Length of encrypted data.
+ * @param [out] out Resulting data from encrypt/decrypt.
+ * @param [out] outLen Size of resulting data.
+ * @param [in] tag Authentication tag for encrypted data.
+ * @param [in] heap Dynamic memory allocation data hint.
+ * @param [in] enc 1 when encrypting, 0 when decrypting.
+ * @return 0 on success.
+ * @return Other value when encryption/decryption fails.
+ */
+static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz,
+ byte* in, int inLen, byte* out, int* outLen, byte* tag,
+ void* heap, int enc)
+{
+ int ret;
+#ifdef WOLFSSL_SMALL_STACK
+ Aes* aes;
+ Hmac* hmac;
+#else
+ Aes aes[1];
+ Hmac hmac[1];
+#endif
+
+ (void)heap;
+
+#ifdef WOLFSSL_SMALL_STACK
+ aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (aes == NULL)
+ return MEMORY_E;
+ hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (hmac == NULL) {
+ XFREE(aes, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
+#endif
+
+ XMEMSET(aes, 0, sizeof(Aes));
+ XMEMSET(hmac, 0, sizeof(Hmac));
+
+ ret = wc_HmacInit(hmac, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (ret == 0) {
+ ret = wc_HmacSetKey(hmac, WOLFSSL_TICKET_ENC_HMAC, key + keyLen -
+ WOLFSSL_TICKET_HMAC_KEY_SZ, WOLFSSL_TICKET_HMAC_KEY_SZ);
+ }
+ if (ret == 0) {
+ ret = wc_HmacUpdate(hmac, aad, aadSz);
+ }
+
+ if (ret == 0) {
+ if (enc) {
+ ret = wc_AesInit(aes, NULL, INVALID_DEVID);
+ if (ret == 0) {
+ ret = wc_AesSetKey(aes, key,
+ keyLen - WOLFSSL_TICKET_HMAC_KEY_SZ, iv, AES_ENCRYPTION);
+ }
+ if (ret == 0) {
+ ret = wc_HmacUpdate(hmac, in, inLen);
+ }
+ if (ret == 0) {
+ ret = wc_AesCbcEncrypt(aes, in, out, inLen);
+ }
+ if (ret == 0) {
+ XMEMSET(tag, 0, WOLFSSL_TICKET_MAC_SZ);
+ ret = wc_HmacFinal(hmac, tag);
+ }
+ wc_AesFree(aes);
+ }
+ else {
+ unsigned char calcTag[WOLFSSL_TICKET_MAC_SZ];
+
+ ret = wc_AesInit(aes, NULL, INVALID_DEVID);
+ if (ret == 0) {
+ ret = wc_AesSetKey(aes, key,
+ keyLen - WOLFSSL_TICKET_HMAC_KEY_SZ, iv, AES_DECRYPTION);
+ }
+ if (ret == 0) {
+ ret = wc_AesCbcDecrypt(aes, in, out, inLen);
+ }
+ if (ret == 0) {
+ ret = wc_HmacUpdate(hmac, out, inLen);
+ }
+ if (ret == 0) {
+ XMEMSET(calcTag, 0, WOLFSSL_TICKET_MAC_SZ);
+ ret = wc_HmacFinal(hmac, calcTag);
+ }
+ if (ret == 0) {
+ int i;
+ calcTag[0] ^= tag[0];
+ for (i = 1; i < WOLFSSL_TICKET_MAC_SZ; i++) {
+ calcTag[0] |= calcTag[i] ^ tag[i];
+ }
+ /* Return a negative value when no match. */
+ ret = -calcTag[0];
+ }
+ wc_AesFree(aes);
+ }
+ }
+ wc_HmacFree(hmac);
+
+ WC_FREE_VAR_EX(hmac, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(aes, heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ *outLen = inLen;
+
+ return ret;
+}
+#elif defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
!defined(WOLFSSL_TICKET_ENC_AES128_GCM) && \
!defined(WOLFSSL_TICKET_ENC_AES256_GCM)
/* Ticket encryption/decryption implementation.
@@ -37913,19 +40334,12 @@ static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz,
void* heap, int enc)
{
int ret;
-#ifdef WOLFSSL_SMALL_STACK
- Aes* aes;
-#else
- Aes aes[1];
-#endif
+ WC_DECLARE_VAR(aes, Aes, 1, 0);
(void)heap;
-#ifdef WOLFSSL_SMALL_STACK
- aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (aes == NULL)
- return MEMORY_E;
-#endif
+ WC_ALLOC_VAR_EX(aes, Aes, 1, heap, DYNAMIC_TYPE_TMP_BUFFER,
+ return MEMORY_E);
if (enc) {
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
@@ -37934,7 +40348,7 @@ static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz,
}
if (ret == 0) {
ret = wc_AesGcmEncrypt(aes, in, out, inLen, iv, GCM_NONCE_MID_SZ,
- tag, AES_BLOCK_SIZE, aad, aadSz);
+ tag, WC_AES_BLOCK_SIZE, aad, aadSz);
}
wc_AesFree(aes);
}
@@ -37945,14 +40359,12 @@ static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz,
}
if (ret == 0) {
ret = wc_AesGcmDecrypt(aes, in, out, inLen, iv, GCM_NONCE_MID_SZ,
- tag, AES_BLOCK_SIZE, aad, aadSz);
+ tag, WC_AES_BLOCK_SIZE, aad, aadSz);
}
wc_AesFree(aes);
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(aes, heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(aes, heap, DYNAMIC_TYPE_TMP_BUFFER);
*outLen = inLen;
@@ -37982,19 +40394,12 @@ static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz,
void* heap, int enc)
{
int ret;
-#ifdef WOLFSSL_SMALL_STACK
- wc_Sm4* sm4;
-#else
- wc_Sm4 sm4[1];
-#endif
+ WC_DECLARE_VAR(sm4, wc_Sm4, 1, 0);
(void)heap;
-#ifdef WOLFSSL_SMALL_STACK
- sm4 = (wc_Sm4*)XMALLOC(sizeof(wc_Sm4), heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (sm4 == NULL)
- return MEMORY_E;
-#endif
+ WC_ALLOC_VAR_EX(sm4, wc_Sm4, 1, heap, DYNAMIC_TYPE_TMP_BUFFER,
+ return MEMORY_E);
if (enc) {
ret = wc_Sm4Init(sm4, NULL, INVALID_DEVID);
@@ -38019,9 +40424,7 @@ static int TicketEncDec(byte* key, int keyLen, byte* iv, byte* aad, int aadSz,
wc_Sm4Free(sm4);
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(sm4, heap, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(sm4, heap, DYNAMIC_TYPE_TMP_BUFFER);
*outLen = inLen;
@@ -38142,6 +40545,10 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
WOLFSSL_ENTER("DefTicketEncCb");
+ if ((!enc) && (inLen != WOLFSSL_INTERNAL_TICKET_LEN)) {
+ return BUFFER_E;
+ }
+
/* Check we have setup the RNG, name and primary key. */
if (keyCtx->expirary[0] == 0) {
#ifndef SINGLE_THREADED
@@ -38379,7 +40786,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi;
ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo;
}
- AddHeaders(output, length, hello_verify_request, ssl);
+ AddHeaders(output, (word32)length, hello_verify_request, ssl);
output[idx++] = DTLS_MAJOR;
output[idx++] = DTLS_MINOR;
@@ -38445,6 +40852,198 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
(void)args;
}
+ #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448)
+ static int ImportPeerECCKey(WOLFSSL* ssl, byte* input, DckeArgs* args,
+ word32 size, ecc_key* private_key, byte* haveCb)
+ {
+ int ret;
+ int kea = ssl->specs.kea;
+
+ *haveCb = 0;
+ if ((args->idx - args->begin) + OPAQUE8_LEN > size)
+ return BUFFER_ERROR;
+
+ args->length = input[args->idx++];
+
+ if ((args->idx - args->begin) + args->length > size)
+ return BUFFER_ERROR;
+
+ if (kea == ecdhe_psk_kea)
+ args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN;
+
+ #ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X25519SharedSecretCb != NULL) {
+ *haveCb = 1;
+ return 0;
+ }
+ #endif
+
+ if (kea == ecdhe_psk_kea && ssl->eccTempKeyPresent == 0) {
+ WOLFSSL_MSG("X25519 ephemeral key not made correctly");
+ return ECC_MAKEKEY_ERROR;
+ }
+
+ if (ssl->peerX25519Key == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ (void**)&ssl->peerX25519Key);
+ if (ret != 0) {
+ return ret;
+ }
+ } else if (ssl->peerX25519KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
+ ssl->peerX25519Key);
+ ssl->peerX25519KeyPresent = 0;
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ if ((ret = wc_curve25519_check_public(input + args->idx,
+ args->length, EC25519_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == WC_NO_ERR_TRACE(BUFFER_E))
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E))
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ }
+ #else
+ (void)ret;
+ #endif
+ return ECC_PEERKEY_ERROR;
+ }
+
+ if (wc_curve25519_import_public_ex(input + args->idx, args->length,
+ ssl->peerX25519Key, EC25519_LITTLE_ENDIAN)) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ #endif
+ return ECC_PEERKEY_ERROR;
+ }
+ if (kea == ecc_diffie_hellman_kea)
+ ssl->arrays->preMasterSz = CURVE25519_KEYSIZE;
+
+ ssl->peerX25519KeyPresent = 1;
+ return 0;
+ }
+ #endif
+ #ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID) {
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->X448SharedSecretCb != NULL) {
+ *haveCb = 1;
+ return 0;
+ }
+ #endif
+
+ if (kea == ecdhe_psk_kea && ssl->eccTempKeyPresent == 0) {
+ WOLFSSL_MSG("X448 ephemeral key not made correctly");
+ return ECC_MAKEKEY_ERROR;
+ }
+
+ if (ssl->peerX448Key == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
+ (void**)&ssl->peerX448Key);
+ if (ret != 0)
+ return ret;
+ } else if (ssl->peerX448KeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
+ ssl->peerX448Key);
+ ssl->peerX448KeyPresent = 0;
+ if (ret != 0)
+ return ret;
+ }
+
+ if ((ret = wc_curve448_check_public(input + args->idx, args->length,
+ EC448_LITTLE_ENDIAN)) != 0) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ if (ret == WC_NO_ERR_TRACE(BUFFER_E))
+ SendAlert(ssl, alert_fatal, decode_error);
+ else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E))
+ SendAlert(ssl, alert_fatal, bad_record_mac);
+ else {
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ }
+ #else
+ (void)ret;
+ #endif
+ return ECC_PEERKEY_ERROR;
+ }
+
+ if (wc_curve448_import_public_ex(input + args->idx, args->length,
+ ssl->peerX448Key, EC448_LITTLE_ENDIAN)) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ #endif
+
+ return ECC_PEERKEY_ERROR;
+ }
+
+ if (kea == ecc_diffie_hellman_kea)
+ ssl->arrays->preMasterSz = CURVE448_KEY_SIZE;
+
+ ssl->peerX448KeyPresent = 1;
+
+ return 0;
+ }
+ #endif
+ #ifdef HAVE_ECC
+ #ifdef HAVE_PK_CALLBACKS
+ /* if callback then use it for shared secret */
+ if (ssl->ctx->EccSharedSecretCb != NULL) {
+ *haveCb = 1;
+ return 0;
+ }
+ #endif
+
+ if (ssl->eccTempKeyPresent == 0 &&
+ (kea == ecdhe_psk_kea || !ssl->specs.static_ecdh)) {
+ WOLFSSL_MSG("Ecc ephemeral key not made correctly");
+ return ECC_MAKEKEY_ERROR;
+ }
+
+ if (ssl->peerEccKey == NULL) {
+ /* alloc/init on demand */
+ ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey);
+ if (ret != 0)
+ return ret;
+ }
+ else if (ssl->peerEccKeyPresent) {
+ ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey);
+ ssl->peerEccKeyPresent = 0;
+ if (ret != 0)
+ return ret;
+ }
+ if (wc_ecc_import_x963_ex(input + args->idx, args->length,
+ ssl->peerEccKey, kea == ecdhe_psk_kea ? ssl->eccTempKey->dp->id
+ : private_key->dp->id)) {
+ #ifdef WOLFSSL_EXTRA_ALERTS
+ SendAlert(ssl, alert_fatal, illegal_parameter);
+ #endif
+
+ return ECC_PEERKEY_ERROR;
+ }
+
+ if (kea == ecc_diffie_hellman_kea)
+ ssl->arrays->preMasterSz = (word32)private_key->dp->size;
+
+ ssl->peerEccKeyPresent = 1;
+ #else
+ (void)private_key;
+ #endif /* HAVE_ECC */
+ return 0;
+ }
+ #endif /* defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+ defined(HAVE_CURVE448) */
+
/* handle processing client_key_exchange (16) */
static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx,
word32 size)
@@ -38463,6 +41062,10 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
WOLFSSL_ENTER("DoClientKeyExchange");
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key, ssl->buffers.keyMask);
+ #endif
+
#ifdef WOLFSSL_ASYNC_CRYPT
if (ssl->async == NULL) {
ssl->async = (struct WOLFSSL_ASYNC*)
@@ -38474,7 +41077,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
args = (DckeArgs*)ssl->async->args;
ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* Check for error */
if (ret < 0)
goto exit_dcke;
@@ -38618,7 +41221,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);
@@ -38667,7 +41270,6 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
#ifndef NO_PSK
case psk_kea:
{
- byte* pms = ssl->arrays->preMasterSecret;
word16 ci_sz;
if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
@@ -38688,38 +41290,10 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
XMEMCPY(ssl->arrays->client_identity,
input + args->idx, ci_sz);
args->idx += ci_sz;
-
ssl->arrays->client_identity[ci_sz] = '\0'; /* null term */
- ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
- ssl->arrays->client_identity, ssl->arrays->psk_key,
- MAX_PSK_KEY_LEN);
-
- if (ssl->arrays->psk_keySz == 0 ||
- ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
- #if defined(WOLFSSL_EXTRA_ALERTS) || \
- defined(WOLFSSL_PSK_IDENTITY_ALERT)
- SendAlert(ssl, alert_fatal,
- unknown_psk_identity);
- #endif
+ if (AddPSKtoPreMasterSecret(ssl))
ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
- }
- /* SERVER: Pre-shared Key for peer authentication. */
- ssl->options.peerAuthGood = 1;
-
- /* make psk pre master secret */
- /* length of key + length 0s + length of key + key */
- c16toa((word16) ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
-
- XMEMSET(pms, 0, ssl->arrays->psk_keySz);
- pms += ssl->arrays->psk_keySz;
-
- c16toa((word16) ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
-
- XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz =
- (ssl->arrays->psk_keySz * 2) + (OPAQUE16_LEN * 2);
+ MakePSKPreMasterSecret(ssl->arrays, 1);
break;
}
#endif /* !NO_PSK */
@@ -38727,14 +41301,16 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
defined(HAVE_CURVE448)
case ecc_diffie_hellman_kea:
{
+ ecc_key* private_key = NULL;
+ byte haveCb;
#ifdef HAVE_ECC
- ecc_key* private_key = ssl->eccTempKey;
+ private_key = ssl->eccTempKey;
/* handle static private key */
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);
@@ -38745,182 +41321,24 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
}
#endif
- /* import peer ECC key */
- if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dcke);
- }
-
- args->length = input[args->idx++];
-
- if ((args->idx - args->begin) + args->length > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dcke);
- }
-
- #ifdef HAVE_CURVE25519
- if (ssl->ecdhCurveOID == ECC_X25519_OID) {
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X25519SharedSecretCb != NULL) {
- break;
- }
- #endif
- if (ssl->peerX25519Key == NULL) {
- /* alloc/init on demand */
- ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
- (void**)&ssl->peerX25519Key);
- if (ret != 0) {
- goto exit_dcke;
- }
- } else if (ssl->peerX25519KeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
- ssl->peerX25519Key);
- ssl->peerX25519KeyPresent = 0;
- if (ret != 0) {
- goto exit_dcke;
- }
- }
-
- if ((ret = wc_curve25519_check_public(
- input + args->idx, args->length,
- EC25519_LITTLE_ENDIAN)) != 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- if (ret == BUFFER_E)
- SendAlert(ssl, alert_fatal, decode_error);
- else if (ret == ECC_OUT_OF_RANGE_E)
- SendAlert(ssl, alert_fatal, bad_record_mac);
- else {
- SendAlert(ssl, alert_fatal,
- illegal_parameter);
- }
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- if (wc_curve25519_import_public_ex(
- input + args->idx, args->length,
- ssl->peerX25519Key,
- EC25519_LITTLE_ENDIAN)) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- SendAlert(ssl, alert_fatal, illegal_parameter);
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- ssl->arrays->preMasterSz = CURVE25519_KEYSIZE;
-
- ssl->peerX25519KeyPresent = 1;
-
- break;
- }
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->ecdhCurveOID == ECC_X448_OID) {
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X448SharedSecretCb != NULL) {
- break;
- }
- #endif
- if (ssl->peerX448Key == NULL) {
- /* alloc/init on demand */
- ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
- (void**)&ssl->peerX448Key);
- if (ret != 0) {
- goto exit_dcke;
- }
- } else if (ssl->peerX448KeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
- ssl->peerX448Key);
- ssl->peerX448KeyPresent = 0;
- if (ret != 0) {
- goto exit_dcke;
- }
- }
-
- if ((ret = wc_curve448_check_public(
- input + args->idx, args->length,
- EC448_LITTLE_ENDIAN)) != 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- if (ret == BUFFER_E)
- SendAlert(ssl, alert_fatal, decode_error);
- else if (ret == ECC_OUT_OF_RANGE_E)
- SendAlert(ssl, alert_fatal, bad_record_mac);
- else {
- SendAlert(ssl, alert_fatal,
- illegal_parameter);
- }
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- if (wc_curve448_import_public_ex(
- input + args->idx, args->length,
- ssl->peerX448Key,
- EC448_LITTLE_ENDIAN)) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- SendAlert(ssl, alert_fatal, illegal_parameter);
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- ssl->arrays->preMasterSz = CURVE448_KEY_SIZE;
-
- ssl->peerX448KeyPresent = 1;
-
- break;
- }
- #endif
- #ifdef HAVE_ECC
+ if ((ret = ImportPeerECCKey(ssl, input, args, size,
+ private_key, &haveCb)))
+ ERROR_OUT(ret, exit_dcke);
#ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->EccSharedSecretCb != NULL) {
+ if (haveCb) {
+ WOLFSSL_MSG("Using PK callback for peer key");
break;
}
+ #else
+ (void)haveCb; /* not used */
#endif
- if (!ssl->specs.static_ecdh &&
- ssl->eccTempKeyPresent == 0) {
- WOLFSSL_MSG("Ecc ephemeral key not made correctly");
- ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
- }
-
- if (ssl->peerEccKey == NULL) {
- /* alloc/init on demand */
- ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
- (void**)&ssl->peerEccKey);
- if (ret != 0) {
- goto exit_dcke;
- }
- } else if (ssl->peerEccKeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
- ssl->peerEccKey);
- ssl->peerEccKeyPresent = 0;
- if (ret != 0) {
- goto exit_dcke;
- }
- }
-
- if (wc_ecc_import_x963_ex(input + args->idx,
- args->length, ssl->peerEccKey,
- private_key->dp->id)) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- SendAlert(ssl, alert_fatal, illegal_parameter);
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- ssl->arrays->preMasterSz = private_key->dp->size;
-
- ssl->peerEccKeyPresent = 1;
-
#if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE)
/* client_hello may have sent FFEDH2048, which sets namedGroup,
but that is not being used, so clear it */
/* resolves issue with server side wolfSSL_get_curve_name */
ssl->namedGroup = 0;
#endif
- #endif /* HAVE_ECC */
-
break;
}
#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
@@ -39018,6 +41436,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
case ecdhe_psk_kea:
{
word16 clientSz;
+ byte haveCb;
/* Read in the PSK hint */
if ((args->idx - args->begin) + OPAQUE16_LEN > size) {
@@ -39038,172 +41457,17 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
args->idx += clientSz;
ssl->arrays->client_identity[clientSz] = '\0'; /* null term */
- /* import peer ECC key */
- if ((args->idx - args->begin) + OPAQUE8_LEN > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dcke);
- }
-
- args->length = input[args->idx++];
-
- if ((args->idx - args->begin) + args->length > size) {
- ERROR_OUT(BUFFER_ERROR, exit_dcke);
- }
-
- args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN;
-
- #ifdef HAVE_CURVE25519
- if (ssl->ecdhCurveOID == ECC_X25519_OID) {
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X25519SharedSecretCb != NULL) {
- break;
- }
- #endif
-
- if (ssl->eccTempKeyPresent == 0) {
- WOLFSSL_MSG(
- "X25519 ephemeral key not made correctly");
- ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
- }
-
- if (ssl->peerX25519Key == NULL) {
- /* alloc/init on demand */
- ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519,
- (void**)&ssl->peerX25519Key);
- if (ret != 0) {
- goto exit_dcke;
- }
- } else if (ssl->peerX25519KeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519,
- ssl->peerX25519Key);
- ssl->peerX25519KeyPresent = 0;
- if (ret != 0) {
- goto exit_dcke;
- }
- }
-
- if ((ret = wc_curve25519_check_public(
- input + args->idx, args->length,
- EC25519_LITTLE_ENDIAN)) != 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- if (ret == BUFFER_E)
- SendAlert(ssl, alert_fatal, decode_error);
- else if (ret == ECC_OUT_OF_RANGE_E)
- SendAlert(ssl, alert_fatal, bad_record_mac);
- else {
- SendAlert(ssl, alert_fatal,
- illegal_parameter);
- }
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- if (wc_curve25519_import_public_ex(
- input + args->idx, args->length,
- ssl->peerX25519Key,
- EC25519_LITTLE_ENDIAN)) {
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- ssl->peerX25519KeyPresent = 1;
-
- break;
- }
- #endif
- #ifdef HAVE_CURVE448
- if (ssl->ecdhCurveOID == ECC_X448_OID) {
- #ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->X448SharedSecretCb != NULL) {
- break;
- }
- #endif
-
- if (ssl->eccTempKeyPresent == 0) {
- WOLFSSL_MSG(
- "X448 ephemeral key not made correctly");
- ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
- }
-
- if (ssl->peerX448Key == NULL) {
- /* alloc/init on demand */
- ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE448,
- (void**)&ssl->peerX448Key);
- if (ret != 0) {
- goto exit_dcke;
- }
- } else if (ssl->peerX448KeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE448,
- ssl->peerX448Key);
- ssl->peerX448KeyPresent = 0;
- if (ret != 0) {
- goto exit_dcke;
- }
- }
-
- if ((ret = wc_curve448_check_public(
- input + args->idx, args->length,
- EC448_LITTLE_ENDIAN)) != 0) {
- #ifdef WOLFSSL_EXTRA_ALERTS
- if (ret == BUFFER_E)
- SendAlert(ssl, alert_fatal, decode_error);
- else if (ret == ECC_OUT_OF_RANGE_E)
- SendAlert(ssl, alert_fatal, bad_record_mac);
- else {
- SendAlert(ssl, alert_fatal,
- illegal_parameter);
- }
- #endif
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- if (wc_curve448_import_public_ex(
- input + args->idx, args->length,
- ssl->peerX448Key,
- EC448_LITTLE_ENDIAN)) {
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- ssl->peerX448KeyPresent = 1;
-
- break;
- }
- #endif
+ if ((ret = ImportPeerECCKey(ssl, input, args, size,
+ NULL, &haveCb)))
+ ERROR_OUT(ret, exit_dcke);
#ifdef HAVE_PK_CALLBACKS
- /* if callback then use it for shared secret */
- if (ssl->ctx->EccSharedSecretCb != NULL) {
+ if (haveCb) {
+ WOLFSSL_MSG("Using PK callback for peer key");
break;
}
+ #else
+ (void)haveCb; /* not used */
#endif
-
- if (ssl->eccTempKeyPresent == 0) {
- WOLFSSL_MSG("Ecc ephemeral key not made correctly");
- ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke);
- }
-
- if (ssl->peerEccKey == NULL) {
- /* alloc/init on demand */
- ret = AllocKey(ssl, DYNAMIC_TYPE_ECC,
- (void**)&ssl->peerEccKey);
- if (ret != 0) {
- goto exit_dcke;
- }
- }
- else if (ssl->peerEccKeyPresent) {
- ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC,
- ssl->peerEccKey);
- ssl->peerEccKeyPresent = 0;
- if (ret != 0) {
- goto exit_dcke;
- }
- }
- if (wc_ecc_import_x963_ex(input + args->idx,
- args->length, ssl->peerEccKey,
- ssl->eccTempKey->dp->id)) {
- ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke);
- }
-
- ssl->peerEccKeyPresent = 1;
break;
}
#endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
@@ -39224,11 +41488,11 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
case TLS_ASYNC_DO:
{
switch (ssl->specs.kea) {
- #ifndef NO_RSA
+ #if !defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
case rsa_kea:
{
RsaKey* key = (RsaKey*)ssl->hsKey;
- int lenErrMask;
+ volatile int lenErrMask;
ret = RsaDec(ssl,
input + args->idx,
@@ -39248,19 +41512,19 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
* RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR
*/
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
goto exit_dcke;
#endif
- if (ret == BAD_FUNC_ARG)
+ if (ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG))
goto exit_dcke;
lenErrMask = 0 - (SECRET_LEN != args->sigSz);
args->lastErr = (ret & (~lenErrMask)) |
- (RSA_PAD_E & lenErrMask);
+ (WC_NO_ERR_TRACE(RSA_PAD_E) & lenErrMask);
ret = 0;
break;
} /* rsa_kea */
- #endif /* !NO_RSA */
+ #endif /* !NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY */
#ifndef NO_PSK
case psk_kea:
{
@@ -39314,7 +41578,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
WOLFSSL_SERVER_END
);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret != WC_PENDING_E)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
FreeKey(ssl, DYNAMIC_TYPE_ECC,
@@ -39370,7 +41634,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
WOLFSSL_SERVER_END
);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret != WC_PENDING_E)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
FreeKey(ssl, DYNAMIC_TYPE_CURVE25519,
@@ -39391,7 +41655,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
WOLFSSL_SERVER_END
);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret != WC_PENDING_E)
+ if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
FreeKey(ssl, DYNAMIC_TYPE_CURVE448,
@@ -39411,7 +41675,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
);
if (!ssl->specs.static_ecdh
#ifdef WOLFSSL_ASYNC_CRYPT
- && ret != WC_PENDING_E
+ && ret != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
) {
FreeKey(ssl, DYNAMIC_TYPE_ECC,
@@ -39442,7 +41706,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
case rsa_kea:
{
byte *tmpRsa;
- byte mask;
+ volatile byte mask;
/* Add the signature length to idx */
args->idx += args->length;
@@ -39466,8 +41730,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
ret = args->lastErr;
args->lastErr = 0; /* reset */
/* On error 'ret' will be negative */
- mask = ((unsigned int)ret >>
- ((sizeof(ret) * 8) - 1)) - 1;
+ mask = (byte)(((unsigned int)ret >> ((sizeof(ret) * 8) - 1)) - 1);
/* build PreMasterSecret */
ssl->arrays->preMasterSecret[0] = ssl->chVersion.major;
@@ -39519,39 +41782,15 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
#if !defined(NO_DH) && !defined(NO_PSK)
case dhe_psk_kea:
{
- byte* pms = ssl->arrays->preMasterSecret;
word16 clientSz = (word16)args->sigSz;
args->idx += clientSz;
- c16toa((word16)ssl->arrays->preMasterSz, pms);
- ssl->arrays->preMasterSz += OPAQUE16_LEN;
- pms += ssl->arrays->preMasterSz;
/* Use the PSK hint to look up the PSK and add it to the
* preMasterSecret here. */
- ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
- ssl->arrays->client_identity, ssl->arrays->psk_key,
- MAX_PSK_KEY_LEN);
-
- if (ssl->arrays->psk_keySz == 0 ||
- ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
- #if defined(WOLFSSL_EXTRA_ALERTS) || \
- defined(WOLFSSL_PSK_IDENTITY_ALERT)
- SendAlert(ssl, alert_fatal,
- unknown_psk_identity);
- #endif
+ if (AddPSKtoPreMasterSecret(ssl))
ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
- }
- /* SERVER: Pre-shared Key for peer authentication. */
- ssl->options.peerAuthGood = 1;
-
- c16toa((word16) ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
-
- XMEMCPY(pms, ssl->arrays->psk_key,
- ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz += ssl->arrays->psk_keySz +
- OPAQUE16_LEN;
+ MakePSKPreMasterSecret(ssl->arrays, 0);
break;
}
#endif /* !NO_DH && !NO_PSK */
@@ -39559,36 +41798,19 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
defined(HAVE_CURVE448)) && !defined(NO_PSK)
case ecdhe_psk_kea:
{
- byte* pms = ssl->arrays->preMasterSecret;
word16 clientSz = (word16)args->sigSz;
/* skip past the imported peer key */
args->idx += args->length;
/* Add preMasterSecret */
- c16toa(clientSz, pms);
- ssl->arrays->preMasterSz = OPAQUE16_LEN + clientSz;
- pms += ssl->arrays->preMasterSz;
+ ssl->arrays->preMasterSz = clientSz;
/* Use the PSK hint to look up the PSK and add it to the
* preMasterSecret here. */
- ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
- ssl->arrays->client_identity, ssl->arrays->psk_key,
- MAX_PSK_KEY_LEN);
-
- if (ssl->arrays->psk_keySz == 0 ||
- ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) {
+ if (AddPSKtoPreMasterSecret(ssl))
ERROR_OUT(PSK_KEY_ERROR, exit_dcke);
- }
- /* SERVER: Pre-shared Key for peer authentication. */
- ssl->options.peerAuthGood = 1;
-
- c16toa((word16) ssl->arrays->psk_keySz, pms);
- pms += OPAQUE16_LEN;
-
- XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
- ssl->arrays->preMasterSz +=
- ssl->arrays->psk_keySz + OPAQUE16_LEN;
+ MakePSKPreMasterSecret(ssl->arrays, 0);
break;
}
#endif /* (HAVE_ECC || CURVE25519 || CURVE448) && !NO_PSK */
@@ -39608,13 +41830,8 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
case TLS_ASYNC_FINALIZE:
{
- if (IsEncryptionOn(ssl, 0)) {
+ if (IsEncryptionOn(ssl, 0))
args->idx += ssl->keys.padSz;
- #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
- if (ssl->options.startedETMRead)
- args->idx += MacSize(ssl);
- #endif
- }
ret = MakeMasterSecret(ssl);
@@ -39647,11 +41864,22 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
exit_dcke:
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ if (ret == 0) {
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key,
+ &ssl->buffers.keyMask);
+ }
+ else {
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key,
+ ssl->buffers.keyMask);
+ }
+ #endif
+
WOLFSSL_LEAVE("DoClientKeyExchange", ret);
WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO);
#ifdef WOLFSSL_ASYNC_CRYPT
/* Handle async operation */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* Mark message as not received so it can process again */
ssl->msgsReceived.got_client_key_exchange = 0;
@@ -39695,7 +41923,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
WOLFSSL_EXTRA_ALERTS is defined, indicating user is OK with
potential information disclosure from alerts. */
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_EXTRA_ALERTS)
- ad = SSL_AD_UNRECOGNIZED_NAME;
+ ad = WOLFSSL_AD_UNRECOGNIZED_NAME;
#endif
/* Stunnel supports a custom sni callback to switch an SSL's ctx
* when SNI is received. Call it now if exists */
@@ -39722,7 +41950,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
}
#endif /* HAVE_SNI */
-#endif /* NO_WOLFSSL_SERVER */
+#endif /* !NO_WOLFSSL_SERVER && !NO_TLS */
#ifdef WOLFSSL_ASYNC_CRYPT
@@ -39743,7 +41971,8 @@ int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state)
event = &asyncDev->event;
ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL);
- if (ret != WC_NO_PENDING_E && ret != WC_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E) &&
+ ret != WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* advance key share state if doesn't need called again */
if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) {
(*state)++;
@@ -39756,7 +41985,7 @@ int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state)
#if (defined(WOLF_CRYPTO_CB) || defined(HAVE_PK_CALLBACKS)) && \
!defined(WOLFSSL_ASYNC_CRYPT_SW) && !defined(HAVE_INTEL_QA) && \
!defined(HAVE_CAVIUM)
- else if (ret == WC_PENDING_E) {
+ else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* Allow the underlying crypto API to be called again to trigger the
* crypto or PK callback. The actual callback must be called, since
* the completion is not detected in the poll like Intel QAT or
@@ -39894,7 +42123,7 @@ int wolfSSL_set_iotsafe_ctx(WOLFSSL *ssl, IOTSAFE *iotsafe)
return 0;
}
-#endif
+#endif /* WOLFSSL_IOTSAFE && HAVE_PK_CALLBACKS */
#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
/* create an instance of WOLFSSL_BY_DIR_HASH structure */
@@ -39955,7 +42184,7 @@ int wolfSSL_sk_BY_DIR_HASH_find(
}
next = next->next;
}
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* return a number of WOLFSSL_BY_DIR_HASH in stack */
int wolfSSL_sk_BY_DIR_HASH_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk)
@@ -39963,7 +42192,7 @@ int wolfSSL_sk_BY_DIR_HASH_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk)
WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_num");
if (sk == NULL)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
return (int)sk->num;
}
/* return WOLFSSL_BY_DIR_HASH instance at i */
@@ -39983,32 +42212,7 @@ WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_value(
WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_pop(
WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk)
{
- WOLFSSL_STACK* node;
- WOLFSSL_BY_DIR_HASH* hash;
-
- WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_pop");
-
- if (sk == NULL) {
- return NULL;
- }
-
- node = sk->next;
- hash = sk->data.dir_hash;
-
- if (node != NULL) { /* update sk and remove node from stack */
- sk->data.dir_hash = node->data.dir_hash;
- sk->next = node->next;
- wolfSSL_sk_free_node(node);
- }
- else { /* last x509 in stack */
- sk->data.dir_hash = NULL;
- }
-
- if (sk->num > 0) {
- sk->num -= 1;
- }
-
- return hash;
+ return (WOLFSSL_BY_DIR_HASH *)wolfSSL_sk_pop(sk);
}
/* release all contents in stack, and then release stack itself. */
/* Second argument is a function pointer to release resources. */
@@ -40063,39 +42267,13 @@ void wolfSSL_sk_BY_DIR_HASH_free(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk)
int wolfSSL_sk_BY_DIR_HASH_push(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk,
WOLFSSL_BY_DIR_HASH* in)
{
- WOLFSSL_STACK* node;
-
WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_push");
if (sk == NULL || in == NULL) {
return WOLFSSL_FAILURE;
}
- /* no previous values in stack */
- if (sk->data.dir_hash == NULL) {
- sk->data.dir_hash = in;
- sk->num += 1;
- return WOLFSSL_SUCCESS;
- }
-
- /* stack already has value(s) create a new node and add more */
- node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (node == NULL) {
- WOLFSSL_MSG("Memory error");
- return WOLFSSL_FAILURE;
- }
- XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
-
- /* push new obj onto head of stack */
- node->data.dir_hash = sk->data.dir_hash;
- node->next = sk->next;
- node->type = sk->type;
- sk->next = node;
- sk->data.dir_hash = in;
- sk->num += 1;
-
- return WOLFSSL_SUCCESS;
+ return wolfSSL_sk_push(sk, in);
}
/* create an instance of WOLFSSL_BY_DIR_entry structure */
WOLFSSL_BY_DIR_entry* wolfSSL_BY_DIR_entry_new(void)
@@ -40124,9 +42302,7 @@ void wolfSSL_BY_DIR_entry_free(WOLFSSL_BY_DIR_entry* entry)
wolfSSL_sk_BY_DIR_HASH_free(entry->hashes);
}
- if (entry->dir_name != NULL) {
- XFREE(entry->dir_name, NULL, DYNAMIC_TYPE_OPENSSL);
- }
+ XFREE(entry->dir_name, NULL, DYNAMIC_TYPE_OPENSSL);
XFREE(entry, NULL, DYNAMIC_TYPE_OPENSSL);
}
@@ -40148,7 +42324,7 @@ int wolfSSL_sk_BY_DIR_entry_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *sk)
WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_num");
if (sk == NULL)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
return (int)sk->num;
}
/* return WOLFSSL_BY_DIR_entry instance at i */
@@ -40168,32 +42344,7 @@ WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_value(
WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_pop(
WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk)
{
- WOLFSSL_STACK* node;
- WOLFSSL_BY_DIR_entry* entry;
-
- WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_pop");
-
- if (sk == NULL) {
- return NULL;
- }
-
- node = sk->next;
- entry = sk->data.dir_entry;
-
- if (node != NULL) { /* update sk and remove node from stack */
- sk->data.dir_entry = node->data.dir_entry;
- sk->next = node->next;
- wolfSSL_sk_free_node(node);
- }
- else { /* last x509 in stack */
- sk->data.dir_entry = NULL;
- }
-
- if (sk->num > 0) {
- sk->num -= 1;
- }
-
- return entry;
+ return (WOLFSSL_BY_DIR_entry *)wolfSSL_sk_pop(sk);
}
/* release all contents in stack, and then release stack itself. */
/* Second argument is a function pointer to release resources. */
@@ -40249,40 +42400,16 @@ void wolfSSL_sk_BY_DIR_entry_free(WOLF_STACK_OF(wolfSSL_BY_DIR_entry) *sk)
int wolfSSL_sk_BY_DIR_entry_push(WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk,
WOLFSSL_BY_DIR_entry* in)
{
- WOLFSSL_STACK* node;
+ WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_push");
if (sk == NULL || in == NULL) {
return WOLFSSL_FAILURE;
}
- /* no previous values in stack */
- if (sk->data.dir_entry == NULL) {
- sk->data.dir_entry = in;
- sk->num += 1;
- return WOLFSSL_SUCCESS;
- }
-
- /* stack already has value(s) create a new node and add more */
- node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
- DYNAMIC_TYPE_OPENSSL);
- if (node == NULL) {
- WOLFSSL_MSG("Memory error");
- return WOLFSSL_FAILURE;
- }
- XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
-
- /* push new obj onto head of stack */
- node->data.dir_entry = sk->data.dir_entry;
- node->next = sk->next;
- node->type = sk->type;
- sk->next = node;
- sk->data.dir_entry = in;
- sk->num += 1;
-
- return WOLFSSL_SUCCESS;
+ return wolfSSL_sk_push(sk, in);
}
-#endif /* OPENSSL_ALL */
+#endif /* OPENSSL_ALL && !NO_FILESYSTEM && !NO_FILESYSTEM */
#if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS)
@@ -40327,7 +42454,122 @@ static SecCertificateRef ConvertToSecCertificateRef(const byte* derCert,
return secCert;
}
+static int DisplaySecTrustError(CFErrorRef error, SecTrustRef trust)
+{
+ CFStringRef desc;
+ CFStringRef domain;
+ SecTrustResultType trustResult;
+ CFDictionaryRef info;
+
+ /* Description */
+ desc = CFErrorCopyDescription(error);
+ if (desc) {
+ char buffer[256];
+ if (CFStringGetCString(desc, buffer, sizeof(buffer),
+ kCFStringEncodingUTF8)) {
+ WOLFSSL_MSG_EX("SecTrustEvaluateWithError Error description: %s\n",
+ buffer);
+ }
+ CFRelease(desc);
+ }
+
+ /* Domain */
+ domain = CFErrorGetDomain(error);
+ if (domain) {
+ char domainStr[128];
+ if (CFStringGetCString(domain, domainStr, sizeof(domainStr),
+ kCFStringEncodingUTF8)) {
+ WOLFSSL_MSG_EX("SecTrustEvaluateWithError Domain: %s\n", domainStr);
+ }
+ }
+
+ /* Get additional trust result info */
+ if (SecTrustGetTrustResult(trust, &trustResult) == errSecSuccess) {
+ WOLFSSL_MSG_EX("SecTrustResultType: %d\n", trustResult);
+ /* Optional: decode the enum */
+ switch (trustResult) {
+ case kSecTrustResultInvalid:
+ WOLFSSL_MSG("TrustResult: Invalid\n");
+ break;
+ case kSecTrustResultProceed:
+ WOLFSSL_MSG("TrustResult: Proceed\n");
+ break;
+ case kSecTrustResultDeny:
+ WOLFSSL_MSG("TrustResult: Deny\n");
+ break;
+ case kSecTrustResultUnspecified:
+ WOLFSSL_MSG("TrustResult: Unspecified (implicitly trusted)\n");
+ break;
+ case kSecTrustResultRecoverableTrustFailure:
+ WOLFSSL_MSG("TrustResult: Recoverable trust failure\n");
+ break;
+ case kSecTrustResultFatalTrustFailure:
+ WOLFSSL_MSG("TrustResult: Fatal trust failure\n");
+ break;
+ case kSecTrustResultOtherError:
+ WOLFSSL_MSG("TrustResult: Other error\n");
+ break;
+ default:
+ WOLFSSL_MSG("TrustResult: Unknown\n");
+ break;
+ }
+ }
+ else {
+ WOLFSSL_MSG("SecTrustGetTrustResult failed\n");
+ }
+
+ info = CFErrorCopyUserInfo(error);
+ if (info) {
+ WOLFSSL_MSG("Trust error info dump:\n");
+ CFShow(info);
+ CFRelease(info);
+ }
+
+ return 0;
+}
+#if defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) && \
+ defined (WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION)
+static int MaxValidityPeriodErrorOnly(CFErrorRef error)
+{
+ int multiple = 0;
+
+ CFDictionaryRef userInfo = CFErrorCopyUserInfo(error);
+ if (userInfo) {
+ /* Get underlying error */
+ CFTypeRef underlying =
+ CFDictionaryGetValue(userInfo, kCFErrorUnderlyingErrorKey);
+ if (underlying) {
+ /* Get underlying error value*/
+ CFDictionaryRef underlyingDict =
+ CFErrorCopyUserInfo((CFErrorRef)underlying);
+ if (underlyingDict) {
+ char buffer[512];
+ CFStringRef values =
+ CFDictionaryGetValue(underlyingDict,
+ kCFErrorLocalizedDescriptionKey);
+ if(CFStringGetCString(values, buffer, sizeof(buffer),
+ kCFStringEncodingUTF8)) {
+ if (XSTRSTR(buffer, "Certificate exceeds maximum "
+ "temporal validity period") &&
+ (!XSTRSTR(buffer, "Certificate exceeds maximum "
+ "temporal validity period,") ||
+ !XSTRSTR(buffer, ", Certificate exceeds maximum "
+ "temporal validity period"))) {
+ WOLFSSL_MSG("Maximum validity period error only");
+ } else {
+ WOLFSSL_MSG("Found other errors");
+ multiple = 1;
+ }
+ }
+ CFRelease(underlyingDict);
+ }
+ }
+ CFRelease(userInfo);
+ }
+ return multiple;
+}
+#endif
/*
* Validates a chain of certificates using the Apple system trust APIs
*
@@ -40343,21 +42585,23 @@ static SecCertificateRef ConvertToSecCertificateRef(const byte* derCert,
* wolfSSL's built-in certificate validation mechanisms anymore. We instead
* must call into the Security Framework APIs to authenticate peer certificates
*/
-static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs,
- int totalCerts)
+static int DoAppleNativeCertValidation(WOLFSSL* ssl,
+ const WOLFSSL_BUFFER_INFO* certs,
+ int totalCerts)
{
- int i;
- int ret;
- OSStatus status;
+ int i;
+ int ret;
+ OSStatus status;
CFMutableArrayRef certArray = NULL;
SecCertificateRef secCert = NULL;
SecTrustRef trust = NULL;
- SecPolicyRef policy = NULL ;
+ SecPolicyRef policy = NULL;
+ CFStringRef hostname = NULL;
+ CFErrorRef error = NULL;
WOLFSSL_ENTER("DoAppleNativeCertValidation");
- certArray = CFArrayCreateMutable(kCFAllocatorDefault,
- totalCerts,
+ certArray = CFArrayCreateMutable(kCFAllocatorDefault, totalCerts,
&kCFTypeArrayCallBacks);
if (!certArray) {
WOLFSSL_MSG("Error: can't allocate CFArray for certificates");
@@ -40366,7 +42610,8 @@ static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs,
}
for (i = 0; i < totalCerts; i++) {
- secCert = ConvertToSecCertificateRef(certs[i].buffer, certs[i].length);
+ secCert =
+ ConvertToSecCertificateRef(certs[i].buffer, (int)certs[i].length);
if (!secCert) {
WOLFSSL_MSG("Error: can't convert DER cert to SecCertificateRef");
ret = 0;
@@ -40380,24 +42625,80 @@ static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs,
}
/* Create trust object for SecCertifiate Ref */
- policy = SecPolicyCreateSSL(true, NULL);
+ if (ssl->buffers.domainName.buffer && ssl->buffers.domainName.length > 0) {
+ /* Create policy with specified value to require host name match */
+ hostname = CFStringCreateWithCString(
+ kCFAllocatorDefault, (const char*)ssl->buffers.domainName.buffer,
+ kCFStringEncodingUTF8);
+ }
+ if (hostname != NULL) {
+ policy = SecPolicyCreateSSL(true, hostname);
+ }
+ else {
+ policy = SecPolicyCreateSSL(true, NULL);
+ }
status = SecTrustCreateWithCertificates(certArray, policy, &trust);
if (status != errSecSuccess) {
WOLFSSL_MSG_EX("Error creating trust object, "
- "SecTrustCreateWithCertificates returned %d",status);
+ "SecTrustCreateWithCertificates returned %d",
+ status);
ret = 0;
goto cleanup;
}
+#if defined(WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION)
+ /* TEST ONLY CODE:
+ * Set accumulated list of trusted CA certificates as trust anchors */
+ WOLFSSL_MSG("Setting anchor certificates");
+ if (ssl->ctx->testTrustedCAs != NULL) {
+ status = SecTrustSetAnchorCertificates(trust, ssl->ctx->testTrustedCAs);
+ if (status != errSecSuccess) {
+ WOLFSSL_MSG_EX("Error setting anchor certificates: %d", status);
+ ret = 0;
+ goto cleanup;
+ }
+ }
+#endif
+
/* Evaluate the certificate's authenticity */
- if (SecTrustEvaluateWithError(trust, NULL) == 1) {
- WOLFSSL_MSG("Cert chain is trusted");
- ret = 1;
+ WOLFSSL_MSG("Performing Apple native cert validation via "
+ "SecTrustEvaluateWithError");
+ ret = SecTrustEvaluateWithError(trust, &error);
+ if (ret != 1) {
+ if (error) {
+ CFIndex code;
+ code = CFErrorGetCode(error);
+ WOLFSSL_MSG_EX("SecTrustEvaluateWithError failed with code: %ld\n",
+ code);
+ DisplaySecTrustError(error, trust);
+
+#ifdef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION
+ /* TEST ONLY CODE:
+ * wolfSSL API tests use a cert with a validity period that is too
+ * long for the Apple system trust APIs
+ * (See: https://support.apple.com/en-us/103769)
+ * therefore we should skip over this particular error */
+ if (code == errSecCertificateValidityPeriodTooLong) {
+ if (MaxValidityPeriodErrorOnly(error)) {
+ WOLFSSL_MSG("Multiple reasons for validity period error, "
+ "not skipping");
+ ret = 0;
+ } else {
+ WOLFSSL_MSG("Skipping certificate validity period error");
+ ret = 1;
+ }
+ }
+#endif
+ (void)code;
+ CFRelease(error);
+ }
+ else {
+ WOLFSSL_MSG(
+ "SecTrustEvaluateWithError failed with unknown error.\n");
+ }
}
else {
- WOLFSSL_MSG("Cert chain trust evaluation failed"
- "SecTrustEvaluateWithError returned 0");
- ret = 0;
+ WOLFSSL_MSG("SecTrustEvaluateWithError succeeded");
}
/* Cleanup */
@@ -40411,13 +42712,48 @@ static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs,
if (policy) {
CFRelease(policy);
}
+ if (hostname) {
+ CFRelease(hostname);
+ }
WOLFSSL_LEAVE("DoAppleNativeCertValidation", ret);
return ret;
}
+
+#if defined(WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION)
+int wolfSSL_TestAppleNativeCertValidation_AppendCA(WOLFSSL_CTX* ctx,
+ const byte* derCert,
+ int derLen)
+{
+ SecCertificateRef certRef;
+
+ if (derCert == NULL || derLen == 0) {
+ return WOLFSSL_FAILURE;
+ }
+
+ /* Create the base array for trust anchors if it doesn't exist */
+ if (ctx->testTrustedCAs == NULL) {
+ ctx->testTrustedCAs =
+ CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (!ctx->testTrustedCAs) {
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ certRef = ConvertToSecCertificateRef(derCert, derLen);
+ if (!certRef) {
+ return false;
+ }
+
+ CFArrayAppendValue(ctx->testTrustedCAs, certRef);
+ CFRelease(certRef);
+ return WOLFSSL_SUCCESS;
+}
+#endif /* WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION */
+
#endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */
#undef ERROR_OUT
-#endif /* WOLFCRYPT_ONLY */
+#endif /* !WOLFCRYPT_ONLY */
diff --git a/src/src/keys.c b/src/src/keys.c
index fa04c4d..714d9dd 100644
--- a/src/src/keys.c
+++ b/src/src/keys.c
@@ -1,12 +1,12 @@
/* keys.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -22,13 +22,9 @@
/* Name change compatibility layer no longer needs to be included here */
-#ifdef HAVE_CONFIG_H
- #include
-#endif
-
-#include
+#include
-#ifndef WOLFCRYPT_ONLY
+#if !defined(WOLFCRYPT_ONLY) && !defined(NO_TLS)
#include
#include
@@ -105,7 +101,7 @@ int SetCipherSpecs(WOLFSSL* ssl)
* @param cipherSuite [in]
* @param specs [out] CipherSpecs
* @param opts [in/out] Options can be NULL
- * @return
+ * @return int (less than 0 on fail, 0 on success)
*/
int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
CipherSpecs* specs, Options* opts)
@@ -128,6 +124,9 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
}
#endif /* NO_WOLFSSL_CLIENT */
+ /* Initialize specs */
+ XMEMSET(specs, 0, sizeof(CipherSpecs));
+
/* Chacha extensions, 0xcc */
if (cipherSuite0 == CHACHA_BYTE) {
@@ -341,7 +340,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
specs->iv_size = AES_IV_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
break;
#endif
@@ -358,7 +357,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
specs->iv_size = AES_IV_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
break;
#endif
@@ -374,7 +373,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -431,7 +430,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -448,7 +447,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -466,7 +465,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -503,7 +502,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
if (opts != NULL)
@@ -530,7 +529,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
specs->iv_size = AES_IV_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
break;
#endif
@@ -547,7 +546,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
specs->iv_size = AES_IV_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
break;
#endif
@@ -601,7 +600,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -618,7 +617,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -635,7 +634,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -653,7 +652,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -671,8 +670,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_16_AUTH_SZ;
break;
@@ -689,8 +688,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_8_AUTH_SZ;
break;
@@ -707,8 +706,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_8_AUTH_SZ;
break;
@@ -747,7 +746,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->static_ecdh = 1;
specs->key_size = AES_128_KEY_SIZE;
specs->iv_size = AES_IV_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
break;
#endif
@@ -764,7 +763,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->static_ecdh = 1;
specs->key_size = AES_128_KEY_SIZE;
specs->iv_size = AES_IV_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
break;
#endif
@@ -781,7 +780,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->static_ecdh = 1;
specs->key_size = AES_256_KEY_SIZE;
specs->iv_size = AES_IV_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
break;
#endif
@@ -798,7 +797,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->static_ecdh = 1;
specs->key_size = AES_256_KEY_SIZE;
specs->iv_size = AES_IV_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
break;
#endif
@@ -814,7 +813,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 1;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -907,7 +906,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 1;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -924,7 +923,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 1;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -941,7 +940,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 1;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -958,7 +957,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 1;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -976,7 +975,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 1;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -994,7 +993,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 1;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1012,7 +1011,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 1;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1068,8 +1067,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_8_AUTH_SZ;
break;
@@ -1086,8 +1085,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_8_AUTH_SZ;
break;
@@ -1104,8 +1103,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_8_AUTH_SZ;
if (opts != NULL)
@@ -1124,8 +1123,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_8_AUTH_SZ;
if (opts != NULL)
@@ -1144,8 +1143,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_16_AUTH_SZ;
if (opts != NULL)
@@ -1164,8 +1163,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_16_AUTH_SZ;
if (opts != NULL)
@@ -1184,8 +1183,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_16_AUTH_SZ;
if (opts != NULL)
@@ -1204,8 +1203,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_IMP_IV_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_IMP_IV_SZ;
specs->aead_mac_size = AES_CCM_16_AUTH_SZ;
if (opts != NULL)
@@ -1219,8 +1218,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->bulk_cipher_algorithm = wolfssl_cipher_null;
specs->cipher_type = aead;
specs->mac_algorithm = sha256_mac;
- specs->kea = 0;
- specs->sig_algo = 0;
+ specs->kea = any_kea;
+ specs->sig_algo = any_sa_algo;
specs->hash_size = WC_SHA256_DIGEST_SIZE;
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
@@ -1237,8 +1236,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->bulk_cipher_algorithm = wolfssl_cipher_null;
specs->cipher_type = aead;
specs->mac_algorithm = sha384_mac;
- specs->kea = 0;
- specs->sig_algo = 0;
+ specs->kea = any_kea;
+ specs->sig_algo = any_sa_algo;
specs->hash_size = WC_SHA384_DIGEST_SIZE;
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
@@ -1267,13 +1266,13 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->bulk_cipher_algorithm = wolfssl_aes_gcm;
specs->cipher_type = aead;
specs->mac_algorithm = sha256_mac;
- specs->kea = 0;
- specs->sig_algo = 0;
+ specs->kea = any_kea;
+ specs->sig_algo = any_sa_algo;
specs->hash_size = WC_SHA256_DIGEST_SIZE;
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_NONCE_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1285,13 +1284,13 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->bulk_cipher_algorithm = wolfssl_aes_gcm;
specs->cipher_type = aead;
specs->mac_algorithm = sha384_mac;
- specs->kea = 0;
- specs->sig_algo = 0;
+ specs->kea = any_kea;
+ specs->sig_algo = any_sa_algo;
specs->hash_size = WC_SHA384_DIGEST_SIZE;
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_NONCE_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1303,8 +1302,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->bulk_cipher_algorithm = wolfssl_chacha;
specs->cipher_type = aead;
specs->mac_algorithm = sha256_mac;
- specs->kea = 0;
- specs->sig_algo = 0;
+ specs->kea = any_kea;
+ specs->sig_algo = any_sa_algo;
specs->hash_size = WC_SHA256_DIGEST_SIZE;
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
@@ -1323,14 +1322,14 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->bulk_cipher_algorithm = wolfssl_aes_ccm;
specs->cipher_type = aead;
specs->mac_algorithm = sha256_mac;
- specs->kea = 0;
- specs->sig_algo = 0;
+ specs->kea = any_kea;
+ specs->sig_algo = any_sa_algo;
specs->hash_size = WC_SHA256_DIGEST_SIZE;
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_NONCE_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_NONCE_SZ;
specs->aead_mac_size = AES_CCM_16_AUTH_SZ;
break;
@@ -1341,14 +1340,14 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->bulk_cipher_algorithm = wolfssl_aes_ccm;
specs->cipher_type = aead;
specs->mac_algorithm = sha256_mac;
- specs->kea = 0;
- specs->sig_algo = 0;
+ specs->kea = any_kea;
+ specs->sig_algo = any_sa_algo;
specs->hash_size = WC_SHA256_DIGEST_SIZE;
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
- specs->iv_size = AESGCM_NONCE_SZ;
+ specs->block_size = WC_AES_BLOCK_SIZE;
+ specs->iv_size = AESCCM_NONCE_SZ;
specs->aead_mac_size = AES_CCM_8_AUTH_SZ;
break;
@@ -1375,7 +1374,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1440,7 +1439,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->static_ecdh = 0;
specs->key_size = SM4_KEY_SIZE;
specs->block_size = SM4_BLOCK_SIZE;
- specs->iv_size = GCM_IMP_IV_SZ;
+ specs->iv_size = CCM_IMP_IV_SZ;
specs->aead_mac_size = SM4_CCM_AUTH_SZ;
break;
@@ -1467,8 +1466,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->bulk_cipher_algorithm = wolfssl_sm4_gcm;
specs->cipher_type = aead;
specs->mac_algorithm = sm3_mac;
- specs->kea = 0;
- specs->sig_algo = 0;
+ specs->kea = any_kea;
+ specs->sig_algo = any_sa_algo;
specs->hash_size = WC_SM3_DIGEST_SIZE;
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
@@ -1485,8 +1484,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->bulk_cipher_algorithm = wolfssl_sm4_ccm;
specs->cipher_type = aead;
specs->mac_algorithm = sm3_mac;
- specs->kea = 0;
- specs->sig_algo = 0;
+ specs->kea = any_kea;
+ specs->sig_algo = any_sa_algo;
specs->hash_size = WC_SM3_DIGEST_SIZE;
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
@@ -1564,7 +1563,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -1581,7 +1580,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -1649,7 +1648,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -1666,7 +1665,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -1683,7 +1682,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1703,7 +1702,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1723,7 +1722,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1743,7 +1742,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1763,7 +1762,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -1783,7 +1782,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
if (opts != NULL)
@@ -1802,7 +1801,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
if (opts != NULL)
@@ -1821,7 +1820,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
if (opts != NULL)
@@ -1840,7 +1839,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
if (opts != NULL)
@@ -1859,7 +1858,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
if (opts != NULL)
@@ -1878,7 +1877,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
if (opts != NULL)
@@ -1992,7 +1991,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -2026,7 +2025,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -2043,7 +2042,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -2060,7 +2059,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
break;
@@ -2077,7 +2076,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -2095,7 +2094,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -2113,7 +2112,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -2131,7 +2130,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_256_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AESGCM_IMP_IV_SZ;
specs->aead_mac_size = AES_GCM_AUTH_SZ;
@@ -2149,7 +2148,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = CAMELLIA_128_KEY_SIZE;
- specs->block_size = CAMELLIA_BLOCK_SIZE;
+ specs->block_size = WC_CAMELLIA_BLOCK_SIZE;
specs->iv_size = CAMELLIA_IV_SIZE;
break;
@@ -2166,7 +2165,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = CAMELLIA_256_KEY_SIZE;
- specs->block_size = CAMELLIA_BLOCK_SIZE;
+ specs->block_size = WC_CAMELLIA_BLOCK_SIZE;
specs->iv_size = CAMELLIA_IV_SIZE;
break;
@@ -2183,7 +2182,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = CAMELLIA_128_KEY_SIZE;
- specs->block_size = CAMELLIA_BLOCK_SIZE;
+ specs->block_size = WC_CAMELLIA_BLOCK_SIZE;
specs->iv_size = CAMELLIA_IV_SIZE;
break;
@@ -2200,7 +2199,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = CAMELLIA_256_KEY_SIZE;
- specs->block_size = CAMELLIA_BLOCK_SIZE;
+ specs->block_size = WC_CAMELLIA_BLOCK_SIZE;
specs->iv_size = CAMELLIA_IV_SIZE;
break;
@@ -2217,7 +2216,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = CAMELLIA_128_KEY_SIZE;
- specs->block_size = CAMELLIA_BLOCK_SIZE;
+ specs->block_size = WC_CAMELLIA_BLOCK_SIZE;
specs->iv_size = CAMELLIA_IV_SIZE;
break;
@@ -2234,7 +2233,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = CAMELLIA_256_KEY_SIZE;
- specs->block_size = CAMELLIA_BLOCK_SIZE;
+ specs->block_size = WC_CAMELLIA_BLOCK_SIZE;
specs->iv_size = CAMELLIA_IV_SIZE;
break;
@@ -2251,7 +2250,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = CAMELLIA_128_KEY_SIZE;
- specs->block_size = CAMELLIA_BLOCK_SIZE;
+ specs->block_size = WC_CAMELLIA_BLOCK_SIZE;
specs->iv_size = CAMELLIA_IV_SIZE;
break;
@@ -2268,7 +2267,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = CAMELLIA_256_KEY_SIZE;
- specs->block_size = CAMELLIA_BLOCK_SIZE;
+ specs->block_size = WC_CAMELLIA_BLOCK_SIZE;
specs->iv_size = CAMELLIA_IV_SIZE;
break;
@@ -2285,7 +2284,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
specs->pad_size = PAD_SHA;
specs->static_ecdh = 0;
specs->key_size = AES_128_KEY_SIZE;
- specs->block_size = AES_BLOCK_SIZE;
+ specs->block_size = WC_AES_BLOCK_SIZE;
specs->iv_size = AES_IV_SIZE;
if (opts != NULL)
@@ -2371,7 +2370,7 @@ static int SetPrefix(byte* sha_input, int idx)
#endif
-static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
+int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
int side, void* heap, int devId, WC_RNG* rng, int tls13)
{
(void)rng;
@@ -2976,13 +2975,13 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
if (enc && enc->cam == NULL)
enc->cam =
- (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER);
+ (wc_Camellia*)XMALLOC(sizeof(wc_Camellia), heap, DYNAMIC_TYPE_CIPHER);
if (enc && enc->cam == NULL)
return MEMORY_E;
if (dec && dec->cam == NULL)
dec->cam =
- (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER);
+ (wc_Camellia*)XMALLOC(sizeof(wc_Camellia), heap, DYNAMIC_TYPE_CIPHER);
if (dec && dec->cam == NULL)
return MEMORY_E;
@@ -3318,9 +3317,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
DYNAMIC_TYPE_CIPHER);
if (enc->hmac == NULL)
return MEMORY_E;
- }
- if (enc) {
if (wc_HmacInit(enc->hmac, heap, devId) != 0) {
WOLFSSL_MSG("HmacInit failed in SetKeys");
XFREE(enc->hmac, heap, DYNAMIC_TYPE_CIPHER);
@@ -3334,9 +3331,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
DYNAMIC_TYPE_CIPHER);
if (dec->hmac == NULL)
return MEMORY_E;
- }
- if (dec) {
if (wc_HmacInit(dec->hmac, heap, devId) != 0) {
WOLFSSL_MSG("HmacInit failed in SetKeys");
XFREE(dec->hmac, heap, DYNAMIC_TYPE_CIPHER);
@@ -3559,9 +3554,17 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
ret = PROTOCOLCB_UNAVAILABLE;
if (ssl->ctx->EncryptKeysCb) {
void* ctx = wolfSSL_GetEncryptKeysCtx(ssl);
+ #if defined(WOLFSSL_RENESAS_FSPSM_TLS)
+ FSPSM_ST* cbInfo = (FSPSM_ST*)ctx;
+ cbInfo->internal->side = side;
+ #elif defined(WOLFSSL_RENESAS_TSIP_TLS)
+ TsipUserCtx* cbInfo = (TsipUserCtx*)ctx;
+ cbInfo->internal->key_side = side;
+ #endif
ret = ssl->ctx->EncryptKeysCb(ssl, ctx);
}
- if (!ssl->ctx->EncryptKeysCb || ret == PROTOCOLCB_UNAVAILABLE)
+ if (!ssl->ctx->EncryptKeysCb ||
+ ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE))
#endif
{
ret = SetKeys(wc_encrypt, wc_decrypt, keys, &ssl->specs, ssl->options.side,
@@ -3668,7 +3671,8 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
/* TLS can call too */
int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
{
- int sz, i = 0;
+ size_t sz;
+ int i = 0;
Keys* keys = &ssl->keys;
#ifdef WOLFSSL_DTLS
/* In case of DTLS, ssl->keys is updated here */
@@ -3712,7 +3716,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz);
XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz);
#endif
- i += sz;
+ i += (int)sz;
}
sz = ssl->specs.key_size;
#ifdef WOLFSSL_DTLS
@@ -3725,7 +3729,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
#endif
XMEMCPY(keys->client_write_key, &keyData[i], sz);
XMEMCPY(keys->server_write_key, &keyData[i], sz);
- i += sz;
+ i += (int)sz;
sz = ssl->specs.iv_size;
#ifdef WOLFSSL_DTLS
@@ -3767,7 +3771,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
#endif
XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz);
#endif
- i += sz;
+ i += (int)sz;
}
if (side & PROVISION_SERVER) {
#ifndef WOLFSSL_AEAD_ONLY
@@ -3778,7 +3782,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
#endif
XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz);
#endif
- i += sz;
+ i += (int)sz;
}
}
sz = ssl->specs.key_size;
@@ -3789,7 +3793,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
keys->client_write_key, sz);
#endif
XMEMCPY(keys->client_write_key, &keyData[i], sz);
- i += sz;
+ i += (int)sz;
}
if (side & PROVISION_SERVER) {
#ifdef WOLFSSL_DTLS
@@ -3798,7 +3802,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
keys->server_write_key, sz);
#endif
XMEMCPY(keys->server_write_key, &keyData[i], sz);
- i += sz;
+ i += (int)sz;
}
sz = ssl->specs.iv_size;
@@ -3809,7 +3813,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side)
keys->client_write_IV, sz);
#endif
XMEMCPY(keys->client_write_IV, &keyData[i], sz);
- i += sz;
+ i += (int)sz;
}
if (side & PROVISION_SERVER) {
#ifdef WOLFSSL_DTLS
@@ -3874,12 +3878,12 @@ int DeriveKeys(WOLFSSL* ssl)
if (shaOutput == NULL || md5Input == NULL || shaInput == NULL ||
keyData == NULL || md5 == NULL || sha == NULL) {
- if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (md5Input) XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (shaInput) XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (keyData) XFREE(keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
@@ -3910,7 +3914,8 @@ int DeriveKeys(WOLFSSL* ssl)
XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN);
if (ret == 0) {
ret = wc_ShaUpdate(sha, shaInput,
- (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - KEY_PREFIX + j);
+ (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - KEY_PREFIX +
+ (word32)(j));
}
if (ret == 0) {
ret = wc_ShaFinal(sha, shaOutput);
@@ -3929,14 +3934,12 @@ int DeriveKeys(WOLFSSL* ssl)
ret = StoreKeys(ssl, keyData, PROVISION_CLIENT_SERVER);
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
@@ -3944,12 +3947,13 @@ int DeriveKeys(WOLFSSL* ssl)
static int CleanPreMaster(WOLFSSL* ssl)
{
- int i, ret, sz = ssl->arrays->preMasterSz;
+ int i, ret, sz = (int)(ssl->arrays->preMasterSz);
for (i = 0; i < sz; i++)
ssl->arrays->preMasterSecret[i] = 0;
- ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret, sz);
+ ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret,
+ (word32)(sz));
if (ret != 0)
return ret;
@@ -4011,11 +4015,11 @@ static int MakeSslMasterSecret(WOLFSSL* ssl)
if (shaOutput == NULL || md5Input == NULL || shaInput == NULL ||
md5 == NULL || sha == NULL) {
- if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (md5Input) XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (shaInput) XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
@@ -4037,8 +4041,8 @@ static int MakeSslMasterSecret(WOLFSSL* ssl)
}
idx = 0;
- XMEMCPY(shaInput, prefix, i + 1);
- idx += i + 1;
+ XMEMCPY(shaInput, prefix, (size_t)(i + 1));
+ idx += (word32)(i + 1);
XMEMCPY(shaInput + idx, ssl->arrays->preMasterSecret, pmsSz);
idx += pmsSz;
@@ -4078,13 +4082,11 @@ static int MakeSslMasterSecret(WOLFSSL* ssl)
ret = DeriveKeys(ssl);
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (ret == 0)
ret = CleanPreMaster(ssl);
@@ -4111,4 +4113,4 @@ int MakeMasterSecret(WOLFSSL* ssl)
#endif
}
-#endif /* WOLFCRYPT_ONLY */
+#endif /* !WOLFCRYPT_ONLY && !NO_TLS */
diff --git a/src/src/ocsp.c b/src/src/ocsp.c
index c56ec22..2348af7 100644
--- a/src/src/ocsp.c
+++ b/src/src/ocsp.c
@@ -1,12 +1,12 @@
/* ocsp.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,15 +19,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+#include
/* Name change compatibility layer no longer needs to be included here */
-#ifdef HAVE_CONFIG_H
- #include
-#endif
-
-#include
-
/*
* WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK:
* Disable looking for an authorized responder in the verification path of
@@ -49,6 +44,63 @@
#include
#endif
+/* Allocates and initializes a WOLFSSL_OCSP object. Returns pointer on success, NULL on failure. */
+WOLFSSL_OCSP* wc_NewOCSP(WOLFSSL_CERT_MANAGER* cm)
+{
+ WOLFSSL_OCSP* ocsp = NULL;
+ ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm ? cm->heap : NULL, DYNAMIC_TYPE_OCSP);
+ if (ocsp == NULL)
+ return NULL;
+ if (InitOCSP(ocsp, cm) != 0) {
+ XFREE(ocsp, cm ? cm->heap : NULL, DYNAMIC_TYPE_OCSP);
+ return NULL;
+ }
+ return ocsp;
+}
+
+/* Frees a WOLFSSL_OCSP object allocated by wc_NewOCSP. */
+void wc_FreeOCSP(WOLFSSL_OCSP* ocsp)
+{
+ if (ocsp) {
+ FreeOCSP(ocsp, 1);
+ }
+}
+
+int wc_CheckCertOcspResponse(WOLFSSL_OCSP *ocsp, DecodedCert *cert,
+ byte *response, int responseSz, void* heap)
+{
+ int ret = WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E);
+
+#ifdef WOLFSSL_SMALL_STACK
+ OcspRequest* ocspRequest;
+#else
+ OcspRequest ocspRequest[1];
+#endif
+
+
+#ifdef WOLFSSL_SMALL_STACK
+ ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (ocspRequest == NULL) {
+ WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
+ return MEMORY_E;
+ }
+#endif
+
+ if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
+ ocsp->cm->heap) == 0) {
+ ret = CheckOcspResponse(ocsp, response, responseSz, NULL, NULL, NULL,
+ ocspRequest, heap);
+ FreeOcspRequest(ocspRequest);
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ WOLFSSL_LEAVE("CheckCertOCSP", ret);
+ return ret;
+}
int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
{
@@ -90,8 +142,7 @@ static void FreeOcspEntry(OcspEntry* entry, void* heap)
for (status = entry->status; status; status = next) {
next = status->next;
- if (status->rawOcspResponse)
- XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS);
+ XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS);
#ifdef OPENSSL_EXTRA
if (status->serialInt) {
@@ -144,13 +195,9 @@ static int xstat2err(int st)
int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, WOLFSSL* ssl)
{
- int ret = OCSP_LOOKUP_FAIL;
+ int ret = WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL);
-#ifdef WOLFSSL_SMALL_STACK
- OcspRequest* ocspRequest;
-#else
- OcspRequest ocspRequest[1];
-#endif
+ WC_DECLARE_VAR(ocspRequest, OcspRequest, 1, 0);
WOLFSSL_ENTER("CheckCertOCSP");
@@ -172,9 +219,7 @@ int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, WOLFSSL* ssl)
FreeOcspRequest(ocspRequest);
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
WOLFSSL_LEAVE("CheckCertOCSP", ret);
return ret;
@@ -227,7 +272,7 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
OcspEntry* entry, CertStatus** status, buffer* responseBuffer,
void* heap)
{
- int ret = OCSP_INVALID_STATUS;
+ int ret = WC_NO_ERR_TRACE(OCSP_INVALID_STATUS);
WOLFSSL_ENTER("GetOcspStatus");
@@ -241,7 +286,7 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
for (*status = entry->status; *status; *status = (*status)->next)
if ((*status)->serialSz == request->serialSz
- && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz))
+ && !XMEMCMP((*status)->serial, request->serial, (size_t)(*status)->serialSz))
break;
if (responseBuffer && *status && !(*status)->rawOcspResponse) {
@@ -251,10 +296,10 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
else if (*status) {
#ifndef NO_ASN_TIME
if (XVALIDATE_DATE((*status)->thisDate,
- (*status)->thisDateFormat, BEFORE)
+ (*status)->thisDateFormat, ASN_BEFORE)
&& ((*status)->nextDate[0] != 0)
&& XVALIDATE_DATE((*status)->nextDate,
- (*status)->nextDateFormat, AFTER))
+ (*status)->nextDateFormat, ASN_AFTER))
#endif
{
ret = xstat2err((*status)->status);
@@ -284,7 +329,7 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
* ocsp Context object for OCSP status.
* response OCSP response message data.
* responseSz Length of OCSP response message data.
- * reponseBuffer Buffer object to return the response with.
+ * responseBuffer Buffer object to return the response with.
* status The certificate status object.
* entry The OCSP entry for this certificate.
* ocspRequest Request corresponding to response.
@@ -318,18 +363,23 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
DYNAMIC_TYPE_OCSP_REQUEST);
if (newStatus == NULL || newSingle == NULL || ocspResponse == NULL) {
- if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS);
- if (newSingle) XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
- if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
+ XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS);
+ XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
+ XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
return MEMORY_E;
}
#endif
- InitOcspResponse(ocspResponse, newSingle, newStatus, response, responseSz,
- ocsp->cm->heap);
-
- ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
+ InitOcspResponse(ocspResponse, newSingle, newStatus, response,
+ (word32)responseSz, ocsp->cm->heap);
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ if (ocspRequest != NULL && ocspRequest->ssl != NULL &&
+ TLSX_CSR2_IsMulti(((WOLFSSL*)ocspRequest->ssl)->extensions)) {
+ ocspResponse->pendingCAs = TLSX_CSR2_GetPendingSigners(((WOLFSSL*)ocspRequest->ssl)->extensions);
+ }
+#endif
+ ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0, 0);
if (ret != 0) {
ocsp->error = ret;
WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error);
@@ -350,12 +400,12 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
}
if (responseBuffer) {
- responseBuffer->buffer = (byte*)XMALLOC(responseSz, heap,
+ responseBuffer->buffer = (byte*)XMALLOC((size_t)responseSz, heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (responseBuffer->buffer) {
- responseBuffer->length = responseSz;
- XMEMCPY(responseBuffer->buffer, response, responseSz);
+ responseBuffer->length = (unsigned int)responseSz;
+ XMEMCPY(responseBuffer->buffer, response, (size_t)responseSz);
}
}
@@ -370,16 +420,13 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
}
if (status != NULL) {
- if (status->rawOcspResponse) {
- XFREE(status->rawOcspResponse, ocsp->cm->heap,
- DYNAMIC_TYPE_OCSP_STATUS);
- }
+ XFREE(status->rawOcspResponse, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
/* Replace existing certificate entry with updated */
ocspResponse->single->status->next = status->next;
XMEMCPY(status, ocspResponse->single->status, sizeof(CertStatus));
}
- else {
+ else if (entry != NULL) {
/* Save new certificate entry */
status = (CertStatus*)XMALLOC(sizeof(CertStatus),
ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
@@ -410,10 +457,10 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
if (ret == 0 && validated == 1) {
WOLFSSL_MSG("New OcspResponse validated");
}
- else if (ret == OCSP_CERT_REVOKED) {
+ else if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED)) {
WOLFSSL_MSG("OCSP revoked");
}
- else if (ret == OCSP_CERT_UNKNOWN) {
+ else if (ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN)) {
WOLFSSL_MSG("OCSP unknown");
}
else {
@@ -422,11 +469,9 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
}
FreeOcspResponse(ocspResponse);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS);
- XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
- XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
-#endif
+ WC_FREE_VAR_EX(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS);
+ WC_FREE_VAR_EX(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
+ WC_FREE_VAR_EX(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
return ret;
}
@@ -466,7 +511,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer,
heap);
- if (ret != OCSP_INVALID_STATUS)
+ if (ret != WC_NO_ERR_TRACE(OCSP_INVALID_STATUS))
return ret;
if (responseBuffer) {
@@ -479,32 +524,6 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
- if (ocsp->statusCb != NULL && ssl != NULL) {
- WOLFSSL_MSG("Calling ocsp->statusCb");
- ret = ocsp->statusCb(ssl, ioCtx);
- switch (ret) {
- case SSL_TLSEXT_ERR_OK:
- ret = wolfSSL_get_ocsp_response(ssl, &response);
- ret = CheckOcspResponse(ocsp, response, ret, responseBuffer,
- status, entry, NULL, heap);
- if (response != NULL)
- XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
- break;
- case SSL_TLSEXT_ERR_NOACK:
- ret = OCSP_LOOKUP_FAIL;
- break;
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- default:
- WOLFSSL_LEAVE("CheckOcspRequest", ocsp->error);
- ret = WOLFSSL_FATAL_ERROR;
- break;
- }
- WOLFSSL_LEAVE("CheckOcspRequest", ret);
- return ret;
- }
-#endif
-
if (ocsp->cm->ocspUseOverrideURL) {
url = ocsp->cm->ocspOverrideURL;
if (url != NULL && url[0] != '\0')
@@ -522,20 +541,23 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
return 0;
}
- request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
+ request = (byte*)XMALLOC((size_t)requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
if (request == NULL) {
WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
return MEMORY_ERROR;
}
- requestSz = EncodeOcspRequest(ocspRequest, request, requestSz);
+ requestSz = EncodeOcspRequest(ocspRequest, request, (word32)requestSz);
if (requestSz > 0 && ocsp->cm->ocspIOCb) {
responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz,
request, requestSz, &response);
}
- if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) {
+ if (responseSz == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ)) {
ret = OCSP_WANT_READ;
}
+ else if (responseSz == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_TIMEOUT)){
+ ret = HTTP_TIMEOUT;
+ }
XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
@@ -555,7 +577,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert,
- void* vp) {
+ void* vp, Signer* pendingCAs) {
/* Attempt to build a chain up to cert's issuer */
WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
Signer* ca = NULL;
@@ -574,8 +596,16 @@ static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert,
/* End loop if no more issuers found or if we have found a self
* signed cert (ca == prev) */
- for (ca = GetCAByName(cm, single->issuerHash); ca != NULL && ca != prev;
- prev = ca, ca = GetCAByName(cm, ca->issuerNameHash)) {
+ ca = GetCAByName(cm, single->issuerHash);
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ if (ca == NULL && pendingCAs != NULL) {
+ ca = findSignerByName(pendingCAs, single->issuerHash);
+ }
+#else
+ (void)pendingCAs;
+#endif
+ for (; ca != NULL && ca != prev;
+ prev = ca) {
if (XMEMCMP(cert->issuerHash, ca->issuerNameHash,
OCSP_DIGEST_SIZE) == 0) {
WOLFSSL_MSG("\tOCSP Response signed by authorized "
@@ -584,6 +614,12 @@ static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert,
passed = 1;
break;
}
+ ca = GetCAByName(cm, ca->issuerNameHash);
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+ if (ca == NULL && pendingCAs != NULL) {
+ ca = findSignerByName(pendingCAs, single->issuerHash);
+ }
+#endif
}
return passed;
}
@@ -632,16 +668,13 @@ int CheckOcspResponder(OcspResponse *bs, DecodedCert *cert, void* vp)
}
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK
else if (vp != NULL) {
- passed = CheckOcspResponderChain(single, cert, vp);
+ passed = CheckOcspResponderChain(single, cert, vp, bs->pendingCAs);
}
#endif
}
if (!passed) {
WOLFSSL_MSG("\tOCSP Responder not authorized");
-#ifdef OPENSSL_EXTRA
- bs->verifyError = OCSP_BAD_ISSUER;
-#endif
ret = BAD_OCSP_RESPONDER;
break;
}
@@ -649,8 +682,9 @@ int CheckOcspResponder(OcspResponse *bs, DecodedCert *cert, void* vp)
return ret;
}
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
- defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIGHTY)
+
+/* compatibility layer OCSP functions */
+#ifdef OPENSSL_EXTRA
int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
WOLFSSL_OCSP_CERTID* id, int* status, int* reason,
WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd,
@@ -663,7 +697,7 @@ int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
single = bs->single;
while (single != NULL) {
- if ((XMEMCMP(single->status->serial, id->status->serial, single->status->serialSz) == 0)
+ if ((XMEMCMP(single->status->serial, id->status->serial, (size_t)single->status->serialSz) == 0)
&& (XMEMCMP(single->issuerHash, id->issuerHash, OCSP_DIGEST_SIZE) == 0)
&& (XMEMCMP(single->issuerKeyHash, id->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) {
break;
@@ -676,10 +710,17 @@ int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
if (status != NULL)
*status = single->status->status;
+#ifdef WOLFSSL_OCSP_PARSE_STATUS
if (thisupd != NULL)
*thisupd = &single->status->thisDateParsed;
if (nextupd != NULL)
*nextupd = &single->status->nextDateParsed;
+#else
+ if (thisupd != NULL)
+ *thisupd = NULL;
+ if (nextupd != NULL)
+ *nextupd = NULL;
+#endif
/* TODO: Not needed for Nginx or httpd */
if (reason != NULL)
@@ -730,13 +771,19 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
WOLFSSL_CERT_MANAGER* cm = NULL;
int ret = -1;
DerBuffer* derCert = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- DecodedCert *cert = NULL;
-#else
- DecodedCert cert[1];
-#endif
+ int dgstType;
+ WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
- (void)dgst;
+ if (dgst == NULL) {
+ dgstType = WC_HASH_TYPE_SHA;
+ }
+ else if (wolfSSL_EVP_get_hashinfo(dgst, &dgstType, NULL) !=
+ WOLFSSL_SUCCESS) {
+ return NULL;
+ }
+
+ if (dgstType != OCSP_DIGEST)
+ return NULL;
cm = wolfSSL_CertManagerNew();
if (cm == NULL
@@ -744,11 +791,8 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
|| issuer == NULL || issuer->derCert == NULL)
goto out;
-#ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert *)XMALLOC(sizeof(*cert), cm->heap, DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- goto out;
-#endif
+ WC_ALLOC_VAR_EX(cert, DecodedCert, 1, cm->heap, DYNAMIC_TYPE_DCERT,
+ goto out);
ret = AllocDer(&derCert, issuer->derCert->length,
issuer->derCert->type, NULL);
@@ -783,14 +827,15 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
InitDecodedCert(cert, subject->derCert->buffer,
subject->derCert->length, NULL);
- if (ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) {
+ if (ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm, NULL) != 0) {
FreeDecodedCert(cert);
goto out;
}
else {
+ certId->hashAlgoOID = wc_HashGetOID(OCSP_DIGEST);
XMEMCPY(certId->issuerHash, cert->issuerHash, OCSP_DIGEST_SIZE);
XMEMCPY(certId->issuerKeyHash, cert->issuerKeyHash, OCSP_DIGEST_SIZE);
- XMEMCPY(certId->status->serial, cert->serial, cert->serialSz);
+ XMEMCPY(certId->status->serial, cert->serial, (size_t)cert->serialSz);
certId->status->serialSz = cert->serialSz;
FreeDecodedCert(cert);
}
@@ -802,16 +847,15 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
if (ret != 0) {
if (derCert != NULL)
FreeDer(&derCert);
- if (certId != NULL) {
+ if (cm != NULL) {
XFREE(certId, cm->heap, DYNAMIC_TYPE_OPENSSL);
certId = NULL;
- }
- if (certStatus)
XFREE(certStatus, cm->heap, DYNAMIC_TYPE_OPENSSL);
+ }
}
#ifdef WOLFSSL_SMALL_STACK
- if (cert != NULL)
+ if (cm != NULL)
XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
#endif
@@ -826,85 +870,240 @@ void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
wolfSSL_OCSP_RESPONSE_free(basicResponse);
}
-/* Signature verified in DecodeBasicOcspResponse.
- * But no store available to verify certificate. */
-int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs,
- WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags)
+/* Calculate ancode CertID DER encoding following RFC 6960:
+ CertID ::= SEQUENCE {
+ hashAlgorithm AlgorithmIdentifier,
+ issuerNameHash OCTET STRING,
+ issuerKeyHash OCTET STRING,
+ serialNumber CertificateSerialNumber }
+*/
+static int OcspEncodeCertID(WOLFSSL_OCSP_CERTID* id, byte* output,
+ word32* totalSz, word32* intSize)
{
- int ret = WOLFSSL_FAILURE;
-#ifdef WOLFSSL_SMALL_STACK
- DecodedCert *cert;
-#else
- DecodedCert cert[1];
-#endif
- byte certInit = 0;
- int idx;
+ word32 idx = 0;
+ int ret;
- (void)certs;
+ if (id == NULL || totalSz == NULL || intSize == NULL ||
+ (output != NULL && (*totalSz == 0 || *totalSz <= *intSize)))
+ return BAD_FUNC_ARG;
- if (flags & OCSP_NOVERIFY)
- return WOLFSSL_SUCCESS;
+ if (output != NULL) {
+ ret = SetSequence(*intSize, output);
+ if (ret < 0)
+ return ret;
+ idx += ret;
+ }
-#ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert *)
- XMALLOC(sizeof(*cert), (st && st->cm) ? st->cm->heap : NULL,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return WOLFSSL_FAILURE;
-#endif
+ ret = SetAlgoID(id->hashAlgoOID, ((output != NULL) ? output + idx : output),
+ oidHashType, 0);
+ if (ret <= 0)
+ return -1;
+ idx += ret;
-#ifdef OPENSSL_EXTRA
- if (bs->verifyError != OCSP_VERIFY_ERROR_NONE)
- goto out;
-#endif
+ /* issuerNameHash */
+ ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output));
+ if (ret < 0)
+ return ret;
+ idx += ret;
+ if (output != NULL)
+ XMEMCPY(output + idx, id->issuerHash, OCSP_DIGEST_SIZE);
+ idx += OCSP_DIGEST_SIZE;
+
+ /* issuerKeyHash */
+ ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output));
+ if (ret < 0)
+ return ret;
+ idx += ret;
+ if (output != NULL)
+ XMEMCPY(output + idx, id->issuerKeyHash, OCSP_DIGEST_SIZE);
+ idx += OCSP_DIGEST_SIZE;
+
+ /* serialNumber */
+ ret = SetASNInt(id->status->serialSz, id->status->serial[0], ((output != NULL) ? output + idx : output));
+ if (ret < 0)
+ return ret;
+ idx += ret;
+ if (output != NULL)
+ XMEMCPY(output + idx, id->status->serial, id->status->serialSz);
+ idx += id->status->serialSz;
- if (flags & OCSP_TRUSTOTHER) {
- for (idx = 0; idx < wolfSSL_sk_X509_num(certs); idx++) {
- WOLFSSL_X509* x = wolfSSL_sk_X509_value(certs, idx);
- int derSz = 0;
- const byte* der = wolfSSL_X509_get_der(x, &derSz);
- if (der != NULL && derSz == (int)bs->certSz &&
- XMEMCMP(bs->cert, der, derSz) == 0) {
- ret = WOLFSSL_SUCCESS;
- goto out;
- }
+ if (output == NULL) {
+ *intSize = idx;
+ ret = SetSequence(idx, NULL);
+ if (ret < 0)
+ return ret;
+ idx += ret;
+ *totalSz = idx;
+ }
+ else if (idx != *totalSz) {
+ return BUFFER_E;
+ }
+
+ return 0;
+}
+
+static int OcspRespIdMatches(OcspResponse* resp, const byte* NameHash,
+ const byte* keyHash)
+{
+ if (resp->responderIdType == OCSP_RESPONDER_ID_NAME) {
+ return XMEMCMP(NameHash, resp->responderId.nameHash,
+ SIGNER_DIGEST_SIZE) == 0;
+ }
+ else if (resp->responderIdType == OCSP_RESPONDER_ID_KEY) {
+ return XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0;
+ }
+
+ return 0;
+}
+
+static int OcspFindSigner(WOLFSSL_OCSP_BASICRESP *resp,
+ WOLF_STACK_OF(WOLFSSL_X509) *certs, DecodedCert **signer, int *embedded,
+ unsigned long flags)
+{
+ WOLFSSL_X509 *signer_x509 = NULL;
+ DecodedCert *certDecoded;
+ int i;
+
+ certDecoded = (DecodedCert *)XMALLOC(sizeof(*certDecoded), resp->heap,
+ DYNAMIC_TYPE_DCERT);
+ if (certDecoded == NULL)
+ return MEMORY_E;
+
+ for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) {
+ signer_x509 = wolfSSL_sk_X509_value(certs, i);
+ if (signer_x509 == NULL)
+ continue;
+
+ InitDecodedCert(certDecoded, signer_x509->derCert->buffer,
+ signer_x509->derCert->length, resp->heap);
+ if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY,
+ NULL, NULL) == 0) {
+ if (OcspRespIdMatches(resp, certDecoded->subjectHash,
+ certDecoded->subjectKeyHash)) {
+ *signer = certDecoded;
+ *embedded = 0;
+ return 0;
+ }
}
+ FreeDecodedCert(certDecoded);
}
- InitDecodedCert(cert, bs->cert, bs->certSz, NULL);
- certInit = 1;
- if (ParseCertRelative(cert, CERT_TYPE, VERIFY, st->cm) < 0)
- goto out;
+ if (flags & WOLFSSL_OCSP_NOINTERN) {
+ XFREE(certDecoded, resp->heap, DYNAMIC_TYPE_DCERT);
+ return ASN_NO_SIGNER_E;
+ }
- if (!(flags & OCSP_NOCHECKS)) {
- if (CheckOcspResponder(bs, cert, st->cm) != 0)
- goto out;
+ /* not found in certs, search the cert embedded in the response */
+ InitDecodedCert(certDecoded, resp->cert, resp->certSz, resp->heap);
+ if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY, NULL, NULL) == 0) {
+ if (OcspRespIdMatches(resp, certDecoded->subjectHash,
+ certDecoded->subjectKeyHash)) {
+ *signer = certDecoded;
+ *embedded = 1;
+ return 0;
+ }
}
+ FreeDecodedCert(certDecoded);
- ret = WOLFSSL_SUCCESS;
-out:
- if (certInit)
- FreeDecodedCert(cert);
+ XFREE(certDecoded, resp->heap, DYNAMIC_TYPE_DCERT);
+ return ASN_NO_SIGNER_E;
+}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, (st && st->cm) ? st->cm->heap : NULL, DYNAMIC_TYPE_DCERT);
+static int OcspVerifySigner(WOLFSSL_OCSP_BASICRESP *resp, DecodedCert *cert,
+ WOLFSSL_X509_STORE *st, unsigned long flags)
+{
+ WC_DECLARE_VAR(c, DecodedCert, 1, 0);
+
+ int ret = -1;
+ if (st == NULL)
+ return ASN_OCSP_CONFIRM_E;
+
+ WC_ALLOC_VAR_EX(c, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
+ return MEMORY_E);
+
+ InitDecodedCert(c, cert->source, cert->maxIdx, NULL);
+ if (ParseCertRelative(c, CERT_TYPE, VERIFY, st->cm, NULL) != 0) {
+ ret = ASN_OCSP_CONFIRM_E;
+ goto err;
+ }
+#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
+ if ((flags & WOLFSSL_OCSP_NOCHECKS) == 0) {
+ ret = CheckOcspResponder(resp, c, st->cm);
+ }
+ else {
+ ret = 0;
+ }
+#else
+ (void)resp;
+ (void)flags;
+ ret = 0;
#endif
+err:
+ FreeDecodedCert(c);
+ WC_FREE_VAR_EX(c, NULL, DYNAMIC_TYPE_DCERT);
return ret;
}
+/* Signature verified in DecodeBasicOcspResponse.
+ * But no store available to verify certificate. */
+int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP* bs,
+ WOLF_STACK_OF(WOLFSSL_X509) * certs, WOLFSSL_X509_STORE* st,
+ unsigned long flags)
+{
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ int embedded;
+ DecodedCert *cert = NULL;
+
+ ret = OcspFindSigner(bs, certs, &cert, &embedded, flags);
+ if (ret != 0) {
+ WOLFSSL_MSG("OCSP no signer found");
+ return WOLFSSL_FAILURE;
+ }
+
+ /* skip certificate verification if cert in certs and TRUST_OTHER is true */
+ if (!embedded && (flags & WOLFSSL_OCSP_TRUSTOTHER) != 0)
+ flags |= WOLFSSL_OCSP_NOVERIFY;
+
+ /* verify response signature */
+ ret = ConfirmSignature(
+ &cert->sigCtx,
+ bs->response, bs->responseSz,
+ cert->publicKey, cert->pubKeySize, cert->keyOID,
+ bs->sig, bs->sigSz, bs->sigOID, bs->sigParams, bs->sigParamsSz,
+ NULL);
+
+ if (ret != 0) {
+ WOLFSSL_MSG("OCSP signature verification failed");
+ ret = -1;
+ goto err;
+ }
+
+ if ((flags & WOLFSSL_OCSP_NOVERIFY) == 0) {
+ ret = OcspVerifySigner(bs, cert, st, flags);
+ }
+
+err:
+ FreeDecodedCert(cert);
+ XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
+ return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
{
+ OcspEntry *s, *sNext;
if (response == NULL)
return;
- if (response->single != NULL) {
- FreeOcspEntry(response->single, NULL);
- XFREE(response->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
+
+ s = response->single;
+ while (s != NULL) {
+ sNext = s->next;
+ FreeOcspEntry(s, NULL);
+ XFREE(s, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
+ s = sNext;
}
- if (response->source != NULL)
- XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
}
@@ -933,18 +1132,18 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
long fcur;
long flen;
- if (bio->ptr == NULL)
+ if (bio->ptr.fh == NULL)
return NULL;
- fcur = XFTELL((XFILE)bio->ptr);
+ fcur = XFTELL(bio->ptr.fh);
if (fcur < 0)
return NULL;
- if(XFSEEK((XFILE)bio->ptr, 0, SEEK_END) != 0)
+ if(XFSEEK(bio->ptr.fh, 0, SEEK_END) != 0)
return NULL;
- flen = XFTELL((XFILE)bio->ptr);
+ flen = XFTELL(bio->ptr.fh);
if (flen < 0)
return NULL;
- if (XFSEEK((XFILE)bio->ptr, fcur, SEEK_SET) != 0)
+ if (XFSEEK(bio->ptr.fh, fcur, SEEK_SET) != 0)
return NULL;
/* check calculated length */
@@ -952,7 +1151,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
if (fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0)
return NULL;
- data = (byte*)XMALLOC(fcur, 0, DYNAMIC_TYPE_TMP_BUFFER);
+ data = (byte*)XMALLOC((size_t)fcur, 0, DYNAMIC_TYPE_TMP_BUFFER);
if (data == NULL)
return NULL;
dataAlloced = 1;
@@ -997,7 +1196,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
XMEMSET(resp, 0, sizeof(OcspResponse));
}
- resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ resp->source = (byte*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (resp->source == NULL) {
XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
return NULL;
@@ -1021,19 +1220,22 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
}
XMEMSET(resp->single->status, 0, sizeof(CertStatus));
- XMEMCPY(resp->source, *data, len);
- resp->maxIdx = len;
+ XMEMCPY(resp->source, *data, (size_t)len);
+ resp->maxIdx = (word32)len;
- ret = OcspResponseDecode(resp, NULL, NULL, 1);
- if (ret != 0 && ret != ASN_OCSP_CONFIRM_E) {
+ ret = OcspResponseDecode(resp, NULL, NULL, 1, 1);
+ if (ret != 0 && ret != WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E)) {
/* for just converting from a DER to an internal structure the CA may
* not yet be known to this function for signature verification */
wolfSSL_OCSP_RESPONSE_free(resp);
return NULL;
}
- if (GetSequence(*data, &idx, &length, len) >= 0)
- (*data) += idx + length;
+ if (GetSequence(*data, &idx, &length, (word32)len) >= 0)
+ (*data) += (unsigned char) ((int)idx + length);
+
+ if (response != NULL && *response == NULL)
+ *response = resp;
return resp;
}
@@ -1042,10 +1244,10 @@ int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response,
unsigned char** data)
{
if (data == NULL)
- return response->maxIdx;
+ return (int)response->maxIdx;
XMEMCPY(*data, response->source, response->maxIdx);
- return response->maxIdx;
+ return (int)response->maxIdx;
}
int wolfSSL_OCSP_response_status(OcspResponse *response)
@@ -1076,29 +1278,9 @@ const char *wolfSSL_OCSP_response_status_str(long s)
WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
{
WOLFSSL_OCSP_BASICRESP* bs;
+ const unsigned char *ptr = response->source;
- bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL,
- DYNAMIC_TYPE_OCSP_REQUEST);
- if (bs == NULL)
- return NULL;
-
- XMEMCPY(bs, response, sizeof(OcspResponse));
- bs->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
- DYNAMIC_TYPE_OCSP_ENTRY);
- bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (bs->single == NULL || bs->source == NULL) {
- if (bs->single) {
- XFREE(bs->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
- bs->single = NULL;
- }
- wolfSSL_OCSP_RESPONSE_free(bs);
- bs = NULL;
- }
- else {
- XMEMCPY(bs->single, response->single, sizeof(OcspEntry));
- XMEMCPY(bs->source, response->source, response->maxIdx);
- bs->single->ownStatus = 0;
- }
+ bs = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, response->maxIdx);
return bs;
}
@@ -1124,11 +1306,14 @@ int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data)
{
int size;
+ if (request == NULL)
+ return BAD_FUNC_ARG;
+
size = EncodeOcspRequest(request, NULL, 0);
if (size <= 0 || data == NULL)
return size;
- return EncodeOcspRequest(request, *data, size);
+ return EncodeOcspRequest(request, *data, (word32) size);
}
WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
@@ -1145,14 +1330,13 @@ WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
XMEMCPY(req->issuerHash, cid->issuerHash, KEYID_SIZE);
XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, KEYID_SIZE);
if (cid->status->serialSz > req->serialSz) {
- if (req->serial != NULL)
- XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP);
- req->serial = (byte*)XMALLOC(cid->status->serialSz,
+ XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP);
+ req->serial = (byte*)XMALLOC((size_t)cid->status->serialSz,
req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
if (req->serial == NULL)
return NULL;
}
- XMEMCPY(req->serial, cid->status->serial, cid->status->serialSz);
+ XMEMCPY(req->serial, cid->status->serial, (size_t)cid->status->serialSz);
req->serialSz = cid->status->serialSz;
return req;
@@ -1172,9 +1356,7 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID* id)
}
return certId;
}
-#endif
-#if defined(OPENSSL_ALL) || defined(APACHE_HTTPD) || defined(WOLFSSL_HAPROXY)
#ifndef NO_BIO
int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out,
WOLFSSL_OCSP_REQUEST *req)
@@ -1188,7 +1370,7 @@ int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out,
size = wolfSSL_i2d_OCSP_REQUEST(req, NULL);
if (size > 0) {
- data = (unsigned char*) XMALLOC(size, out->heap,
+ data = (unsigned char*) XMALLOC((size_t)size, out->heap,
DYNAMIC_TYPE_TMP_BUFFER);
}
@@ -1213,22 +1395,59 @@ int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out,
int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID* id, unsigned char** data)
{
- if (id == NULL || data == NULL)
- return WOLFSSL_FAILURE;
+ int allocated = 0;
+ word32 derSz = 0;
+ word32 intSz = 0;
+ int ret;
+ WOLFSSL_ENTER("wolfSSL_i2d_OCSP_CERTID");
- if (*data != NULL) {
- XMEMCPY(*data, id->rawCertId, id->rawCertIdSize);
- *data = *data + id->rawCertIdSize;
+ if (id == NULL)
+ return -1;
+
+ if (id->rawCertId != NULL) {
+ derSz = id->rawCertIdSize;
}
else {
- *data = (unsigned char*)XMALLOC(id->rawCertIdSize, NULL, DYNAMIC_TYPE_OPENSSL);
+ ret = OcspEncodeCertID(id, NULL, &derSz, &intSz);
+ if (ret != 0) {
+ WOLFSSL_MSG("Failed to calculate CertID size");
+ return -1;
+ }
+ }
+
+ if (data == NULL) {
+ return derSz;
+ }
+
+ if (*data == NULL) {
+ /* Allocate buffer for DER encoding */
+ *data = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
if (*data == NULL) {
- return WOLFSSL_FAILURE;
+ WOLFSSL_MSG("Failed to allocate memory for CertID DER encoding");
+ return -1;
}
+ allocated = 1;
+ }
+
+ if (id->rawCertId != NULL) {
XMEMCPY(*data, id->rawCertId, id->rawCertIdSize);
}
+ else {
+ ret = OcspEncodeCertID(id, *data, &derSz, &intSz);
+ if (ret < 0) {
+ WOLFSSL_MSG("Failed to encode CertID");
+ if (allocated) {
+ XFREE(*data, NULL, DYNAMIC_TYPE_OPENSSL);
+ *data = NULL;
+ }
+ return -1;
+ }
+ }
+
+ if (!allocated)
+ *data += derSz;
- return id->rawCertIdSize;
+ return derSz;
}
WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut,
@@ -1236,47 +1455,54 @@ WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut,
int length)
{
WOLFSSL_OCSP_CERTID *cid = NULL;
+ int isAllocated = 0;
+ word32 idx = 0;
+ int ret;
- if ((cidOut != NULL) && (derIn != NULL) && (*derIn != NULL) &&
- (length > 0)) {
+ if (derIn == NULL || *derIn == NULL || length <= 0)
+ return NULL;
+ if (cidOut != NULL && *cidOut != NULL) {
cid = *cidOut;
+ FreeOcspEntry(cid, NULL);
+ }
+ else {
+ cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (cid == NULL)
+ return NULL;
+ isAllocated = 1;
+ }
- /* If a NULL is passed we allocate the memory for the caller. */
- if (cid == NULL) {
- cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(*cid), NULL,
- DYNAMIC_TYPE_OPENSSL);
- }
- else if (cid->rawCertId != NULL) {
- XFREE(cid->rawCertId, NULL, DYNAMIC_TYPE_OPENSSL);
- cid->rawCertId = NULL;
- cid->rawCertIdSize = 0;
- }
-
- if (cid != NULL) {
- cid->rawCertId = (byte*)XMALLOC(length + 1, NULL, DYNAMIC_TYPE_OPENSSL);
- if (cid->rawCertId != NULL) {
- XMEMCPY(cid->rawCertId, *derIn, length);
- cid->rawCertIdSize = length;
-
- /* Per spec. advance past the data that is being returned
- * to the caller. */
- *cidOut = cid;
- *derIn = *derIn + length;
+ XMEMSET(cid, 0, sizeof(WOLFSSL_OCSP_CERTID));
+ cid->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
+ DYNAMIC_TYPE_OCSP_STATUS);
+ if (cid->status == NULL) {
+ XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
+ XMEMSET(cid->status, 0, sizeof(CertStatus));
+ cid->ownStatus = 1;
- return cid;
- }
+ ret = OcspDecodeCertID(*derIn, &idx, length, cid);
+ if (ret != 0) {
+ FreeOcspEntry(cid, NULL);
+ if (isAllocated) {
+ XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL);
}
+ return NULL;
}
- if ((cid != NULL) && ((cidOut == NULL) || (cid != *cidOut))) {
- XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL);
- }
+ *derIn += idx;
- return NULL;
+ if (isAllocated && cidOut != NULL)
+ *cidOut = cid;
+
+ return cid;
}
-const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id(const WOLFSSL_OCSP_SINGLERESP *single)
+const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id(
+ const WOLFSSL_OCSP_SINGLERESP *single)
{
return single;
}
@@ -1303,7 +1529,7 @@ int wolfSSL_OCSP_id_cmp(WOLFSSL_OCSP_CERTID *a, WOLFSSL_OCSP_CERTID *b)
if (a->status != NULL && b->status != NULL) {
if (a->status->serialSz == b->status->serialSz)
ret = XMEMCMP(a->status->serial, b->status->serial,
- a->status->serialSz);
+ (size_t)a->status->serialSz);
else
ret = -1;
}
@@ -1324,11 +1550,17 @@ int wolfSSL_OCSP_single_get0_status(WOLFSSL_OCSP_SINGLERESP *single,
if (single == NULL)
return WOLFSSL_FAILURE;
+#ifdef WOLFSSL_OCSP_PARSE_STATUS
if (thisupd != NULL)
*thisupd = &single->status->thisDateParsed;
if (nextupd != NULL)
*nextupd = &single->status->nextDateParsed;
-
+#else
+ if (thisupd != NULL)
+ *thisupd = NULL;
+ if (nextupd != NULL)
+ *nextupd = NULL;
+#endif
if (reason != NULL)
*reason = 0;
if (revtime != NULL)
@@ -1373,9 +1605,325 @@ WOLFSSL_OCSP_SINGLERESP* wolfSSL_OCSP_resp_get0(WOLFSSL_OCSP_BASICRESP *bs, int
return single;
}
-#endif /* OPENSSL_ALL || APACHE_HTTPD || WOLFSSL_HAPROXY */
+#endif /* OPENSSL_EXTRA */
+
+#ifdef OPENSSL_ALL
+
+/*******************************************************************************
+ * START OF WOLFSSL_OCSP_REQ_CTX API
+ ******************************************************************************/
+
+enum ocspReqStates {
+ ORS_INVALID = 0,
+ ORS_HEADER_ADDED,
+ ORS_REQ_DONE
+};
+
+enum ocspReqIOStates {
+ ORIOS_INVALID = 0,
+ ORIOS_WRITE,
+ ORIOS_READ
+};
+
+WOLFSSL_OCSP_REQ_CTX* wolfSSL_OCSP_REQ_CTX_new(WOLFSSL_BIO *bio, int maxline)
+{
+ WOLFSSL_OCSP_REQ_CTX* ret = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_new");
+
+ if (maxline <= 0)
+ maxline = OCSP_MAX_REQUEST_SZ;
+
+ ret = (WOLFSSL_OCSP_REQ_CTX*)XMALLOC(sizeof(*ret), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (ret != NULL) {
+ XMEMSET(ret, 0, sizeof(*ret));
+ ret->buf = (byte*)XMALLOC((word32)maxline, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (ret->buf == NULL)
+ goto error;
+ ret->reqResp = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
+ ret->bufLen = maxline;
+ ret->bio = bio;
+ ret->ioState = ORIOS_WRITE;
+ }
+
+ return ret;
+error:
+ wolfSSL_OCSP_REQ_CTX_free(ret);
+ return NULL;
+}
+
+void wolfSSL_OCSP_REQ_CTX_free(WOLFSSL_OCSP_REQ_CTX *ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_free");
+ if (ctx != NULL) {
+ if (ctx->buf != NULL)
+ XFREE(ctx->buf, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (ctx->reqResp != NULL)
+ wolfSSL_BIO_free(ctx->reqResp);
+ XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+}
+
+WOLFSSL_OCSP_REQ_CTX* wolfSSL_OCSP_sendreq_new(WOLFSSL_BIO *bio,
+ const char *path, OcspRequest *req, int maxline)
+{
+ WOLFSSL_OCSP_REQ_CTX* ret = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_OCSP_sendreq_new");
+
+ ret = wolfSSL_OCSP_REQ_CTX_new(bio, maxline);
+ if (ret == NULL)
+ return NULL;
+
+ if (wolfSSL_OCSP_REQ_CTX_http(ret, "POST", path) != WOLFSSL_SUCCESS)
+ goto error;
+
+ if (req != NULL &&
+ wolfSSL_OCSP_REQ_CTX_set1_req(ret, req) != WOLFSSL_SUCCESS)
+ goto error;
+
+ return ret;
+error:
+ wolfSSL_OCSP_REQ_CTX_free(ret);
+ return NULL;
+}
+
+int wolfSSL_OCSP_REQ_CTX_add1_header(WOLFSSL_OCSP_REQ_CTX *ctx,
+ const char *name, const char *value)
+{
+ WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_add1_header");
+
+ if (name == NULL) {
+ WOLFSSL_MSG("Bad parameter");
+ return WOLFSSL_FAILURE;
+ }
+ if (wolfSSL_BIO_puts(ctx->reqResp, name) <= 0) {
+ WOLFSSL_MSG("wolfSSL_BIO_puts error");
+ return WOLFSSL_FAILURE;
+ }
+ if (value != NULL) {
+ if (wolfSSL_BIO_write(ctx->reqResp, ": ", 2) != 2) {
+ WOLFSSL_MSG("wolfSSL_BIO_write error");
+ return WOLFSSL_FAILURE;
+ }
+ if (wolfSSL_BIO_puts(ctx->reqResp, value) <= 0) {
+ WOLFSSL_MSG("wolfSSL_BIO_puts error");
+ return WOLFSSL_FAILURE;
+ }
+ }
+ if (wolfSSL_BIO_write(ctx->reqResp, "\r\n", 2) != 2) {
+ WOLFSSL_MSG("wolfSSL_BIO_write error");
+ return WOLFSSL_FAILURE;
+ }
+
+ ctx->state = ORS_HEADER_ADDED;
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_OCSP_REQ_CTX_http(WOLFSSL_OCSP_REQ_CTX *ctx, const char *op,
+ const char *path)
+{
+ static const char http_hdr[] = "%s %s HTTP/1.0\r\n";
+
+ WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_http");
+
+ if (ctx == NULL || op == NULL) {
+ WOLFSSL_MSG("Bad parameter");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (path == NULL)
+ path = "/";
+
+ if (wolfSSL_BIO_printf(ctx->reqResp, http_hdr, op, path) <= 0) {
+ WOLFSSL_MSG("WOLFSSL_OCSP_REQ_CTX: wolfSSL_BIO_printf error");
+ return WOLFSSL_FAILURE;
+ }
+
+ ctx->state = ORS_HEADER_ADDED;
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_OCSP_REQ_CTX_set1_req(WOLFSSL_OCSP_REQ_CTX *ctx, OcspRequest *req)
+{
+ static const char req_hdr[] =
+ "Content-Type: application/ocsp-request\r\n"
+ "Content-Length: %d\r\n\r\n";
+ /* Should be enough to hold Content-Length */
+ char req_hdr_buf[sizeof(req_hdr) + 10];
+ int req_hdr_buf_len;
+ int req_len = wolfSSL_i2d_OCSP_REQUEST(req, NULL);
+
+ WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_set1_req");
+
+ if (ctx == NULL || req == NULL) {
+ WOLFSSL_MSG("Bad parameters");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (req_len <= 0) {
+ WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: request len error");
+ return WOLFSSL_FAILURE;
+ }
+
+ req_hdr_buf_len =
+ XSNPRINTF(req_hdr_buf, sizeof(req_hdr_buf), req_hdr, req_len);
+ if (req_hdr_buf_len >= (int)sizeof(req_hdr_buf)) {
+ WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: request too long");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_BIO_write(ctx->reqResp, req_hdr_buf, req_hdr_buf_len) <= 0) {
+ WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: wolfSSL_BIO_write error");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (wolfSSL_i2d_OCSP_REQUEST_bio(ctx->reqResp, req) <= 0) {
+ WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: request i2d error");
+ return WOLFSSL_FAILURE;
+ }
+
+ ctx->state = ORS_REQ_DONE;
+
+ return WOLFSSL_SUCCESS;
+}
+
+static int OCSP_REQ_CTX_bio_cb(char *buf, int sz, void *ctx)
+{
+ return BioReceiveInternal((WOLFSSL_BIO*)ctx, NULL, buf, sz);
+}
+
+int wolfSSL_OCSP_REQ_CTX_nbio(WOLFSSL_OCSP_REQ_CTX *ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_nbio");
+
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Bad parameters");
+ return WOLFSSL_FAILURE;
+ }
+
+ switch ((enum ocspReqIOStates)ctx->ioState) {
+ case ORIOS_WRITE:
+ case ORIOS_READ:
+ break;
+ case ORIOS_INVALID:
+ default:
+ WOLFSSL_MSG("Invalid ctx->ioState state");
+ return WOLFSSL_FAILURE;
+ }
+
+ if (ctx->ioState == ORIOS_WRITE) {
+ switch ((enum ocspReqStates)ctx->state) {
+ case ORS_HEADER_ADDED:
+ /* Write final new line to complete http header */
+ if (wolfSSL_BIO_write(ctx->reqResp, "\r\n", 2) != 2) {
+ WOLFSSL_MSG("wolfSSL_BIO_write error");
+ return WOLFSSL_FAILURE;
+ }
+ break;
+ case ORS_REQ_DONE:
+ break;
+ case ORS_INVALID:
+ default:
+ WOLFSSL_MSG("Invalid WOLFSSL_OCSP_REQ_CTX state");
+ return WOLFSSL_FAILURE;
+ }
+ }
+
+ switch ((enum ocspReqIOStates)ctx->ioState) {
+ case ORIOS_WRITE:
+ {
+ const unsigned char *req;
+ int reqLen = wolfSSL_BIO_get_mem_data(ctx->reqResp, (void*)&req);
+ if (reqLen <= 0) {
+ WOLFSSL_MSG("wolfSSL_BIO_get_mem_data error");
+ return WOLFSSL_FAILURE;
+ }
+ while (ctx->sent < reqLen) {
+ int sent = wolfSSL_BIO_write(ctx->bio, req + ctx->sent,
+ reqLen - ctx->sent);
+ if (sent <= 0) {
+ if (wolfSSL_BIO_should_retry(ctx->bio))
+ return WOLFSSL_FATAL_ERROR;
+ WOLFSSL_MSG("wolfSSL_BIO_write error");
+ ctx->ioState = ORIOS_INVALID;
+ return 0;
+ }
+ ctx->sent += sent;
+ }
+ ctx->sent = 0;
+ ctx->ioState = ORIOS_READ;
+ (void)wolfSSL_BIO_reset(ctx->reqResp);
+ FALL_THROUGH;
+ }
+ case ORIOS_READ:
+ {
+ byte* resp = NULL;
+ int respLen;
+ int ret;
+
+ if (ctx->buf == NULL) /* Should be allocated in new call */
+ return WOLFSSL_FAILURE;
+
+ ret = wolfIO_HttpProcessResponseOcspGenericIO(OCSP_REQ_CTX_bio_cb,
+ ctx->bio, &resp, ctx->buf, ctx->bufLen, NULL);
+ if (ret <= 0) {
+ if (resp != NULL)
+ XFREE(resp, NULL, DYNAMIC_TYPE_OCSP);
+ if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ) ||
+ ret == WC_NO_ERR_TRACE(OCSP_WANT_READ))
+ {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ return WOLFSSL_FAILURE;
+ }
+ respLen = ret;
+ ret = wolfSSL_BIO_write(ctx->reqResp, resp, respLen);
+ XFREE(resp, NULL, DYNAMIC_TYPE_OCSP);
+ if (ret != respLen) {
+ WOLFSSL_MSG("wolfSSL_BIO_write error");
+ return WOLFSSL_FAILURE;
+ }
+ break;
+ }
+ case ORIOS_INVALID:
+ default:
+ WOLFSSL_MSG("Invalid ctx->ioState state");
+ return WOLFSSL_FAILURE;
+ }
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_OCSP_sendreq_nbio(OcspResponse **presp, WOLFSSL_OCSP_REQ_CTX *ctx)
+{
+ int ret;
+ int len;
+ const unsigned char *resp = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_OCSP_sendreq_nbio");
+
+ if (presp == NULL)
+ return WOLFSSL_FAILURE;
+
+ ret = wolfSSL_OCSP_REQ_CTX_nbio(ctx);
+ if (ret != WOLFSSL_SUCCESS)
+ return ret;
+
+ len = wolfSSL_BIO_get_mem_data(ctx->reqResp, (void*)&resp);
+ if (len <= 0)
+ return WOLFSSL_FAILURE;
+ return wolfSSL_d2i_OCSP_RESPONSE(presp, &resp, len) != NULL
+ ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
+
+/*******************************************************************************
+ * END OF WOLFSSL_OCSP_REQ_CTX API
+ ******************************************************************************/
-#ifdef OPENSSL_EXTRA
#ifndef NO_WOLFSSL_STUB
int wolfSSL_OCSP_REQUEST_add_ext(OcspRequest* req, WOLFSSL_X509_EXTENSION* ext,
int idx)
@@ -1432,13 +1980,13 @@ int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name,
if (cid->status->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
/* allocate data buffer, +2 for type and length */
- ser->data = (unsigned char*)XMALLOC(cid->status->serialSz + 2, NULL,
+ ser->data = (unsigned char*)XMALLOC((size_t)cid->status->serialSz + 2, NULL,
DYNAMIC_TYPE_OPENSSL);
if (ser->data == NULL) {
wolfSSL_ASN1_INTEGER_free(ser);
return 0;
}
- ser->dataMax = cid->status->serialSz + 2;
+ ser->dataMax = (unsigned int)cid->status->serialSz + 2;
ser->isDynamic = 1;
} else {
/* Use array instead of dynamic memory */
@@ -1448,12 +1996,14 @@ int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name,
#if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY)
/* Serial number starts at 0 index of ser->data */
- XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz);
+ XMEMCPY(&ser->data[i], cid->status->serial,
+ (size_t)cid->status->serialSz);
ser->length = cid->status->serialSz;
#else
ser->data[i++] = ASN_INTEGER;
i += SetLength(cid->status->serialSz, ser->data + i);
- XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz);
+ XMEMCPY(&ser->data[i], cid->status->serial,
+ (size_t)cid->status->serialSz);
ser->length = i + cid->status->serialSz;
#endif
@@ -1493,7 +2043,7 @@ int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val,
sz = MAX_OCSP_NONCE_SZ;
if (val != NULL) {
- XMEMCPY(req->nonce, val, sz);
+ XMEMCPY(req->nonce, val, (size_t)sz);
}
else {
if (
@@ -1506,7 +2056,7 @@ int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val,
WOLFSSL_MSG("RNG init failed");
return WOLFSSL_FAILURE;
}
- if (wc_RNG_GenerateBlock(&rng, req->nonce, sz) != 0) {
+ if (wc_RNG_GenerateBlock(&rng, req->nonce, (word32)sz) != 0) {
WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
wc_FreeRng(&rng);
return WOLFSSL_FAILURE;
@@ -1554,19 +2104,20 @@ int wolfSSL_OCSP_check_nonce(OcspRequest* req, WOLFSSL_OCSP_BASICRESP* bs)
/* nonce present in req only */
if (reqNonce != NULL && rspNonce == NULL)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
/* nonces are present and equal, return 1. Extra NULL check for fixing
scan-build warning. */
if (reqNonceSz == rspNonceSz && reqNonce && rspNonce) {
- if (XMEMCMP(reqNonce, rspNonce, reqNonceSz) == 0)
+ if (XMEMCMP(reqNonce, rspNonce, (size_t)reqNonceSz) == 0)
return 1;
}
/* nonces are present but not equal */
return 0;
}
-#endif /* OPENSSL_EXTRA */
+
+#endif /* OPENSSL_ALL */
#else /* HAVE_OCSP */
diff --git a/src/src/pk.c b/src/src/pk.c
index d7d32dd..8f07a67 100644
--- a/src/src/pk.c
+++ b/src/src/pk.c
@@ -1,12 +1,12 @@
/* pk.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,19 +19,21 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
-#ifdef HAVE_CONFIG_H
- #include
-#endif
-
-#include
+#include
- #include
+#include
#ifndef WC_NO_RNG
#include
#endif
#ifdef HAVE_ECC
#include
+ #ifdef HAVE_SELFTEST
+ /* point compression types. */
+ #define ECC_POINT_COMP_EVEN 0x02
+ #define ECC_POINT_COMP_ODD 0x03
+ #define ECC_POINT_UNCOMP 0x04
+ #endif
#endif
#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
/* FIPS build has replaced ecc.h. */
@@ -49,14 +51,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
******************************************************************************/
@@ -91,11 +85,7 @@ static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key);
static int pem_mem_to_der(const char* pem, int pemSz, wc_pem_password_cb* cb,
void* pass, int keyType, int* keyFormat, DerBuffer** der)
{
-#ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
-#else
- EncryptedInfo info[1];
-#endif /* WOLFSSL_SMALL_STACK */
+ WC_DECLARE_VAR(info, EncryptedInfo, 1, 0);
wc_pem_password_cb* localCb = NULL;
int ret = 0;
@@ -131,9 +121,7 @@ static int pem_mem_to_der(const char* pem, int pemSz, wc_pem_password_cb* cb,
ret = (int)info->consumed;
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
-#endif
+ WC_FREE_VAR_EX(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
return ret;
}
@@ -168,7 +156,25 @@ static int pem_read_bio_key(WOLFSSL_BIO* bio, wc_pem_password_cb* cb,
if ((ret > 0) && ((memSz - ret) > 0) &&
(bio->type != WOLFSSL_BIO_FILE)) {
int res;
- res = wolfSSL_BIO_write(bio, mem + ret, memSz - ret);
+ if (!alloced) {
+ /* If wolfssl_read_bio() points mem at the buffer internal to
+ * bio, we need to dup it before calling wolfSSL_BIO_write(),
+ * because the latter may reallocate the bio, invalidating the
+ * mem pointer before reading from it.
+ */
+ char *mem_dup = (char *)XMALLOC((size_t)(memSz - ret),
+ NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (mem_dup != NULL) {
+ XMEMCPY(mem_dup, mem + ret, (size_t)(memSz - ret));
+ res = wolfSSL_BIO_write(bio, mem_dup, memSz - ret);
+ mem = mem_dup;
+ alloced = 1;
+ }
+ else
+ res = MEMORY_E;
+ }
+ else
+ 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 +186,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 +235,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 +281,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 +292,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 +317,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 +328,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,17 +342,163 @@ 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.
+ * @param [in] hashType Hash algorithm
+ * @return 1 on success.
+ * @return 0 on error.
+ */
+int EncryptDerKey(byte *der, int *derSz, const WOLFSSL_EVP_CIPHER* cipher,
+ unsigned char* passwd, int passwdSz, byte **cipherInfo, int maxDerSz,
+ int hashType)
+{
+ int ret = 0;
+ int paddingSz = 0;
+ word32 idx;
+ word32 cipherInfoSz = 0;
+ WC_DECLARE_VAR(info, EncryptedInfo, 1, 0);
+
+ 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 = MEMORY_E;
+ }
+ }
+ #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, (int)info->ivSz) != 1) {
+ WOLFSSL_MSG("generate iv failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if (ret == 0) {
+ /* Calculate padding size - always a padding block. */
+ paddingSz = (int)info->ivSz - ((*derSz) % (int)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, (size_t)paddingSz);
+ /* Add padding to DER size. */
+ (*derSz) += (int)paddingSz;
+
+ /* Encrypt DER buffer. */
+ ret = wc_BufferKeyEncrypt(info, der, (word32)*derSz, passwd, passwdSz,
+ hashType);
+ 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;
+ }
+ }
+
+ WC_FREE_VAR_EX(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+ 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)
+ const WOLFSSL_EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
+ int type, void* heap, byte** out, int* outSz)
{
int ret = 1;
byte* tmp = NULL;
byte* cipherInfo = NULL;
int pemSz = 0;
+ int hashType = WC_HASH_TYPE_NONE;
+#if !defined(NO_MD5)
+ hashType = WC_MD5;
+#elif !defined(NO_SHA)
+ hashType = WC_SHA;
+#endif
/* Macro doesn't always use it. */
(void)heap;
@@ -354,8 +509,19 @@ static int der_to_enc_pem_alloc(unsigned char* der, int derSz,
byte *tmpBuf;
/* Add space for padding. */
+ #ifdef WOLFSSL_NO_REALLOC
+ tmpBuf = (byte*)XMALLOC((size_t)(derSz + blockSz), heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (tmpBuf != NULL && der != NULL)
+ {
+ XMEMCPY(tmpBuf, der, (size_t)(derSz));
+ XFREE(der, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ der = NULL;
+ }
+ #else
tmpBuf = (byte*)XREALLOC(der, (size_t)(derSz + blockSz), heap,
DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
if (tmpBuf == NULL) {
WOLFSSL_ERROR_MSG("Extending DER buffer failed");
ret = 0; /* der buffer is free'd at the end of the function */
@@ -365,7 +531,7 @@ static int der_to_enc_pem_alloc(unsigned char* der, int derSz,
/* Encrypt DER inline. */
ret = EncryptDerKey(der, &derSz, cipher, passwd, passwdSz,
- &cipherInfo, derSz + blockSz);
+ &cipherInfo, derSz + blockSz, hashType);
if (ret != 1) {
WOLFSSL_ERROR_MSG("EncryptDerKey failed");
}
@@ -558,9 +724,14 @@ static int wolfssl_print_indent(WOLFSSL_BIO* bio, char* line, int lineLen,
int ret = 1;
if (indent > 0) {
+ int len_wanted;
+ /* Cap indent to buffer size to avoid format truncation warning */
+ if (indent >= lineLen) {
+ indent = lineLen - 1;
+ }
/* Print indent spaces. */
- int len_wanted = XSNPRINTF(line, (size_t)lineLen, "%*s", indent, " ");
- if (len_wanted >= lineLen) {
+ len_wanted = XSNPRINTF(line, (size_t)lineLen, "%*s", indent, " ");
+ if ((len_wanted < 0) || (len_wanted >= lineLen)) {
WOLFSSL_ERROR_MSG("Buffer overflow formatting indentation");
ret = 0;
}
@@ -736,8 +907,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 +939,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
@@ -798,23 +970,23 @@ WOLFSSL_RSA_METHOD *wolfSSL_RSA_meth_new(const char *name, int flags)
int err;
/* Validate name is not NULL. */
- err = (name == NULL);
- if (!err) {
- /* Allocate an RSA METHOD to return. */
- meth = (WOLFSSL_RSA_METHOD*)XMALLOC(sizeof(WOLFSSL_RSA_METHOD), NULL,
- DYNAMIC_TYPE_OPENSSL);
- err = (meth == NULL);
- }
- if (!err) {
- XMEMSET(meth, 0, sizeof(*meth));
- meth->flags = flags;
- meth->dynamic = 1;
+ if (name == NULL)
+ return NULL;
+ /* Allocate an RSA METHOD to return. */
+ meth = (WOLFSSL_RSA_METHOD*)XMALLOC(sizeof(WOLFSSL_RSA_METHOD), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (meth == NULL)
+ return NULL;
+
+ XMEMSET(meth, 0, sizeof(*meth));
+ meth->flags = flags;
+ meth->dynamic = 1;
+
+ name_len = (int)XSTRLEN(name);
+ meth->name = (char*)XMALLOC((size_t)(name_len + 1), NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ err = (meth->name == NULL);
- name_len = (int)XSTRLEN(name);
- meth->name = (char*)XMALLOC((size_t)(name_len + 1), NULL,
- DYNAMIC_TYPE_OPENSSL);
- err = (meth->name == NULL);
- }
if (!err) {
XMEMCPY(meth->name, name, (size_t)(name_len + 1));
}
@@ -1382,7 +1554,11 @@ static int wolfssl_read_der_bio(WOLFSSL_BIO* bio, unsigned char** out)
WOLFSSL_ERROR_MSG("Malloc failure");
err = 1;
}
- if (!err) {
+ if ((!err) && (derLen <= (int)sizeof(seq))) {
+ /* Copy the previously read data into the buffer. */
+ XMEMCPY(der, seq, derLen);
+ }
+ else if (!err) {
/* Calculate the unread amount. */
int len = derLen - (int)sizeof(seq);
/* Copy the previously read data into the buffer. */
@@ -1644,7 +1820,7 @@ int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
if ((rsa == NULL) || (rsa->internal == NULL) || (derBuf == NULL) ||
(derSz <= 0)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
@@ -1659,11 +1835,11 @@ int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
rsa->pkcs8HeaderSz = (word16)idx;
}
/* When decoding and not PKCS#8, return will be ASN_PARSE_E. */
- else if (res != ASN_PARSE_E) {
+ else if (res != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
/* Something went wrong while decoding. */
WOLFSSL_ERROR_MSG("Unexpected error with trying to remove PKCS#8 "
"header");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
@@ -1685,13 +1861,13 @@ int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf,
WOLFSSL_ERROR_MSG("RsaPublicKeyDecode failed");
}
WOLFSSL_ERROR_VERBOSE(res);
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
/* Set external RSA key data from wolfCrypt key. */
if (SetRsaExternal(rsa) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else {
rsa->inSet = 1;
@@ -1787,7 +1963,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 +2008,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;
}
@@ -1906,6 +2082,32 @@ WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio,
}
return rsa;
}
+
+WOLFSSL_RSA *wolfSSL_d2i_RSA_PUBKEY_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out)
+{
+ char* data = NULL;
+ int dataSz = 0;
+ int memAlloced = 0;
+ WOLFSSL_RSA* rsa = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_RSA_PUBKEY_bio");
+
+ if (bio == NULL)
+ return NULL;
+
+ if (wolfssl_read_bio(bio, &data, &dataSz, &memAlloced) != 0) {
+ if (memAlloced)
+ XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return NULL;
+ }
+
+ rsa = wolfssl_rsa_d2i(out, (const unsigned char*)data, dataSz,
+ WOLFSSL_RSA_LOAD_PUBLIC);
+ if (memAlloced)
+ XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return rsa;
+}
#endif /* !NO_BIO */
#ifndef NO_FILESYSTEM
@@ -1983,8 +2185,9 @@ WOLFSSL_RSA* wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA** rsa,
* @return 1 on success.
* @return 0 on failure.
*/
-int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
- unsigned char* passwd, int passwdSz, unsigned char **pem, int *pLen)
+int wolfSSL_PEM_write_mem_RSAPrivateKey(WOLFSSL_RSA* rsa,
+ const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
+ unsigned char **pem, int *pLen)
{
int ret = 1;
byte* derBuf = NULL;
@@ -2089,7 +2292,7 @@ int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa,
* @return 0 on failure.
*/
int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa,
- const EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
+ const WOLFSSL_EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
wc_pem_password_cb *cb, void *arg)
{
int ret = 1;
@@ -2306,7 +2509,7 @@ int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int indent)
/* Validate parameters. */
if ((bio == NULL) || (rsa == NULL) || (indent > PRINT_NUM_MAX_INDENT)) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
@@ -2406,7 +2609,7 @@ int SetRsaExternal(WOLFSSL_RSA* rsa)
/* Validate parameters. */
if ((rsa == NULL) || (rsa->internal == NULL)) {
WOLFSSL_ERROR_MSG("rsa key NULL error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
@@ -2426,6 +2629,7 @@ int SetRsaExternal(WOLFSSL_RSA* rsa)
}
if (key->type == RSA_PRIVATE) {
+ #ifndef WOLFSSL_RSA_PUBLIC_ONLY
if (ret == 1) {
/* Copy private exponent. */
ret = wolfssl_bn_set_value(&rsa->d, &key->d);
@@ -2447,7 +2651,8 @@ int SetRsaExternal(WOLFSSL_RSA* rsa)
WOLFSSL_ERROR_MSG("rsa q error");
}
}
- #ifndef RSA_LOW_MEM
+ #if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \
+ !defined(RSA_LOW_MEM)
if (ret == 1) {
/* Copy d mod p-1. */
ret = wolfssl_bn_set_value(&rsa->dmp1, &key->dP);
@@ -2469,7 +2674,11 @@ int SetRsaExternal(WOLFSSL_RSA* rsa)
WOLFSSL_ERROR_MSG("rsa u error");
}
}
- #endif /* !RSA_LOW_MEM */
+ #endif
+ #else
+ WOLFSSL_ERROR_MSG("rsa private key not compiled in ");
+ ret = 0;
+ #endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
}
}
if (ret == 1) {
@@ -2502,7 +2711,7 @@ int SetRsaInternal(WOLFSSL_RSA* rsa)
/* Validate parameters. */
if ((rsa == NULL) || (rsa->internal == NULL)) {
WOLFSSL_ERROR_MSG("rsa key NULL error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
@@ -2511,24 +2720,25 @@ int SetRsaInternal(WOLFSSL_RSA* rsa)
/* Copy down modulus if available. */
if ((rsa->n != NULL) && (wolfssl_bn_get_value(rsa->n, &key->n) != 1)) {
WOLFSSL_ERROR_MSG("rsa n key error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Copy down public exponent if available. */
if ((ret == 1) && (rsa->e != NULL) &&
(wolfssl_bn_get_value(rsa->e, &key->e) != 1)) {
WOLFSSL_ERROR_MSG("rsa e key error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Enough numbers for public key */
key->type = RSA_PUBLIC;
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
/* Copy down private exponent if available. */
if ((ret == 1) && (rsa->d != NULL)) {
if (wolfssl_bn_get_value(rsa->d, &key->d) != 1) {
WOLFSSL_ERROR_MSG("rsa d key error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else {
/* Enough numbers for private key */
@@ -2540,38 +2750,39 @@ int SetRsaInternal(WOLFSSL_RSA* rsa)
if ((ret == 1) && (rsa->p != NULL) &&
(wolfssl_bn_get_value(rsa->p, &key->p) != 1)) {
WOLFSSL_ERROR_MSG("rsa p key error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Copy down second prime if available. */
if ((ret == 1) && (rsa->q != NULL) &&
(wolfssl_bn_get_value(rsa->q, &key->q) != 1)) {
WOLFSSL_ERROR_MSG("rsa q key error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
- #ifndef RSA_LOW_MEM
+#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)
/* Copy down d mod p-1 if available. */
if ((ret == 1) && (rsa->dmp1 != NULL) &&
(wolfssl_bn_get_value(rsa->dmp1, &key->dP) != 1)) {
WOLFSSL_ERROR_MSG("rsa dP key error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Copy down d mod q-1 if available. */
- if ((ret == 1) && (rsa->dmp1 != NULL) &&
+ if ((ret == 1) && (rsa->dmq1 != NULL) &&
(wolfssl_bn_get_value(rsa->dmq1, &key->dQ) != 1)) {
WOLFSSL_ERROR_MSG("rsa dQ key error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Copy down 1/q mod p if available. */
if ((ret == 1) && (rsa->iqmp != NULL) &&
(wolfssl_bn_get_value(rsa->iqmp, &key->u) != 1)) {
WOLFSSL_ERROR_MSG("rsa u key error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
- #endif /* !RSA_LOW_MEM */
+#endif
+#endif
if (ret == 1) {
/* All available numbers have been set down. */
@@ -3128,6 +3339,7 @@ static int wolfssl_rsa_generate_key_native(WOLFSSL_RSA* rsa, int bits,
#endif
int initTmpRng = 0;
WC_RNG* rng = NULL;
+ long en = 0;
#endif
(void)cb;
@@ -3141,10 +3353,12 @@ static int wolfssl_rsa_generate_key_native(WOLFSSL_RSA* rsa, int bits,
/* Something went wrong so return memory error. */
ret = MEMORY_E;
}
+ if ((ret == 0) && ((en = (long)wolfSSL_BN_get_word(e)) <= 0)) {
+ ret = BAD_FUNC_ARG;
+ }
if (ret == 0) {
/* Generate an RSA key. */
- ret = wc_MakeRsaKey((RsaKey*)rsa->internal, bits,
- (long)wolfSSL_BN_get_word(e), rng);
+ ret = wc_MakeRsaKey((RsaKey*)rsa->internal, bits, en, rng);
if (ret != MP_OKAY) {
WOLFSSL_ERROR_MSG("wc_MakeRsaKey failed");
}
@@ -3168,10 +3382,7 @@ static int wolfssl_rsa_generate_key_native(WOLFSSL_RSA* rsa, int bits,
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
-#ifdef WOLFSSL_SMALL_STACK
- /* Dispose of any allocated RNG. */
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-#endif
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
return ret;
#else
@@ -3239,7 +3450,7 @@ WOLFSSL_RSA* wolfSSL_RSA_generate_key(int bits, unsigned long e,
ret = wolfssl_rsa_generate_key_native(rsa, bits, bn, NULL);
#ifdef HAVE_FIPS
/* Keep trying if failed to find a prime. */
- if (ret == PRIME_GEN_E) {
+ if (ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) {
continue;
}
#endif
@@ -3290,7 +3501,7 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* e,
int gen_ret = wolfssl_rsa_generate_key_native(rsa, bits, e, cb);
#ifdef HAVE_FIPS
/* Keep trying again if public key value didn't work. */
- if (gen_ret == PRIME_GEN_E) {
+ if (gen_ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) {
continue;
}
#endif
@@ -3312,9 +3523,43 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* e,
* RSA padding APIs
*/
-#if defined(WC_RSA_PSS) && (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
- defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX))
-#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
+#ifdef WC_RSA_PSS
+
+#if defined(OPENSSL_EXTRA) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+static int rsa_pss_calc_salt(int saltLen, int hashLen, int emLen)
+{
+ /* Calculate the salt length to use for special cases. */
+ switch (saltLen) {
+ /* Negative saltLen values are treated differently. */
+ case WC_RSA_PSS_SALTLEN_DIGEST:
+ saltLen = hashLen;
+ break;
+ case WC_RSA_PSS_SALTLEN_MAX_SIGN:
+ case WC_RSA_PSS_SALTLEN_MAX:
+ #ifdef WOLFSSL_PSS_LONG_SALT
+ saltLen = emLen - hashLen - 2;
+ #else
+ saltLen = hashLen;
+ (void)emLen;
+ #endif
+ break;
+ default:
+ break;
+ }
+ if (saltLen < 0) {
+ /* log invalid salt, let wolfCrypt handle error */
+ WOLFSSL_ERROR_MSG("invalid saltLen");
+ saltLen = -3; /* for wolfCrypt to produce error must be < -2 */
+ }
+ return saltLen;
+}
+#endif /* OPENSSL_EXTRA && !HAVE_SELFTEST */
+
+#if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
+ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX)) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
+
/* Add PKCS#1 PSS padding to hash.
*
*
@@ -3348,15 +3593,18 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* e,
* @param [out] em Encoded message.
* @param [in[ mHash Message hash.
* @param [in] hashAlg Hash algorithm.
+ * @param [in] mgf1Hash MGF algorithm.
* @param [in] saltLen Length of salt to generate.
* @return 1 on success.
* @return 0 on failure.
*/
-int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
- const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg, int saltLen)
+
+int wolfSSL_RSA_padding_add_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa, unsigned char *em,
+ const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg,
+ const WOLFSSL_EVP_MD *mgf1Hash, int saltLen)
{
int ret = 1;
- enum wc_HashType hashType;
+ enum wc_HashType hashType = WC_HASH_TYPE_NONE;
int hashLen = 0;
int emLen = 0;
int mgf = 0;
@@ -3376,6 +3624,9 @@ int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
ret = 0;
}
+ if (mgf1Hash == NULL)
+ mgf1Hash = hashAlg;
+
if (ret == 1) {
/* Get/create an RNG. */
rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
@@ -3401,7 +3652,7 @@ int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
}
if (ret == 1) {
/* Get the wolfCrypt MGF algorithm from hash algorithm. */
- mgf = wc_hash2mgf(hashType);
+ mgf = wc_hash2mgf(EvpMd2MacType(mgf1Hash));
if (mgf == WC_MGF1NONE) {
WOLFSSL_ERROR_MSG("wc_hash2mgf error");
ret = 0;
@@ -3419,35 +3670,14 @@ int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
if (ret == 1) {
/* Get length of RSA key - encrypted message length. */
emLen = wolfSSL_RSA_size(rsa);
- if (ret <= 0) {
+ if (emLen <= 0) {
WOLFSSL_ERROR_MSG("wolfSSL_RSA_size error");
ret = 0;
}
}
if (ret == 1) {
- /* Calculate the salt length to use for special cases. */
- /* TODO: use special case wolfCrypt values? */
- switch (saltLen) {
- /* Negative saltLen values are treated differently. */
- case RSA_PSS_SALTLEN_DIGEST:
- saltLen = hashLen;
- break;
- case RSA_PSS_SALTLEN_MAX_SIGN:
- case RSA_PSS_SALTLEN_MAX:
- #ifdef WOLFSSL_PSS_LONG_SALT
- saltLen = emLen - hashLen - 2;
- #else
- saltLen = hashLen;
- #endif
- break;
- default:
- if (saltLen < 0) {
- /* No other negative values implemented. */
- WOLFSSL_ERROR_MSG("invalid saltLen");
- ret = 0;
- }
- }
+ saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen);
}
if (ret == 1) {
@@ -3464,14 +3694,18 @@ int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
-#ifdef WOLFSSL_SMALL_STACK
- /* Dispose of any allocated RNG. */
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-#endif
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
return ret;
}
+int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
+ const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg, int saltLen)
+{
+ return wolfSSL_RSA_padding_add_PKCS1_PSS_mgf1(rsa, em, mHash, hashAlg, NULL,
+ saltLen);
+}
+
/* Checks that the hash is valid for the RSA PKCS#1 PSS encoded message.
*
* Refer to wolfSSL_RSA_padding_add_PKCS1_PSS for a diagram.
@@ -3479,14 +3713,15 @@ int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em,
* @param [in] rsa RSA key.
* @param [in[ mHash Message hash.
* @param [in] hashAlg Hash algorithm.
+ * @param [in] mgf1Hash MGF algorithm.
* @param [in] em Encoded message.
* @param [in] saltLen Length of salt to generate.
* @return 1 on success.
* @return 0 on failure.
*/
-int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
- const WOLFSSL_EVP_MD *hashAlg,
- const unsigned char *em, int saltLen)
+int wolfSSL_RSA_verify_PKCS1_PSS_mgf1(WOLFSSL_RSA *rsa,
+ const unsigned char *mHash, const WOLFSSL_EVP_MD *hashAlg,
+ const WOLFSSL_EVP_MD *mgf1Hash, const unsigned char *em, int saltLen)
{
int ret = 1;
int hashLen = 0;
@@ -3504,6 +3739,9 @@ int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
ret = 0;
}
+ if (mgf1Hash == NULL)
+ mgf1Hash = hashAlg;
+
/* TODO: use wolfCrypt RSA key to get emLen and bits? */
/* Set the external data from the wolfCrypt RSA key if not done. */
if ((ret == 1) && (!rsa->exSet)) {
@@ -3528,31 +3766,7 @@ int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
}
if (ret == 1) {
- /* Calculate the salt length to use for special cases. */
- switch (saltLen) {
- /* Negative saltLen values are treated differently */
- case RSA_PSS_SALTLEN_DIGEST:
- saltLen = hashLen;
- break;
- case RSA_PSS_SALTLEN_AUTO:
- #ifdef WOLFSSL_PSS_SALT_LEN_DISCOVER
- saltLen = RSA_PSS_SALT_LEN_DISCOVER;
- break;
- #endif
- case RSA_PSS_SALTLEN_MAX:
- #ifdef WOLFSSL_PSS_LONG_SALT
- saltLen = emLen - hashLen - 2;
- #else
- saltLen = hashLen;
- #endif
- break;
- default:
- if (saltLen < 0) {
- /* No other negative values implemented. */
- WOLFSSL_ERROR_MSG("invalid saltLen");
- ret = 0;
- }
- }
+ saltLen = rsa_pss_calc_salt(saltLen, hashLen, emLen);
}
if (ret == 1) {
@@ -3566,7 +3780,7 @@ int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
if (ret == 1) {
/* Get the wolfCrypt MGF algorithm from hash algorithm. */
- if ((mgf = wc_hash2mgf(hashType)) == WC_MGF1NONE) {
+ if ((mgf = wc_hash2mgf(EvpMd2MacType(mgf1Hash))) == WC_MGF1NONE) {
WOLFSSL_ERROR_MSG("wc_hash2mgf error");
ret = 0;
}
@@ -3609,18 +3823,31 @@ int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
-#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */
-#endif /* WC_RSA_PSS && (OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY ||
- * WOLFSSL_NGINX) */
+
+int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash,
+ const WOLFSSL_EVP_MD *hashAlg,
+ const unsigned char *em, int saltLen)
+{
+ return wolfSSL_RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, hashAlg, NULL, em,
+ saltLen);
+}
+#endif /* (!HAVE_FIPS || FIPS_VERSION_GT(2,0)) && \
+ (OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_NGINX) */
+#endif /* WC_RSA_PSS */
/*
* RSA sign/verify APIs
*/
-#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
- #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DEFAULT
+#if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
+ #ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
+ #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DEFAULT
+ #else
+ #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DISCOVER
+ #endif
#else
- #define DEF_PSS_SALT_LEN RSA_PSS_SALT_LEN_DISCOVER
+ #define DEF_PSS_SALT_LEN 0 /* not used */
#endif
#if defined(OPENSSL_EXTRA)
@@ -3649,15 +3876,15 @@ static int wolfssl_rsa_sig_encode(int hashAlg, const unsigned char* hash,
ret = 0;
}
- if ((ret == 1) && (hashAlg != NID_undef) &&
- (padding == RSA_PKCS1_PADDING)) {
+ if ((ret == 1) && (hashAlg != WC_NID_undef) &&
+ (padding == WC_RSA_PKCS1_PADDING)) {
/* Convert hash algorithm to hash type for PKCS#1.5 padding. */
hType = (int)nid2oid(hashAlg, oidHashType);
if (hType == -1) {
ret = 0;
}
}
- if ((ret == 1) && (padding == RSA_PKCS1_PADDING)) {
+ if ((ret == 1) && (padding == WC_RSA_PKCS1_PADDING)) {
/* PKCS#1.5 encoding. */
word32 encSz = wc_EncodeSignature(enc, hash, hLen, hType);
if (encSz == 0) {
@@ -3669,7 +3896,7 @@ static int wolfssl_rsa_sig_encode(int hashAlg, const unsigned char* hash,
}
}
/* Other padding schemes require the hash as is. */
- if ((ret == 1) && (padding != RSA_PKCS1_PADDING)) {
+ if ((ret == 1) && (padding != WC_RSA_PKCS1_PADDING)) {
XMEMCPY(enc, hash, hLen);
*encLen = hLen;
}
@@ -3697,7 +3924,7 @@ int wolfSSL_RSA_sign(int hashAlg, const unsigned char* hash, unsigned int hLen,
}
/* flag is 1: output complete signature. */
return wolfSSL_RSA_sign_generic_padding(hashAlg, hash, hLen, sigRet,
- sigLen, rsa, 1, RSA_PKCS1_PADDING);
+ sigLen, rsa, 1, WC_RSA_PKCS1_PADDING);
}
/* Sign the message hash using hash algorithm and RSA key.
@@ -3727,12 +3954,20 @@ int wolfSSL_RSA_sign_ex(int hashAlg, const unsigned char* hash,
*sigLen = RSA_MAX_SIZE / CHAR_BIT;
}
ret = wolfSSL_RSA_sign_generic_padding(hashAlg, hash, hLen, sigRet,
- sigLen, rsa, flag, RSA_PKCS1_PADDING);
+ sigLen, rsa, flag, WC_RSA_PKCS1_PADDING);
}
return ret;
}
+int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash,
+ unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
+ WOLFSSL_RSA* rsa, int flag, int padding)
+{
+ return wolfSSL_RSA_sign_mgf(hashAlg, hash, hLen, sigRet, sigLen, rsa, flag,
+ padding, hashAlg, DEF_PSS_SALT_LEN);
+}
+
/**
* Sign a message hash with the chosen message digest, padding, and RSA key.
*
@@ -3749,14 +3984,16 @@ int wolfSSL_RSA_sign_ex(int hashAlg, const unsigned char* hash,
* 0: Output the value that the unpadded signature
* should be compared to.
* @param [in] padding Padding to use. Only RSA_PKCS1_PSS_PADDING and
- * RSA_PKCS1_PADDING are currently supported for
+ * WC_RSA_PKCS1_PADDING are currently supported for
* signing.
+ * @param [in] mgf1Hash MGF1 Hash NID
+ * @param [in] saltLen Length of RSA PSS salt
* @return 1 on success.
* @return 0 on failure.
*/
-int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash,
+int wolfSSL_RSA_sign_mgf(int hashAlg, const unsigned char* hash,
unsigned int hLen, unsigned char* sigRet, unsigned int* sigLen,
- WOLFSSL_RSA* rsa, int flag, int padding)
+ WOLFSSL_RSA* rsa, int flag, int padding, int mgf1Hash, int saltLen)
{
int ret = 1;
word32 outLen = 0;
@@ -3773,8 +4010,7 @@ int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash,
#endif
unsigned int encSz = 0;
-
- WOLFSSL_ENTER("wolfSSL_RSA_sign_generic_padding");
+ WOLFSSL_ENTER("wolfSSL_RSA_sign_mgf");
if (flag == 0) {
/* Only encode message. */
@@ -3838,54 +4074,59 @@ int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash,
if (ret == 1) {
switch (padding) {
#if defined(WC_RSA_NO_PADDING) || defined(WC_RSA_DIRECT)
- case RSA_NO_PADDING:
+ case WC_RSA_NO_PAD:
if ((signSz = wc_RsaDirect(encodedSig, encSz, sigRet, &outLen,
(RsaKey*)rsa->internal, RSA_PRIVATE_ENCRYPT, rng)) <= 0) {
- WOLFSSL_ERROR_MSG("Bad Rsa Sign no pad");
+ WOLFSSL_ERROR_MSG("Bad RSA Sign no pad");
ret = 0;
}
break;
#endif
#if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
- case RSA_PKCS1_PSS_PADDING:
+ case WC_RSA_PKCS1_PSS_PADDING:
{
- enum wc_HashType hType =
- wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
- #ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER
- WOLFSSL_MSG("Using RSA-PSS with hash length salt. "
- "OpenSSL uses max length by default.");
- #endif
+ RsaKey* key = (RsaKey*)rsa->internal;
+ enum wc_HashType mgf1, hType;
+ hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
+ if (mgf1Hash == WC_NID_undef)
+ mgf1Hash = hashAlg;
+ mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType));
+ /* handle compat layer salt special cases */
+ saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType),
+ wolfSSL_RSA_size(rsa));
+
/* Create RSA PSS signature. */
if ((signSz = wc_RsaPSS_Sign_ex(encodedSig, encSz, sigRet, outLen,
- hType, wc_hash2mgf(hType), DEF_PSS_SALT_LEN,
- (RsaKey*)rsa->internal, rng)) <= 0) {
- WOLFSSL_ERROR_MSG("Bad Rsa Sign");
+ hType, wc_hash2mgf(mgf1), saltLen, key, rng)) <= 0) {
+ WOLFSSL_ERROR_MSG("Bad RSA PSS Sign");
ret = 0;
}
break;
}
#endif
#ifndef WC_NO_RSA_OAEP
- case RSA_PKCS1_OAEP_PADDING:
+ case WC_RSA_PKCS1_OAEP_PADDING:
/* Not a signature padding scheme. */
WOLFSSL_ERROR_MSG("RSA_PKCS1_OAEP_PADDING not supported for "
"signing");
ret = 0;
break;
#endif
- case RSA_PKCS1_PADDING:
+ case WC_RSA_PKCS1_PADDING:
{
/* Sign (private encrypt) PKCS#1 encoded signature. */
if ((signSz = wc_RsaSSL_Sign(encodedSig, encSz, sigRet, outLen,
(RsaKey*)rsa->internal, rng)) <= 0) {
- WOLFSSL_ERROR_MSG("Bad Rsa Sign");
+ WOLFSSL_ERROR_MSG("Bad PKCS1 RSA Sign");
ret = 0;
}
break;
}
default:
WOLFSSL_ERROR_MSG("Unsupported padding");
+ (void)mgf1Hash;
+ (void)saltLen;
ret = 0;
break;
}
@@ -3900,13 +4141,10 @@ int wolfSSL_RSA_sign_generic_padding(int hashAlg, const unsigned char* hash,
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
-#ifdef WOLFSSL_SMALL_STACK
- /* Dispose of any allocated RNG and encoded signature. */
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE);
-#endif
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+ WC_FREE_VAR_EX(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE);
- WOLFSSL_LEAVE("wolfSSL_RSA_sign_generic_padding", ret);
+ WOLFSSL_LEAVE("wolfSSL_RSA_sign_mgf", ret);
return ret;
}
@@ -3927,7 +4165,15 @@ int wolfSSL_RSA_verify(int hashAlg, const unsigned char* hash,
WOLFSSL_RSA* rsa)
{
return wolfSSL_RSA_verify_ex(hashAlg, hash, hLen, sig, sigLen, rsa,
- RSA_PKCS1_PADDING);
+ WC_RSA_PKCS1_PADDING);
+}
+
+int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash,
+ unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
+ WOLFSSL_RSA* rsa, int padding)
+{
+ return wolfSSL_RSA_verify_mgf(hashAlg, hash, hLen, sig, sigLen, rsa,
+ padding, hashAlg, DEF_PSS_SALT_LEN);
}
/**
@@ -3942,14 +4188,16 @@ int wolfSSL_RSA_verify(int hashAlg, const unsigned char* hash,
* @param [in] sigLen Length of signature data.
* @param [in] rsa RSA key used to sign the input
* @param [in] padding Padding to use. Only RSA_PKCS1_PSS_PADDING and
- * RSA_PKCS1_PADDING are currently supported for
+ * WC_RSA_PKCS1_PADDING are currently supported for
* signing.
+ * @param [in] mgf1Hash MGF1 Hash NID
+ * @param [in] saltLen Length of RSA PSS salt
* @return 1 on success.
* @return 0 on failure.
*/
-int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash,
+int wolfSSL_RSA_verify_mgf(int hashAlg, const unsigned char* hash,
unsigned int hLen, const unsigned char* sig, unsigned int sigLen,
- WOLFSSL_RSA* rsa, int padding)
+ WOLFSSL_RSA* rsa, int padding, int mgf1Hash, int saltLen)
{
int ret = 1;
#ifdef WOLFSSL_SMALL_STACK
@@ -3964,7 +4212,7 @@ int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash,
enum wc_HashType hType = WC_HASH_TYPE_NONE;
#endif
- WOLFSSL_ENTER("wolfSSL_RSA_verify");
+ WOLFSSL_ENTER("wolfSSL_RSA_verify_mgf");
/* Validate parameters. */
if ((hash == NULL) || (sig == NULL) || (rsa == NULL)) {
@@ -3981,18 +4229,59 @@ int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash,
ret = 0;
}
}
-#ifdef WOLFSSL_SMALL_STACK
- if ((ret == 1) && (padding != RSA_PKCS1_PSS_PADDING)) {
- /* Allocate memory for encoded signature. */
- encodedSig = (unsigned char *)XMALLOC(len, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig == NULL) {
- WOLFSSL_ERROR_MSG("Memory allocation failure");
- ret = 0;
+ if (ret == 1 && padding == WC_RSA_PKCS1_PSS_PADDING) {
+ #if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
+ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,1))
+ RsaKey* key = (RsaKey*)rsa->internal;
+ enum wc_HashType mgf1;
+ hType = wc_OidGetHash((int)nid2oid(hashAlg, oidHashType));
+ if (mgf1Hash == WC_NID_undef)
+ mgf1Hash = hashAlg;
+ mgf1 = wc_OidGetHash((int)nid2oid(mgf1Hash, oidHashType));
+
+ /* handle compat layer salt special cases */
+ saltLen = rsa_pss_calc_salt(saltLen, wc_HashGetDigestSize(hType),
+ wolfSSL_RSA_size(rsa));
+
+ verLen = wc_RsaPSS_Verify_ex((byte*)sig, sigLen, sigDec, sigLen,
+ hType, wc_hash2mgf(mgf1), saltLen, key);
+ if (verLen > 0) {
+ /* Check PSS padding is valid. */
+ if (wc_RsaPSS_CheckPadding_ex(hash, hLen, sigDec, (word32)verLen,
+ hType, saltLen, mp_count_bits(&key->n)) != 0) {
+ WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error");
+ ret = WOLFSSL_FAILURE;
+ }
+ else {
+ /* Success! Free resources and return early */
+ XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_SUCCESS;
+ }
+ }
+ else {
+ WOLFSSL_ERROR_MSG("wc_RsaPSS_Verify_ex failed!");
+ ret = WOLFSSL_FAILURE;
+ }
+ #else
+ (void)mgf1Hash;
+ (void)saltLen;
+ WOLFSSL_ERROR_MSG("RSA PSS not compiled in!");
+ ret = WOLFSSL_FAILURE;
+ #endif
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ if (ret == 1) {
+ /* Allocate memory for encoded signature. */
+ encodedSig = (unsigned char *)XMALLOC(len, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (encodedSig == NULL) {
+ WOLFSSL_ERROR_MSG("Memory allocation failure");
+ ret = 0;
}
}
#endif
- if ((ret == 1) && (padding != RSA_PKCS1_PSS_PADDING)) {
+ if (ret == 1) {
/* Make encoded signature to compare with decrypted signature. */
if (wolfssl_rsa_sig_encode(hashAlg, hash, hLen, encodedSig, &len,
padding) <= 0) {
@@ -4019,20 +4308,6 @@ int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash,
#endif
}
if (ret == 1) {
- #if defined(WC_RSA_PSS) && !defined(HAVE_SELFTEST) && \
- (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 1))
- if (padding == RSA_PKCS1_PSS_PADDING) {
- /* Check PSS padding is valid. */
- if (wc_RsaPSS_CheckPadding_ex(hash, hLen, sigDec, (word32)verLen,
- hType, DEF_PSS_SALT_LEN,
- mp_count_bits(&((RsaKey*)rsa->internal)->n)) != 0) {
- WOLFSSL_ERROR_MSG("wc_RsaPSS_CheckPadding_ex error");
- ret = 0;
- }
- }
- else
- #endif /* WC_RSA_PSS && !HAVE_SELFTEST && (!HAVE_FIPS ||
- * FIPS_VERSION >= 5.1) */
/* Compare decrypted signature to encoded signature. */
if (((int)len != verLen) ||
(XMEMCMP(encodedSig, sigDec, (size_t)verLen) != 0)) {
@@ -4042,10 +4317,10 @@ int wolfSSL_RSA_verify_ex(int hashAlg, const unsigned char* hash,
}
/* Dispose of any allocated data. */
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ WOLFSSL_LEAVE("wolfSSL_RSA_verify_mgf", ret);
return ret;
}
@@ -4090,43 +4365,43 @@ int wolfSSL_RSA_public_encrypt(int len, const unsigned char* from,
if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
(from == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
#if !defined(HAVE_FIPS)
/* Convert to wolfCrypt padding, hash and MGF. */
switch (padding) {
- case RSA_PKCS1_PADDING:
+ case WC_RSA_PKCS1_PADDING:
pad_type = WC_RSA_PKCSV15_PAD;
break;
- case RSA_PKCS1_OAEP_PADDING:
+ case WC_RSA_PKCS1_OAEP_PADDING:
pad_type = WC_RSA_OAEP_PAD;
hash = WC_HASH_TYPE_SHA;
mgf = WC_MGF1SHA1;
break;
- case RSA_NO_PADDING:
+ case WC_RSA_NO_PAD:
pad_type = WC_RSA_NO_PAD;
break;
default:
WOLFSSL_ERROR_MSG("RSA_public_encrypt doesn't support padding "
"scheme");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
#else
/* Check for supported padding schemes in FIPS. */
/* TODO: Do we support more schemes in later versions of FIPS? */
- if (padding != RSA_PKCS1_PADDING) {
+ if (padding != WC_RSA_PKCS1_PADDING) {
WOLFSSL_ERROR_MSG("RSA_public_encrypt pad type not supported in "
"FIPS");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
#endif
}
/* Set wolfCrypt RSA key data from external if not already done. */
if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
@@ -4134,7 +4409,7 @@ int wolfSSL_RSA_public_encrypt(int len, const unsigned char* from,
outLen = wolfSSL_RSA_size(rsa);
if (outLen == 0) {
WOLFSSL_ERROR_MSG("Bad RSA size");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
@@ -4142,7 +4417,7 @@ int wolfSSL_RSA_public_encrypt(int len, const unsigned char* from,
/* Get an RNG. */
rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
if (rng == NULL) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
@@ -4161,14 +4436,11 @@ int wolfSSL_RSA_public_encrypt(int len, const unsigned char* from,
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
-#ifdef WOLFSSL_SMALL_STACK
- /* Dispose of any allocated RNG. */
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-#endif
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
/* wolfCrypt error means return -1. */
if (ret <= 0) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
WOLFSSL_LEAVE("wolfSSL_RSA_public_encrypt", ret);
return ret;
@@ -4203,41 +4475,41 @@ int wolfSSL_RSA_private_decrypt(int len, const unsigned char* from,
if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
(from == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
#if !defined(HAVE_FIPS)
switch (padding) {
- case RSA_PKCS1_PADDING:
+ case WC_RSA_PKCS1_PADDING:
pad_type = WC_RSA_PKCSV15_PAD;
break;
- case RSA_PKCS1_OAEP_PADDING:
+ case WC_RSA_PKCS1_OAEP_PADDING:
pad_type = WC_RSA_OAEP_PAD;
hash = WC_HASH_TYPE_SHA;
mgf = WC_MGF1SHA1;
break;
- case RSA_NO_PADDING:
+ case WC_RSA_NO_PAD:
pad_type = WC_RSA_NO_PAD;
break;
default:
WOLFSSL_ERROR_MSG("RSA_private_decrypt unsupported padding");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
#else
/* Check for supported padding schemes in FIPS. */
/* TODO: Do we support more schemes in later versions of FIPS? */
- if (padding != RSA_PKCS1_PADDING) {
+ if (padding != WC_RSA_PKCS1_PADDING) {
WOLFSSL_ERROR_MSG("RSA_public_encrypt pad type not supported in "
"FIPS");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
#endif
}
/* Set wolfCrypt RSA key data from external if not already done. */
if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
@@ -4245,7 +4517,7 @@ int wolfSSL_RSA_private_decrypt(int len, const unsigned char* from,
outLen = wolfSSL_RSA_size(rsa);
if (outLen == 0) {
WOLFSSL_ERROR_MSG("Bad RSA size");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
@@ -4263,7 +4535,7 @@ int wolfSSL_RSA_private_decrypt(int len, const unsigned char* from,
/* wolfCrypt error means return -1. */
if (ret <= 0) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
WOLFSSL_LEAVE("wolfSSL_RSA_private_decrypt", ret);
return ret;
@@ -4294,35 +4566,35 @@ int wolfSSL_RSA_public_decrypt(int len, const unsigned char* from,
if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
(from == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
switch (padding) {
- case RSA_PKCS1_PADDING:
+ case WC_RSA_PKCS1_PADDING:
pad_type = WC_RSA_PKCSV15_PAD;
break;
- case RSA_NO_PADDING:
+ case WC_RSA_NO_PAD:
pad_type = WC_RSA_NO_PAD;
break;
/* TODO: RSA_X931_PADDING not supported */
default:
WOLFSSL_ERROR_MSG("RSA_public_decrypt unsupported padding");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
#else
- if (padding != RSA_PKCS1_PADDING) {
+ if (padding != WC_RSA_PKCS1_PADDING) {
WOLFSSL_ERROR_MSG("RSA_public_decrypt pad type not supported in "
"FIPS");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
#endif
}
/* Set wolfCrypt RSA key data from external if not already done. */
if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
@@ -4330,7 +4602,7 @@ int wolfSSL_RSA_public_decrypt(int len, const unsigned char* from,
outLen = wolfSSL_RSA_size(rsa);
if (outLen == 0) {
WOLFSSL_ERROR_MSG("Bad RSA size");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
@@ -4349,7 +4621,7 @@ int wolfSSL_RSA_public_decrypt(int len, const unsigned char* from,
/* wolfCrypt error means return -1. */
if (ret <= 0) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
WOLFSSL_LEAVE("wolfSSL_RSA_public_decrypt", ret);
return ret;
@@ -4386,45 +4658,45 @@ int wolfSSL_RSA_private_encrypt(int len, const unsigned char* from,
if ((len < 0) || (rsa == NULL) || (rsa->internal == NULL) ||
(from == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
switch (padding) {
- case RSA_PKCS1_PADDING:
+ case WC_RSA_PKCS1_PADDING:
#ifdef WC_RSA_NO_PADDING
- case RSA_NO_PADDING:
+ case WC_RSA_NO_PAD:
#endif
break;
/* TODO: RSA_X931_PADDING not supported */
default:
WOLFSSL_ERROR_MSG("RSA_private_encrypt unsupported padding");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
/* Set wolfCrypt RSA key data from external if not already done. */
if ((ret == 0) && (!rsa->inSet) && (SetRsaInternal(rsa) != 1)) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
/* Get an RNG. */
rng = WOLFSSL_RSA_GetRNG(rsa, (WC_RNG**)&tmpRng, &initTmpRng);
if (rng == NULL) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
/* Use wolfCrypt to private-encrypt with RSA key.
* Size of output buffer must be size of RSA key. */
- if (padding == RSA_PKCS1_PADDING) {
+ if (padding == WC_RSA_PKCS1_PADDING) {
ret = wc_RsaSSL_Sign(from, (word32)len, to,
(word32)wolfSSL_RSA_size(rsa), (RsaKey*)rsa->internal, rng);
}
#ifdef WC_RSA_NO_PADDING
- else if (padding == RSA_NO_PADDING) {
+ else if (padding == WC_RSA_NO_PAD) {
word32 outLen = (word32)wolfSSL_RSA_size(rsa);
ret = wc_RsaFunction(from, (word32)len, to, &outLen,
RSA_PRIVATE_ENCRYPT, (RsaKey*)rsa->internal, rng);
@@ -4438,14 +4710,11 @@ int wolfSSL_RSA_private_encrypt(int len, const unsigned char* from,
if (initTmpRng) {
wc_FreeRng(tmpRng);
}
-#ifdef WOLFSSL_SMALL_STACK
- /* Dispose of any allocated RNG. */
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-#endif
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
/* wolfCrypt error means return -1. */
if (ret <= 0) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", ret);
return ret;
@@ -4468,11 +4737,7 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
int ret = 1;
int err;
mp_int* t = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- mp_int *tmp = NULL;
-#else
- mp_int tmp[1];
-#endif
+ WC_DECLARE_VAR(tmp, mp_int, 1, 0);
WOLFSSL_ENTER("wolfSSL_RsaGenAdd");
@@ -4480,7 +4745,7 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
if ((rsa == NULL) || (rsa->p == NULL) || (rsa->q == NULL) ||
(rsa->d == NULL) || (rsa->dmp1 == NULL) || (rsa->dmq1 == NULL)) {
WOLFSSL_ERROR_MSG("rsa no init error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
#ifdef WOLFSSL_SMALL_STACK
@@ -4489,7 +4754,7 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
WOLFSSL_ERROR_MSG("Memory allocation failure");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
#endif
@@ -4498,7 +4763,7 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
/* Initialize temp MP integer. */
if (mp_init(tmp) != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_init error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
@@ -4509,7 +4774,7 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
err = mp_sub_d((mp_int*)rsa->p->internal, 1, tmp);
if (err != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_sub_d error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
@@ -4518,7 +4783,7 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
(mp_int*)rsa->dmp1->internal);
if (err != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_mod error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
@@ -4526,7 +4791,7 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
err = mp_sub_d((mp_int*)rsa->q->internal, 1, tmp);
if (err != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_sub_d error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
@@ -4535,15 +4800,16 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa)
(mp_int*)rsa->dmq1->internal);
if (err != MP_OKAY) {
WOLFSSL_ERROR_MSG("mp_mod error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
mp_clear(t);
#ifdef WOLFSSL_SMALL_STACK
- if (tmp != NULL)
+ if (rsa != NULL) {
XFREE(tmp, rsa->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
#endif
return ret;
@@ -4716,34 +4982,34 @@ int SetDsaExternal(WOLFSSL_DSA* dsa)
if (dsa == NULL || dsa->internal == NULL) {
WOLFSSL_MSG("dsa key NULL error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
key = (DsaKey*)dsa->internal;
if (wolfssl_bn_set_value(&dsa->p, &key->p) != 1) {
WOLFSSL_MSG("dsa p key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (wolfssl_bn_set_value(&dsa->q, &key->q) != 1) {
WOLFSSL_MSG("dsa q key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (wolfssl_bn_set_value(&dsa->g, &key->g) != 1) {
WOLFSSL_MSG("dsa g key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (wolfssl_bn_set_value(&dsa->pub_key, &key->y) != 1) {
WOLFSSL_MSG("dsa y key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (wolfssl_bn_set_value(&dsa->priv_key, &key->x) != 1) {
WOLFSSL_MSG("dsa x key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
dsa->exSet = 1;
@@ -4761,7 +5027,7 @@ int SetDsaInternal(WOLFSSL_DSA* dsa)
if (dsa == NULL || dsa->internal == NULL) {
WOLFSSL_MSG("dsa key NULL error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
key = (DsaKey*)dsa->internal;
@@ -4769,25 +5035,25 @@ int SetDsaInternal(WOLFSSL_DSA* dsa)
if (dsa->p != NULL &&
wolfssl_bn_get_value(dsa->p, &key->p) != 1) {
WOLFSSL_MSG("rsa p key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (dsa->q != NULL &&
wolfssl_bn_get_value(dsa->q, &key->q) != 1) {
WOLFSSL_MSG("rsa q key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (dsa->g != NULL &&
wolfssl_bn_get_value(dsa->g, &key->g) != 1) {
WOLFSSL_MSG("rsa g key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (dsa->pub_key != NULL) {
if (wolfssl_bn_get_value(dsa->pub_key, &key->y) != 1) {
WOLFSSL_MSG("rsa pub_key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* public key */
@@ -4797,7 +5063,7 @@ int SetDsaInternal(WOLFSSL_DSA* dsa)
if (dsa->priv_key != NULL) {
if (wolfssl_bn_get_value(dsa->priv_key, &key->x) != 1) {
WOLFSSL_MSG("rsa priv_key error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* private key */
@@ -4836,17 +5102,10 @@ int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa)
{
int initTmpRng = 0;
WC_RNG *rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG *tmpRng;
-#else
- WC_RNG tmpRng[1];
-#endif
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
-#ifdef WOLFSSL_SMALL_STACK
- tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (tmpRng == NULL)
- return -1;
-#endif
+ WC_ALLOC_VAR_EX(tmpRng, WC_RNG, 1, NULL, DYNAMIC_TYPE_RNG,
+ return WOLFSSL_FATAL_ERROR);
if (wc_InitRng(tmpRng) == 0) {
rng = tmpRng;
initTmpRng = 1;
@@ -4874,9 +5133,7 @@ int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa)
if (initTmpRng)
wc_FreeRng(tmpRng);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-#endif
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
}
#else /* WOLFSSL_KEY_GEN */
WOLFSSL_MSG("No Key Gen built in");
@@ -4940,17 +5197,10 @@ int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits,
{
int initTmpRng = 0;
WC_RNG *rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG *tmpRng;
-#else
- WC_RNG tmpRng[1];
-#endif
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
-#ifdef WOLFSSL_SMALL_STACK
- tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (tmpRng == NULL)
- return -1;
-#endif
+ WC_ALLOC_VAR_EX(tmpRng, WC_RNG, 1, NULL, DYNAMIC_TYPE_RNG,
+ return WOLFSSL_FATAL_ERROR);
if (wc_InitRng(tmpRng) == 0) {
rng = tmpRng;
initTmpRng = 1;
@@ -4973,9 +5223,7 @@ int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits,
if (initTmpRng)
wc_FreeRng(tmpRng);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-#endif
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
}
#else /* WOLFSSL_KEY_GEN */
WOLFSSL_MSG("No Key Gen built in");
@@ -5121,20 +5369,20 @@ int wolfSSL_i2d_DSA_SIG(const WOLFSSL_DSA_SIG *sig, byte **out)
if (sig == NULL || sig->r == NULL || sig->s == NULL ||
out == NULL) {
WOLFSSL_MSG("Bad function arguments");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (StoreECC_DSA_Sig(buf, &bufLen,
(mp_int*)sig->r->internal, (mp_int*)sig->s->internal) != 0) {
WOLFSSL_MSG("StoreECC_DSA_Sig error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (*out == NULL) {
byte* tmp = (byte*)XMALLOC(bufLen, NULL, DYNAMIC_TYPE_ASN1);
if (tmp == NULL) {
WOLFSSL_MSG("malloc error");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
*out = tmp;
}
@@ -5258,41 +5506,32 @@ WOLFSSL_DSA_SIG* wolfSSL_d2i_DSA_SIG(WOLFSSL_DSA_SIG **sig,
return ret;
}
-#endif /* HAVE_SELFTEST */
-/* return 1 on success, < 0 otherwise */
-int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet,
- WOLFSSL_DSA* dsa)
+#endif /* !HAVE_SELFTEST */
+
+static int dsa_do_sign(const unsigned char* d, int dLen, unsigned char* sigRet,
+ WOLFSSL_DSA* dsa)
{
- int ret = -1;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
int initTmpRng = 0;
WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG tmpRng[1];
-#endif
-
- WOLFSSL_ENTER("wolfSSL_DSA_do_sign");
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
if (d == NULL || sigRet == NULL || dsa == NULL) {
WOLFSSL_MSG("Bad function arguments");
- return ret;
+ return WOLFSSL_FATAL_ERROR;
}
if (dsa->inSet == 0) {
WOLFSSL_MSG("No DSA internal set, do it");
if (SetDsaInternal(dsa) != 1) {
WOLFSSL_MSG("SetDsaInternal failed");
- return ret;
+ return WOLFSSL_FATAL_ERROR;
}
}
-#ifdef WOLFSSL_SMALL_STACK
- tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
- if (tmpRng == NULL)
- return -1;
-#endif
+ WC_ALLOC_VAR_EX(tmpRng, WC_RNG, 1, NULL, DYNAMIC_TYPE_RNG,
+ return WOLFSSL_FATAL_ERROR);
if (wc_InitRng(tmpRng) == 0) {
rng = tmpRng;
@@ -5300,25 +5539,48 @@ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet,
}
else {
WOLFSSL_MSG("Bad RNG Init, trying global");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
+ tmpRng = NULL;
+#endif
rng = wolfssl_get_global_rng();
+ if (! rng)
+ return WOLFSSL_FATAL_ERROR;
}
if (rng) {
- if (wc_DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0)
- WOLFSSL_MSG("DsaSign failed");
+#ifdef HAVE_SELFTEST
+ if (dLen != WC_SHA_DIGEST_SIZE ||
+ wc_DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0) {
+ WOLFSSL_MSG("wc_DsaSign failed or dLen wrong length");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+#else
+ if (wc_DsaSign_ex(d, dLen, sigRet, (DsaKey*)dsa->internal, rng) < 0) {
+ WOLFSSL_MSG("wc_DsaSign_ex failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+#endif
else
- ret = 1;
+ ret = WOLFSSL_SUCCESS;
}
if (initTmpRng)
wc_FreeRng(tmpRng);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
-#endif
+ WC_FREE_VAR_EX(tmpRng, NULL, DYNAMIC_TYPE_RNG);
return ret;
}
+/* return 1 on success, < 0 otherwise */
+int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet,
+ WOLFSSL_DSA* dsa)
+{
+ WOLFSSL_ENTER("wolfSSL_DSA_do_sign");
+
+ return dsa_do_sign(d, WC_SHA_DIGEST_SIZE, sigRet, dsa);
+}
+
#ifndef HAVE_SELFTEST
WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest,
int inLen, WOLFSSL_DSA* dsa)
@@ -5329,12 +5591,12 @@ WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest,
WOLFSSL_ENTER("wolfSSL_DSA_do_sign_ex");
- if (!digest || !dsa || inLen != WC_SHA_DIGEST_SIZE) {
+ if (!digest || !dsa) {
WOLFSSL_MSG("Bad function arguments");
return NULL;
}
- if (wolfSSL_DSA_do_sign(digest, sigBin, dsa) != 1) {
+ if (dsa_do_sign(digest, inLen, sigBin, dsa) != 1) {
WOLFSSL_MSG("wolfSSL_DSA_do_sign error");
return NULL;
}
@@ -5353,18 +5615,16 @@ WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest,
/* 2 * sigLen for the two points r and s */
return wolfSSL_d2i_DSA_SIG(NULL, &tmp, 2 * sigLen);
}
-#endif /* !HAVE_SELFTEST */
+#endif
-int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig,
+static int dsa_do_verify(const unsigned char* d, int dLen, unsigned char* sig,
WOLFSSL_DSA* dsa, int *dsacheck)
{
- int ret = -1;
-
- WOLFSSL_ENTER("wolfSSL_DSA_do_verify");
+ int ret;
if (d == NULL || sig == NULL || dsa == NULL) {
WOLFSSL_MSG("Bad function arguments");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (dsa->inSet == 0)
{
@@ -5372,17 +5632,35 @@ int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig,
if (SetDsaInternal(dsa) != 1) {
WOLFSSL_MSG("SetDsaInternal failed");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
- ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck);
- if (ret != 0 || *dsacheck != 1) {
+#ifdef HAVE_SELFTEST
+ ret = dLen == WC_SHA_DIGEST_SIZE ?
+ wc_DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck) : BAD_FUNC_ARG;
+#else
+ ret = wc_DsaVerify_ex(d, (word32)dLen, sig, (DsaKey*)dsa->internal,
+ dsacheck);
+#endif
+ if (ret != 0) {
WOLFSSL_MSG("DsaVerify failed");
- return ret;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ if (*dsacheck != 1) {
+ WOLFSSL_MSG("DsaVerify sig failed");
+ return WOLFSSL_FAILURE;
}
- return 1;
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig,
+ WOLFSSL_DSA* dsa, int *dsacheck)
+{
+ WOLFSSL_ENTER("wolfSSL_DSA_do_verify");
+
+ return dsa_do_verify(d, WC_SHA_DIGEST_SIZE, sig, dsa, dsacheck);
}
@@ -5407,7 +5685,7 @@ int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len,
WOLFSSL_ENTER("wolfSSL_DSA_do_verify_ex");
- if (!digest || !sig || !dsa || digest_len != WC_SHA_DIGEST_SIZE) {
+ if (!digest || !sig || !dsa) {
WOLFSSL_MSG("Bad function arguments");
return 0;
}
@@ -5459,16 +5737,16 @@ int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len,
if (wolfSSL_BN_bn2bin(sig->s, sigBinPtr) == -1)
return 0;
- if ((wolfSSL_DSA_do_verify(digest, sigBin, dsa, &dsacheck)
+ if ((dsa_do_verify(digest, digest_len, sigBin, dsa, &dsacheck)
!= 1) || dsacheck != 1) {
return 0;
}
return 1;
}
-#endif /* !HAVE_SELFTEST */
+#endif
-WOLFSSL_API int wolfSSL_i2d_DSAparams(const WOLFSSL_DSA* dsa,
+int wolfSSL_i2d_DSAparams(const WOLFSSL_DSA* dsa,
unsigned char** out)
{
int ret = 0;
@@ -5485,7 +5763,7 @@ WOLFSSL_API int wolfSSL_i2d_DSAparams(const WOLFSSL_DSA* dsa,
if (ret == 0) {
key = (DsaKey*)dsa->internal;
ret = wc_DsaKeyToParamsDer_ex(key, NULL, &derLen);
- if (ret == LENGTH_ONLY_E) {
+ if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
ret = 0;
}
}
@@ -5577,99 +5855,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 WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
+ wc_pem_password_cb* cb, void* arg)
{
- int ret = 0, der_max_len = 0, derSz = 0;
- byte *derBuf;
- WOLFSSL_EVP_PKEY* pkey;
+ int ret = 1;
+ byte *pem = NULL;
+ int pLen = 0;
WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSAPrivateKey");
- if (bio == NULL || dsa == NULL) {
+ (void)cb;
+ (void)arg;
+
+ /* Validate parameters. */
+ if ((bio == NULL) || (dsa == NULL)) {
WOLFSSL_MSG("Bad Function Arguments");
- return 0;
+ ret = 0;
}
- pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
- if (pkey == NULL) {
- WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
- return 0;
+ if (ret == 1) {
+ ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, cipher, passwd, passwdSz,
+ &pem, &pLen);
}
- pkey->type = EVP_PKEY_DSA;
- pkey->dsa = dsa;
- pkey->ownDsa = 0;
+ /* Write PEM to BIO. */
+ if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) != pLen)) {
+ WOLFSSL_ERROR_MSG("DSA private key BIO write failed");
+ ret = 0;
+ }
- /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */
- der_max_len = MAX_DSA_PRIVKEY_SZ;
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
+ return ret;
+}
- derBuf = (byte*)XMALLOC((size_t)der_max_len, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (derBuf == NULL) {
- WOLFSSL_MSG("Malloc failed");
- wolfSSL_EVP_PKEY_free(pkey);
- return 0;
- }
+#ifndef HAVE_SELFTEST
+/* Encode the DSA public key as DER.
+ *
+ * @param [in] key DSA key to encode.
+ * @param [out] der Pointer through which buffer is returned.
+ * @param [in] heap Heap hint.
+ * @return Size of encoding on success.
+ * @return 0 on error.
+ */
+static int wolfssl_dsa_key_to_pubkey_der(WOLFSSL_DSA* key, unsigned char** der,
+ void* heap)
+{
+ int sz;
+ unsigned char* buf = NULL;
- /* convert key to der format */
- derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, (word32)der_max_len);
- if (derSz < 0) {
- WOLFSSL_MSG("wc_DsaKeyToDer failed");
- XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- wolfSSL_EVP_PKEY_free(pkey);
- return 0;
+ /* Use maximum encoded size to allocate. */
+ sz = MAX_DSA_PUBKEY_SZ;
+ /* Allocate memory to hold encoding. */
+ buf = (byte*)XMALLOC((size_t)sz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf == NULL) {
+ WOLFSSL_MSG("malloc failed");
+ sz = 0;
}
-
- pkey->pkey.ptr = (char*)XMALLOC((size_t)derSz, bio->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (pkey->pkey.ptr == NULL) {
- WOLFSSL_MSG("key malloc failed");
- XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- wolfSSL_EVP_PKEY_free(pkey);
- return 0;
+ if (sz > 0) {
+ /* Encode public key to DER using wolfSSL. */
+ sz = wc_DsaKeyToPublicDer((DsaKey*)key->internal, buf, (word32)sz);
+ if (sz < 0) {
+ WOLFSSL_MSG("wc_DsaKeyToPublicDer failed");
+ sz = 0;
+ }
}
- /* add der info to the evp key */
- pkey->pkey_sz = derSz;
- XMEMCPY(pkey->pkey.ptr, derBuf, (size_t)derSz);
- XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
- ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
- cb, arg);
- wolfSSL_EVP_PKEY_free(pkey);
+ /* Return buffer on success. */
+ if (sz > 0) {
+ *der = buf;
+ }
+ else {
+ /* Dispose of any dynamically allocated data not returned. */
+ XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
- return ret;
+ return sz;
}
-#ifndef HAVE_SELFTEST
/* Takes a DSA public key and writes it out to a WOLFSSL_BIO
* Returns 1 or 0
*/
int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa)
{
- int ret = 0;
- WOLFSSL_EVP_PKEY* pkey;
+ int ret = 1;
+ unsigned char* derBuf = NULL;
+ int derSz = 0;
+
WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSA_PUBKEY");
- if (bio == NULL || dsa == NULL) {
- WOLFSSL_MSG("Bad function arguments");
+ /* Validate parameters. */
+ if ((bio == NULL) || (dsa == NULL)) {
+ WOLFSSL_MSG("Bad Function Arguments");
return 0;
}
- pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
- if (pkey == NULL) {
- WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
- return 0;
+ /* Encode public key in EC key as DER. */
+ derSz = wolfssl_dsa_key_to_pubkey_der(dsa, &derBuf, bio->heap);
+ if (derSz == 0) {
+ ret = 0;
}
- pkey->type = EVP_PKEY_DSA;
- pkey->dsa = dsa;
- pkey->ownDsa = 0;
+ /* Write out to BIO the PEM encoding of the DSA public key. */
+ if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio,
+ PUBLICKEY_TYPE) != 1)) {
+ ret = 0;
+ }
+
+ /* Dispose of any dynamically allocated data. */
+ XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- ret = pem_write_bio_pubkey(bio, pkey);
- wolfSSL_EVP_PKEY_free(pkey);
return ret;
}
#endif /* HAVE_SELFTEST */
@@ -5679,11 +5973,12 @@ int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa)
* 1 if success, 0 if error
*/
int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
- const EVP_CIPHER* cipher,
+ const WOLFSSL_EVP_CIPHER* cipher,
unsigned char* passwd, int passwdSz,
unsigned char **pem, int *pLen)
{
-#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+#if (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) && \
+ !defined(NO_MD5)
byte *derBuf, *tmp, *cipherInfo = NULL;
int der_max_len = 0, derSz = 0;
const int type = DSA_PRIVATEKEY_TYPE;
@@ -5729,8 +6024,8 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
int ret;
- ret = EncryptDerKey(derBuf, &derSz, cipher,
- passwd, passwdSz, &cipherInfo, der_max_len);
+ ret = EncryptDerKey(derBuf, &derSz, cipher, passwd, passwdSz,
+ &cipherInfo, der_max_len, WC_MD5);
if (ret != 1) {
WOLFSSL_MSG("EncryptDerKey failed");
XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
@@ -5749,8 +6044,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
if (tmp == NULL) {
WOLFSSL_MSG("malloc failed");
XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
- if (cipherInfo != NULL)
- XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
return 0;
}
@@ -5761,13 +6055,11 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
WOLFSSL_MSG("wc_DerToPemEx failed");
XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
- if (cipherInfo != NULL)
- XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
return 0;
}
XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
- if (cipherInfo != NULL)
- XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
+ XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING);
*pem = (byte*)XMALLOC((size_t)((*pLen)+1), NULL, DYNAMIC_TYPE_KEY);
if (*pem == NULL) {
@@ -5794,7 +6086,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
(void)pem;
(void)pLen;
return 0;
-#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+#endif /* (WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM) && !NO_MD5 */
}
#ifndef NO_FILESYSTEM
@@ -5802,7 +6094,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
* 1 if success, 0 if error
*/
int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa,
- const EVP_CIPHER *enc,
+ const WOLFSSL_EVP_CIPHER *enc,
unsigned char *kstr, int klen,
wc_pem_password_cb *cb, void *u)
{
@@ -5943,19 +6235,19 @@ int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz
if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) {
WOLFSSL_MSG("Bad function arguments");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal,
(word32)derSz);
if (ret < 0) {
WOLFSSL_MSG("DsaPrivateKeyDecode failed");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (SetDsaExternal(dsa) != 1) {
WOLFSSL_MSG("SetDsaExternal failed");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
dsa->inSet = 1;
@@ -5975,7 +6267,7 @@ int wolfSSL_DSA_LoadDer_ex(WOLFSSL_DSA* dsa, const unsigned char* derBuf,
if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) {
WOLFSSL_MSG("Bad function arguments");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (opt == WOLFSSL_DSA_LOAD_PRIVATE) {
@@ -5990,17 +6282,17 @@ int wolfSSL_DSA_LoadDer_ex(WOLFSSL_DSA* dsa, const unsigned char* derBuf,
if (ret < 0 && opt == WOLFSSL_DSA_LOAD_PRIVATE) {
WOLFSSL_ERROR_VERBOSE(ret);
WOLFSSL_MSG("DsaPrivateKeyDecode failed");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
else if (ret < 0 && opt == WOLFSSL_DSA_LOAD_PUBLIC) {
WOLFSSL_ERROR_VERBOSE(ret);
WOLFSSL_MSG("DsaPublicKeyDecode failed");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (SetDsaExternal(dsa) != 1) {
WOLFSSL_MSG("SetDsaExternal failed");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
dsa->inSet = 1;
@@ -6248,17 +6540,17 @@ static int wolfssl_dh_set_nid(WOLFSSL_DH* dh, int nid)
* FIPS v2 module */
switch (nid) {
#ifdef HAVE_FFDHE_2048
- case NID_ffdhe2048:
+ case WC_NID_ffdhe2048:
params = wc_Dh_ffdhe2048_Get();
break;
#endif /* HAVE_FFDHE_2048 */
#ifdef HAVE_FFDHE_3072
- case NID_ffdhe3072:
+ case WC_NID_ffdhe3072:
params = wc_Dh_ffdhe3072_Get();
break;
#endif /* HAVE_FFDHE_3072 */
#ifdef HAVE_FFDHE_4096
- case NID_ffdhe4096:
+ case WC_NID_ffdhe4096:
params = wc_Dh_ffdhe4096_Get();
break;
#endif /* HAVE_FFDHE_4096 */
@@ -6344,17 +6636,17 @@ static int wolfssl_dh_set_nid(WOLFSSL_DH* dh, int nid)
switch (nid) {
#ifdef HAVE_FFDHE_2048
- case NID_ffdhe2048:
+ case WC_NID_ffdhe2048:
name = WC_FFDHE_2048;
break;
#endif /* HAVE_FFDHE_2048 */
#ifdef HAVE_FFDHE_3072
- case NID_ffdhe3072:
+ case WC_NID_ffdhe3072:
name = WC_FFDHE_3072;
break;
#endif /* HAVE_FFDHE_3072 */
#ifdef HAVE_FFDHE_4096
- case NID_ffdhe4096:
+ case WC_NID_ffdhe4096:
name = WC_FFDHE_4096;
break;
#endif /* HAVE_FFDHE_4096 */
@@ -7118,7 +7410,7 @@ WOLFSSL_BIGNUM* wolfSSL_DH_8192_prime(WOLFSSL_BIGNUM* bn)
#ifndef NO_CERTS
-/* Load the DER encoded DH parameters/key into DH key.
+/* Load the DER encoded DH parameters into DH key.
*
* @param [in, out] dh DH key to load parameters into.
* @param [in] der Buffer holding DER encoded parameters data.
@@ -7129,7 +7421,7 @@ WOLFSSL_BIGNUM* wolfSSL_DH_8192_prime(WOLFSSL_BIGNUM* bn)
* @return 0 on success.
* @return 1 when decoding DER or setting the external key fails.
*/
-static int wolfssl_dh_load_key(WOLFSSL_DH* dh, const unsigned char* der,
+static int wolfssl_dh_load_params(WOLFSSL_DH* dh, const unsigned char* der,
word32* idx, word32 derSz)
{
int err = 0;
@@ -7242,7 +7534,7 @@ WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH** dh, const unsigned char** pp,
WOLFSSL_ERROR_MSG("wolfSSL_DH_new() failed");
err = 1;
}
- if ((!err) && (wolfssl_dh_load_key(newDh, *pp, &idx,
+ if ((!err) && (wolfssl_dh_load_params(newDh, *pp, &idx,
(word32)length) != 0)) {
WOLFSSL_ERROR_MSG("Loading DH parameters failed");
err = 1;
@@ -7305,7 +7597,7 @@ int wolfSSL_i2d_DHparams(const WOLFSSL_DH *dh, unsigned char **out)
*out += len;
}
/* An error occurred unless only length returned. */
- else if (ret != LENGTH_ONLY_E) {
+ else if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
err = 1;
}
}
@@ -7399,13 +7691,13 @@ int wolfSSL_DH_LoadDer(WOLFSSL_DH* dh, const unsigned char* derBuf, int derSz)
if ((dh == NULL) || (dh->internal == NULL) || (derBuf == NULL) ||
(derSz <= 0)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
- if ((ret == 1) && (wolfssl_dh_load_key(dh, derBuf, &idx,
+ if ((ret == 1) && (wolfssl_dh_load_params(dh, derBuf, &idx,
(word32)derSz) != 0)) {
WOLFSSL_ERROR_MSG("DH key decode failed");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
return ret;
@@ -7455,7 +7747,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) {
@@ -7593,10 +7885,10 @@ WOLFSSL_DH* wolfSSL_PEM_read_DHparams(XFILE fp, WOLFSSL_DH** dh,
static int wolfssl_dhparams_to_der(WOLFSSL_DH* dh, unsigned char** out,
void* heap)
{
- int ret = -1;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
int err = 0;
byte* der = NULL;
- word32 derSz;
+ word32 derSz = 0;
DhKey* key = NULL;
(void)heap;
@@ -7610,7 +7902,7 @@ static int wolfssl_dhparams_to_der(WOLFSSL_DH* dh, unsigned char** out,
/* Use wolfSSL API to get length of DER encode DH parameters. */
key = (DhKey*)dh->internal;
ret = wc_DhParamsToDer(key, NULL, &derSz);
- if (ret != LENGTH_ONLY_E) {
+ if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
WOLFSSL_ERROR_MSG("Failed to get size of DH params");
err = 1;
}
@@ -7637,9 +7929,7 @@ static int wolfssl_dhparams_to_der(WOLFSSL_DH* dh, unsigned char** out,
*out = der;
der = NULL;
}
- if (der != NULL) {
- XFREE(der, heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
+ XFREE(der, heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
@@ -7655,7 +7945,7 @@ static int wolfssl_dhparams_to_der(WOLFSSL_DH* dh, unsigned char** out,
int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh)
{
int ret = 1;
- int derSz;
+ int derSz = 0;
byte* derBuf = NULL;
void* heap = NULL;
@@ -7681,7 +7971,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;
}
@@ -7724,7 +8014,7 @@ int SetDhExternal_ex(WOLFSSL_DH *dh, int elm)
/* Validate parameters. */
if ((dh == NULL) || (dh->internal == NULL)) {
WOLFSSL_ERROR_MSG("dh key NULL error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
@@ -7736,21 +8026,21 @@ int SetDhExternal_ex(WOLFSSL_DH *dh, int elm)
/* Set the prime. */
if (wolfssl_bn_set_value(&dh->p, &key->p) != 1) {
WOLFSSL_ERROR_MSG("dh param p error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if ((ret == 1) && (elm & ELEMENT_G)) {
/* Set the generator. */
if (wolfssl_bn_set_value(&dh->g, &key->g) != 1) {
WOLFSSL_ERROR_MSG("dh param g error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if ((ret == 1) && (elm & ELEMENT_Q)) {
/* Set the order. */
if (wolfssl_bn_set_value(&dh->q, &key->q) != 1) {
WOLFSSL_ERROR_MSG("dh param q error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
#ifdef WOLFSSL_DH_EXTRA
@@ -7758,14 +8048,14 @@ int SetDhExternal_ex(WOLFSSL_DH *dh, int elm)
/* Set the private key. */
if (wolfssl_bn_set_value(&dh->priv_key, &key->priv) != 1) {
WOLFSSL_ERROR_MSG("No DH Private Key");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if ((ret == 1) && (elm & ELEMENT_PUB)) {
/* Set the public key. */
if (wolfssl_bn_set_value(&dh->pub_key, &key->pub) != 1) {
WOLFSSL_ERROR_MSG("No DH Public Key");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
#endif /* WOLFSSL_DH_EXTRA */
@@ -7810,7 +8100,7 @@ int SetDhInternal(WOLFSSL_DH* dh)
/* Validate parameters. */
if ((dh == NULL) || (dh->p == NULL) || (dh->g == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
/* Get the wolfSSL DH key. */
@@ -7819,26 +8109,26 @@ int SetDhInternal(WOLFSSL_DH* dh)
/* Clear out key and initialize. */
wc_FreeDhKey(key);
if (wc_InitDhKey(key) != 0) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
/* Transfer prime. */
if (wolfssl_bn_get_value(dh->p, &key->p) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
/* Transfer generator. */
if (wolfssl_bn_get_value(dh->g, &key->g) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
#ifdef HAVE_FFDHE_Q
/* Transfer order if available. */
if ((ret == 1) && (dh->q != NULL)) {
if (wolfssl_bn_get_value(dh->q, &key->q) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
#endif
@@ -7847,14 +8137,14 @@ int SetDhInternal(WOLFSSL_DH* dh)
if ((ret == 1) && (dh->priv_key != NULL) &&
(!wolfSSL_BN_is_zero(dh->priv_key))) {
if (wolfssl_bn_get_value(dh->priv_key, &key->priv) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
/* Transfer public key if available. */
if ((ret == 1) && (dh->pub_key != NULL) &&
(!wolfSSL_BN_is_zero(dh->pub_key))) {
if (wolfssl_bn_get_value(dh->pub_key, &key->pub) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
#endif /* WOLFSSL_DH_EXTRA */
@@ -7877,17 +8167,14 @@ int SetDhInternal(WOLFSSL_DH* dh)
*/
int wolfSSL_DH_size(WOLFSSL_DH* dh)
{
- int ret = -1;
-
WOLFSSL_ENTER("wolfSSL_DH_size");
- /* Validate parameter. */
- if (dh != NULL) {
- /* Size of key is size of prime in bytes. */
- ret = wolfSSL_BN_num_bytes(dh->p);
- }
+ if (dh == NULL)
+ return WOLFSSL_FATAL_ERROR;
- return ret;
+ /* Validate parameter. */
+ /* Size of key is size of prime in bytes. */
+ return wolfSSL_BN_num_bytes(dh->p);
}
/**
@@ -8126,11 +8413,7 @@ int wolfSSL_DH_set0_key(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *pub_key,
static int wolfssl_dh_check_prime(WOLFSSL_BIGNUM* n, int* isPrime)
{
int ret = 1;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG tmpRng[1];
-#endif
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
WC_RNG* rng;
int localRng;
@@ -8148,9 +8431,7 @@ static int wolfssl_dh_check_prime(WOLFSSL_BIGNUM* n, int* isPrime)
/* Free local random number generator if created. */
if (localRng) {
wc_FreeRng(rng);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
}
@@ -8278,11 +8559,7 @@ int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len,
{
int ret = 1;
DhKey* key = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG tmpRng[1];
-#endif
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
WC_RNG* rng = NULL;
int localRng = 0;
@@ -8328,9 +8605,7 @@ int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len,
/* Free local random number generator if created. */
if (localRng) {
wc_FreeRng(rng);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
if (ret == 1) {
@@ -8371,11 +8646,7 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
word32 privSz = 0;
int localRng = 0;
WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG tmpRng[1];
-#endif
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
unsigned char* pub = NULL;
unsigned char* priv = NULL;
@@ -8414,6 +8685,10 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
/* Private key size can be as much as the size of the prime. */
if (dh->length) {
privSz = (word32)(dh->length / 8); /* to bytes */
+ /* Special case where priv key is larger than dh->length / 8
+ * See GeneratePrivateDh */
+ if (dh->length == 128)
+ privSz = 21;
}
else {
privSz = pubSz;
@@ -8468,9 +8743,7 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
if (localRng) {
/* Free an initialized local random number generator. */
wc_FreeRng(rng);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
- #endif
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
}
/* Dispose of allocated data. */
XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
@@ -8480,20 +8753,8 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
}
-/* Compute the shared key from the private key and peer's public key.
- *
- * Return code compliant with OpenSSL.
- * OpenSSL returns 0 when number of bits in p are smaller than minimum
- * supported.
- *
- * @param [out] key Buffer to place shared key.
- * @param [in] otherPub Peer's public key.
- * @param [in] dh DH key containing private key.
- * @return -1 on error.
- * @return Size of shared secret in bytes on success.
- */
-int wolfSSL_DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub,
- WOLFSSL_DH* dh)
+static int _DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub,
+ WOLFSSL_DH* dh, int ct)
{
int ret = 0;
word32 keySz = 0;
@@ -8513,19 +8774,19 @@ int wolfSSL_DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub,
/* Validate parameters. */
if ((dh == NULL) || (dh->priv_key == NULL) || (otherPub == NULL)) {
WOLFSSL_ERROR_MSG("Bad function arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Get the maximum size of computed DH key. */
- if ((ret == 0) && ((keySz = (word32)DH_size(dh)) == 0)) {
+ if ((ret == 0) && ((keySz = (word32)wolfSSL_DH_size(dh)) == 0)) {
WOLFSSL_ERROR_MSG("Bad DH_size");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
/* Validate the size of the private key. */
sz = wolfSSL_BN_num_bytes(dh->priv_key);
- if (sz > (int)privSz) {
+ if (sz > privSz) {
WOLFSSL_ERROR_MSG("Bad priv internal size");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
@@ -8538,7 +8799,7 @@ int wolfSSL_DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub,
sz = wolfSSL_BN_num_bytes(otherPub);
if (sz > pubSz) {
WOLFSSL_ERROR_MSG("Bad otherPub size");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
@@ -8548,14 +8809,14 @@ int wolfSSL_DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub,
pub = (unsigned char*)XMALLOC((size_t)sz, NULL,
DYNAMIC_TYPE_PUBLIC_KEY);
if (pub == NULL)
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
/* Allocate memory for the private key array. */
priv = (unsigned char*)XMALLOC((size_t)privSz, NULL,
DYNAMIC_TYPE_PRIVATE_KEY);
if (priv == NULL) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
@@ -8563,51 +8824,120 @@ int wolfSSL_DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub,
/* Get the private key into the array. */
privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv);
if (privSz <= 0) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
/* Get the public key into the array. */
pubSz = wolfSSL_BN_bn2bin(otherPub, pub);
- if (privSz <= 0) {
- ret = -1;
+ if (pubSz <= 0) {
+ ret = WOLFSSL_FATAL_ERROR;
}
}
/* Synchronize the external into the internal parameters. */
if ((ret == 0) && ((dh->inSet == 0) && (SetDhInternal(dh) != 1))) {
WOLFSSL_ERROR_MSG("Bad DH set internal");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
PRIVATE_KEY_UNLOCK();
/* Calculate shared secret from private and public keys. */
- if ((ret == 0) && (wc_DhAgree((DhKey*)dh->internal, key, &keySz, priv,
- (word32)privSz, pub, (word32)pubSz) < 0)) {
- WOLFSSL_ERROR_MSG("wc_DhAgree failed");
- ret = -1;
- }
if (ret == 0) {
- /* Return actual length. */
- ret = (int)keySz;
- }
- PRIVATE_KEY_LOCK();
-
-#ifdef WOLFSSL_SMALL_STACK
- if (priv != NULL)
-#endif
- {
- /* Zeroize sensitive data. */
- ForceZero(priv, (word32)privSz);
- }
+ word32 padded_keySz = keySz;
+#if (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) && !defined(HAVE_SELFTEST)
+ if (ct) {
+ if (wc_DhAgree_ct((DhKey*)dh->internal, key, &keySz, priv,
+ (word32)privSz, pub, (word32)pubSz) < 0) {
+ WOLFSSL_ERROR_MSG("wc_DhAgree_ct failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+ else
+#endif /* (!HAVE_FIPS || FIPS_VERSION_GE(7,0)) && !HAVE_SELFTEST */
+ {
+ if (wc_DhAgree((DhKey*)dh->internal, key, &keySz, priv,
+ (word32)privSz, pub, (word32)pubSz) < 0) {
+ WOLFSSL_ERROR_MSG("wc_DhAgree failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
+
+ if ((ret == 0) && ct) {
+ /* Arrange for correct fixed-length, right-justified key, even if
+ * the crypto back end doesn't support it. With some crypto back
+ * ends this forgoes formal constant-timeness on the key agreement,
+ * but assured that wolfSSL_DH_compute_key_padded() functions
+ * correctly.
+ */
+ if (keySz < padded_keySz) {
+ XMEMMOVE(key, key + (padded_keySz - keySz),
+ padded_keySz - keySz);
+ XMEMSET(key, 0, padded_keySz - keySz);
+ keySz = padded_keySz;
+ }
+ }
+ }
+ if (ret == 0) {
+ /* Return actual length. */
+ ret = (int)keySz;
+ }
+ PRIVATE_KEY_LOCK();
+
+ if (privSz > 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
+ if (priv != NULL)
#endif
+ {
+ /* Zeroize sensitive data. */
+ ForceZero(priv, (word32)privSz);
+ }
+ }
+ WC_FREE_VAR_EX(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ WC_FREE_VAR_EX(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
WOLFSSL_LEAVE("wolfSSL_DH_compute_key", ret);
return ret;
}
+
+/* Compute the shared key from the private key and peer's public key.
+ *
+ * Return code compliant with OpenSSL.
+ * OpenSSL returns 0 when number of bits in p are smaller than minimum
+ * supported.
+ *
+ * @param [out] key Buffer to place shared key.
+ * @param [in] otherPub Peer's public key.
+ * @param [in] dh DH key containing private key.
+ * @return -1 on error.
+ * @return Size of shared secret in bytes on success.
+ */
+int wolfSSL_DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub,
+ WOLFSSL_DH* dh)
+{
+ return _DH_compute_key(key, otherPub, dh, 0);
+}
+
+/* Compute the shared key from the private key and peer's public key as in
+ * wolfSSL_DH_compute_key, but using constant time processing, with an output
+ * key length fixed at the nominal DH key size. Leading zeros are retained.
+ *
+ * Return code compliant with OpenSSL.
+ * OpenSSL returns 0 when number of bits in p are smaller than minimum
+ * supported.
+ *
+ * @param [out] key Buffer to place shared key.
+ * @param [in] otherPub Peer's public key.
+ * @param [in] dh DH key containing private key.
+ * @return -1 on error.
+ * @return Size of shared secret in bytes on success.
+ */
+int wolfSSL_DH_compute_key_padded(unsigned char* key,
+ const WOLFSSL_BIGNUM* otherPub, WOLFSSL_DH* dh)
+{
+ return _DH_compute_key(key, otherPub, dh, 1);
+}
+
#endif /* !HAVE_FIPS || (HAVE_FIPS && !WOLFSSL_DH_EXTRA) ||
* HAVE_FIPS_VERSION > 2 */
@@ -8712,7 +9042,7 @@ int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth)
if (meth != NULL) {
/* Only field type supported by code base. */
- nid = NID_X9_62_prime_field;
+ nid = WC_NID_X9_62_prime_field;
}
return nid;
@@ -8736,66 +9066,66 @@ int EccEnumToNID(int n)
switch(n) {
case ECC_SECP192R1:
- return NID_X9_62_prime192v1;
+ return WC_NID_X9_62_prime192v1;
case ECC_PRIME192V2:
- return NID_X9_62_prime192v2;
+ return WC_NID_X9_62_prime192v2;
case ECC_PRIME192V3:
- return NID_X9_62_prime192v3;
+ return WC_NID_X9_62_prime192v3;
case ECC_PRIME239V1:
- return NID_X9_62_prime239v1;
+ return WC_NID_X9_62_prime239v1;
case ECC_PRIME239V2:
- return NID_X9_62_prime239v2;
+ return WC_NID_X9_62_prime239v2;
case ECC_PRIME239V3:
- return NID_X9_62_prime239v3;
+ return WC_NID_X9_62_prime239v3;
case ECC_SECP256R1:
- return NID_X9_62_prime256v1;
+ return WC_NID_X9_62_prime256v1;
case ECC_SECP112R1:
- return NID_secp112r1;
+ return WC_NID_secp112r1;
case ECC_SECP112R2:
- return NID_secp112r2;
+ return WC_NID_secp112r2;
case ECC_SECP128R1:
- return NID_secp128r1;
+ return WC_NID_secp128r1;
case ECC_SECP128R2:
- return NID_secp128r2;
+ return WC_NID_secp128r2;
case ECC_SECP160R1:
- return NID_secp160r1;
+ return WC_NID_secp160r1;
case ECC_SECP160R2:
- return NID_secp160r2;
+ return WC_NID_secp160r2;
case ECC_SECP224R1:
- return NID_secp224r1;
+ return WC_NID_secp224r1;
case ECC_SECP384R1:
- return NID_secp384r1;
+ return WC_NID_secp384r1;
case ECC_SECP521R1:
- return NID_secp521r1;
+ return WC_NID_secp521r1;
case ECC_SECP160K1:
- return NID_secp160k1;
+ return WC_NID_secp160k1;
case ECC_SECP192K1:
- return NID_secp192k1;
+ return WC_NID_secp192k1;
case ECC_SECP224K1:
- return NID_secp224k1;
+ return WC_NID_secp224k1;
case ECC_SECP256K1:
- return NID_secp256k1;
+ return WC_NID_secp256k1;
case ECC_BRAINPOOLP160R1:
- return NID_brainpoolP160r1;
+ return WC_NID_brainpoolP160r1;
case ECC_BRAINPOOLP192R1:
- return NID_brainpoolP192r1;
+ return WC_NID_brainpoolP192r1;
case ECC_BRAINPOOLP224R1:
- return NID_brainpoolP224r1;
+ return WC_NID_brainpoolP224r1;
case ECC_BRAINPOOLP256R1:
- return NID_brainpoolP256r1;
+ return WC_NID_brainpoolP256r1;
case ECC_BRAINPOOLP320R1:
- return NID_brainpoolP320r1;
+ return WC_NID_brainpoolP320r1;
case ECC_BRAINPOOLP384R1:
- return NID_brainpoolP384r1;
+ return WC_NID_brainpoolP384r1;
case ECC_BRAINPOOLP512R1:
- return NID_brainpoolP512r1;
+ return WC_NID_brainpoolP512r1;
#ifdef WOLFSSL_SM2
case ECC_SM2P256V1:
- return NID_sm2;
+ return WC_NID_sm2;
#endif
default:
WOLFSSL_MSG("NID not found");
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
@@ -8811,95 +9141,96 @@ int EccEnumToNID(int n)
*/
int NIDToEccEnum(int nid)
{
- /* -1 on error. */
- int id = -1;
+ int id;
WOLFSSL_ENTER("NIDToEccEnum");
switch (nid) {
- case NID_X9_62_prime192v1:
+ case WC_NID_X9_62_prime192v1:
id = ECC_SECP192R1;
break;
- case NID_X9_62_prime192v2:
+ case WC_NID_X9_62_prime192v2:
id = ECC_PRIME192V2;
break;
- case NID_X9_62_prime192v3:
+ case WC_NID_X9_62_prime192v3:
id = ECC_PRIME192V3;
break;
- case NID_X9_62_prime239v1:
+ case WC_NID_X9_62_prime239v1:
id = ECC_PRIME239V1;
break;
- case NID_X9_62_prime239v2:
+ case WC_NID_X9_62_prime239v2:
id = ECC_PRIME239V2;
break;
- case NID_X9_62_prime239v3:
+ case WC_NID_X9_62_prime239v3:
id = ECC_PRIME239V3;
break;
- case NID_X9_62_prime256v1:
+ case WC_NID_X9_62_prime256v1:
id = ECC_SECP256R1;
break;
- case NID_secp112r1:
+ case WC_NID_secp112r1:
id = ECC_SECP112R1;
break;
- case NID_secp112r2:
+ case WC_NID_secp112r2:
id = ECC_SECP112R2;
break;
- case NID_secp128r1:
+ case WC_NID_secp128r1:
id = ECC_SECP128R1;
break;
- case NID_secp128r2:
+ case WC_NID_secp128r2:
id = ECC_SECP128R2;
break;
- case NID_secp160r1:
+ case WC_NID_secp160r1:
id = ECC_SECP160R1;
break;
- case NID_secp160r2:
+ case WC_NID_secp160r2:
id = ECC_SECP160R2;
break;
- case NID_secp224r1:
+ case WC_NID_secp224r1:
id = ECC_SECP224R1;
break;
- case NID_secp384r1:
+ case WC_NID_secp384r1:
id = ECC_SECP384R1;
break;
- case NID_secp521r1:
+ case WC_NID_secp521r1:
id = ECC_SECP521R1;
break;
- case NID_secp160k1:
+ case WC_NID_secp160k1:
id = ECC_SECP160K1;
break;
- case NID_secp192k1:
+ case WC_NID_secp192k1:
id = ECC_SECP192K1;
break;
- case NID_secp224k1:
+ case WC_NID_secp224k1:
id = ECC_SECP224K1;
break;
- case NID_secp256k1:
+ case WC_NID_secp256k1:
id = ECC_SECP256K1;
break;
- case NID_brainpoolP160r1:
+ case WC_NID_brainpoolP160r1:
id = ECC_BRAINPOOLP160R1;
break;
- case NID_brainpoolP192r1:
+ case WC_NID_brainpoolP192r1:
id = ECC_BRAINPOOLP192R1;
break;
- case NID_brainpoolP224r1:
+ case WC_NID_brainpoolP224r1:
id = ECC_BRAINPOOLP224R1;
break;
- case NID_brainpoolP256r1:
+ case WC_NID_brainpoolP256r1:
id = ECC_BRAINPOOLP256R1;
break;
- case NID_brainpoolP320r1:
+ case WC_NID_brainpoolP320r1:
id = ECC_BRAINPOOLP320R1;
break;
- case NID_brainpoolP384r1:
+ case WC_NID_brainpoolP384r1:
id = ECC_BRAINPOOLP384R1;
break;
- case NID_brainpoolP512r1:
+ case WC_NID_brainpoolP512r1:
id = ECC_BRAINPOOLP512R1;
break;
default:
WOLFSSL_MSG("NID not found");
+ /* -1 on error. */
+ id = WOLFSSL_FATAL_ERROR;
}
return id;
@@ -9011,13 +9342,19 @@ void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
* @return NULL on error.
*/
static WOLFSSL_EC_GROUP* wolfssl_ec_group_d2i(WOLFSSL_EC_GROUP** group,
- const unsigned char* in, long inSz)
+ const unsigned char** in_pp, long inSz)
{
int err = 0;
WOLFSSL_EC_GROUP* ret = NULL;
word32 idx = 0;
word32 oid = 0;
int id = 0;
+ const unsigned char* in;
+
+ if (in_pp == NULL || *in_pp == NULL)
+ return NULL;
+
+ in = *in_pp;
/* Use the group passed in. */
if ((group != NULL) && (*group != NULL)) {
@@ -9066,6 +9403,9 @@ static WOLFSSL_EC_GROUP* wolfssl_ec_group_d2i(WOLFSSL_EC_GROUP** group,
}
ret = NULL;
}
+ else {
+ *in_pp += idx;
+ }
return ret;
}
@@ -9097,7 +9437,8 @@ WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio,
}
if (!err) {
/* Create EC group from DER encoding. */
- ret = wolfssl_ec_group_d2i(group, der->buffer, der->length);
+ const byte** p = (const byte**)&der->buffer;
+ ret = wolfssl_ec_group_d2i(group, p, der->length);
if (ret == NULL) {
WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_GROUP");
}
@@ -9108,6 +9449,52 @@ WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio,
return ret;
}
+WOLFSSL_EC_GROUP *wolfSSL_d2i_ECPKParameters(WOLFSSL_EC_GROUP **out,
+ const unsigned char **in, long len)
+{
+ return wolfssl_ec_group_d2i(out, in, len);
+}
+
+int wolfSSL_i2d_ECPKParameters(const WOLFSSL_EC_GROUP* grp, unsigned char** pp)
+{
+ unsigned char* out = NULL;
+ int len = 0;
+ int idx;
+ const byte* oid = NULL;
+ word32 oidSz = 0;
+
+ if (grp == NULL || !wc_ecc_is_valid_idx(grp->curve_idx) ||
+ grp->curve_idx < 0)
+ return WOLFSSL_FATAL_ERROR;
+
+ /* Get the actual DER encoding of the OID. ecc_sets[grp->curve_idx].oid
+ * is just the numerical representation. */
+ if (wc_ecc_get_oid((word32)grp->curve_oid, &oid, &oidSz) < 0)
+ return WOLFSSL_FATAL_ERROR;
+
+ len = SetObjectId((int)oidSz, NULL) + (int)oidSz;
+
+ if (pp == NULL)
+ return len;
+
+ if (*pp == NULL) {
+ out = (unsigned char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1);
+ if (out == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ out = *pp;
+ }
+
+ idx = SetObjectId((int)oidSz, out);
+ XMEMCPY(out + idx, oid, oidSz);
+ if (*pp == NULL)
+ *pp = out;
+ else
+ *pp += len;
+
+ return len;
+}
#endif /* !NO_BIO */
#if defined(OPENSSL_ALL) && !defined(NO_CERTS)
@@ -9176,7 +9563,7 @@ int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
if ((a == NULL) || (b == NULL)) {
WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
/* Return error value. */
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Compare NID and wolfSSL curve index. */
else {
@@ -9249,53 +9636,53 @@ int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
}
else {
switch (group->curve_nid) {
- case NID_secp112r1:
- case NID_secp112r2:
+ case WC_NID_secp112r1:
+ case WC_NID_secp112r2:
degree = 112;
break;
- case NID_secp128r1:
- case NID_secp128r2:
+ case WC_NID_secp128r1:
+ case WC_NID_secp128r2:
degree = 128;
break;
- case NID_secp160k1:
- case NID_secp160r1:
- case NID_secp160r2:
- case NID_brainpoolP160r1:
+ case WC_NID_secp160k1:
+ case WC_NID_secp160r1:
+ case WC_NID_secp160r2:
+ case WC_NID_brainpoolP160r1:
degree = 160;
break;
- case NID_secp192k1:
- case NID_brainpoolP192r1:
- case NID_X9_62_prime192v1:
- case NID_X9_62_prime192v2:
- case NID_X9_62_prime192v3:
+ case WC_NID_secp192k1:
+ case WC_NID_brainpoolP192r1:
+ case WC_NID_X9_62_prime192v1:
+ case WC_NID_X9_62_prime192v2:
+ case WC_NID_X9_62_prime192v3:
degree = 192;
break;
- case NID_secp224k1:
- case NID_secp224r1:
- case NID_brainpoolP224r1:
+ case WC_NID_secp224k1:
+ case WC_NID_secp224r1:
+ case WC_NID_brainpoolP224r1:
degree = 224;
break;
- case NID_X9_62_prime239v1:
- case NID_X9_62_prime239v2:
- case NID_X9_62_prime239v3:
+ case WC_NID_X9_62_prime239v1:
+ case WC_NID_X9_62_prime239v2:
+ case WC_NID_X9_62_prime239v3:
degree = 239;
break;
- case NID_secp256k1:
- case NID_brainpoolP256r1:
- case NID_X9_62_prime256v1:
+ case WC_NID_secp256k1:
+ case WC_NID_brainpoolP256r1:
+ case WC_NID_X9_62_prime256v1:
degree = 256;
break;
- case NID_brainpoolP320r1:
+ case WC_NID_brainpoolP320r1:
degree = 320;
break;
- case NID_secp384r1:
- case NID_brainpoolP384r1:
+ case WC_NID_secp384r1:
+ case WC_NID_brainpoolP384r1:
degree = 384;
break;
- case NID_brainpoolP512r1:
+ case WC_NID_brainpoolP512r1:
degree = 512;
break;
- case NID_secp521r1:
+ case WC_NID_secp521r1:
degree = 521;
break;
}
@@ -9318,16 +9705,12 @@ int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group)
{
int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
- mp_int *order = NULL;
-#else
- mp_int order[1];
-#endif
+ WC_DECLARE_VAR(order, mp_int, 1, 0);
/* Validate parameter. */
if ((group == NULL) || (group->curve_idx < 0)) {
WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
#ifdef WOLFSSL_SMALL_STACK
@@ -9336,7 +9719,7 @@ int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group)
order = (mp_int *)XMALLOC(sizeof(*order), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (order == NULL) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
#endif
@@ -9358,10 +9741,7 @@ int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group)
mp_clear(order);
}
-#ifdef WOLFSSL_SMALL_STACK
- /* Deallocate order. */
- XFREE(order, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(order, NULL, DYNAMIC_TYPE_TMP_BUFFER);
/* Convert error code to length of 0. */
if (ret < 0) {
@@ -9398,6 +9778,12 @@ int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
ret = 0;
}
+ if (ret == 1 &&
+ (group->curve_idx < 0 || !wc_ecc_is_valid_idx(group->curve_idx))) {
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad group idx");
+ ret = 0;
+ }
+
if (ret == 1) {
mp = (mp_int*)order->internal;
}
@@ -9443,7 +9829,7 @@ static int ec_point_internal_set(WOLFSSL_EC_POINT *p)
/* Validate parameter. */
if ((p == NULL) || (p->internal == NULL)) {
WOLFSSL_MSG("ECPoint NULL error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else {
/* Get internal point as a wolfCrypt EC point. */
@@ -9452,19 +9838,19 @@ static int ec_point_internal_set(WOLFSSL_EC_POINT *p)
/* Set X ordinate if available. */
if ((p->X != NULL) && (wolfssl_bn_get_value(p->X, point->x) != 1)) {
WOLFSSL_MSG("ecc point X error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Set Y ordinate if available. */
if ((ret == 1) && (p->Y != NULL) && (wolfssl_bn_get_value(p->Y,
point->y) != 1)) {
WOLFSSL_MSG("ecc point Y error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Set Z ordinate if available. */
if ((ret == 1) && (p->Z != NULL) && (wolfssl_bn_get_value(p->Z,
point->z) != 1)) {
WOLFSSL_MSG("ecc point Z error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Internal values set when operations succeeded. */
p->inSet = (ret == 1);
@@ -9490,7 +9876,7 @@ static int ec_point_external_set(WOLFSSL_EC_POINT *p)
/* Validate parameter. */
if ((p == NULL) || (p->internal == NULL)) {
WOLFSSL_MSG("ECPoint NULL error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else {
/* Get internal point as a wolfCrypt EC point. */
@@ -9499,17 +9885,17 @@ static int ec_point_external_set(WOLFSSL_EC_POINT *p)
/* Set X ordinate. */
if (wolfssl_bn_set_value(&p->X, point->x) != 1) {
WOLFSSL_MSG("ecc point X error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Set Y ordinate. */
if ((ret == 1) && (wolfssl_bn_set_value(&p->Y, point->y) != 1)) {
WOLFSSL_MSG("ecc point Y error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Set Z ordinate. */
if ((ret == 1) && (wolfssl_bn_set_value(&p->Z, point->z) != 1)) {
WOLFSSL_MSG("ecc point Z error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* External values set when operations succeeded. */
p->exSet = (ret == 1);
@@ -9715,7 +10101,6 @@ void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *point)
#endif
}
-#ifndef HAVE_SELFTEST
/* Convert EC point to hex string that as either uncompressed or compressed.
*
* ECC point compression types were not included in selftest ecc.h
@@ -9761,7 +10146,7 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
if (!err) {
/* [] */
len = sz + 1;
- if (form == POINT_CONVERSION_UNCOMPRESSED) {
+ if (form == WC_POINT_CONVERSION_UNCOMPRESSED) {
/* Include y ordinate when uncompressed. */
len += sz;
}
@@ -9787,7 +10172,7 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
}
}
if (!err) {
- if (form == POINT_CONVERSION_COMPRESSED) {
+ if (form == WC_POINT_CONVERSION_COMPRESSED) {
/* Compressed format byte value dependent on whether y-ordinate is
* odd.
*/
@@ -9828,7 +10213,100 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group,
return hex;
}
-#endif /* HAVE_SELFTEST */
+static size_t hex_to_bytes(const char *hex, unsigned char *output, size_t sz)
+{
+ word32 i;
+ for (i = 0; i < sz; i++) {
+ signed char ch1, ch2;
+ ch1 = HexCharToByte(hex[i * 2]);
+ ch2 = HexCharToByte(hex[i * 2 + 1]);
+ if ((ch1 < 0) || (ch2 < 0)) {
+ WOLFSSL_MSG("hex_to_bytes: syntax error");
+ return 0;
+ }
+ output[i] = (unsigned char)((ch1 << 4) + ch2);
+ }
+ return sz;
+}
+
+WOLFSSL_EC_POINT* wolfSSL_EC_POINT_hex2point(const WOLFSSL_EC_GROUP *group,
+ const char *hex, WOLFSSL_EC_POINT*p, WOLFSSL_BN_CTX *ctx)
+{
+ /* for uncompressed mode */
+ size_t str_sz;
+ WOLFSSL_BIGNUM *Gx = NULL;
+ WOLFSSL_BIGNUM *Gy = NULL;
+ char strGx[MAX_ECC_BYTES * 2 + 1];
+
+ /* for compressed mode */
+ int key_sz;
+ byte *octGx = (byte *)strGx; /* octGx[MAX_ECC_BYTES] */
+
+ int p_alloc = 0;
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_hex2point");
+
+ if (group == NULL || hex == NULL || ctx == NULL)
+ return NULL;
+
+ if (p == NULL) {
+ if ((p = wolfSSL_EC_POINT_new(group)) == NULL) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new");
+ goto err;
+ }
+ p_alloc = 1;
+ }
+
+ key_sz = (wolfSSL_EC_GROUP_get_degree(group) + 7) / 8;
+ if (hex[0] == '0' && hex[1] == '4') { /* uncompressed mode */
+ str_sz = (size_t)key_sz * 2;
+
+ XMEMSET(strGx, 0x0, str_sz + 1);
+ XMEMCPY(strGx, hex + 2, str_sz);
+
+ if (wolfSSL_BN_hex2bn(&Gx, strGx) == 0)
+ goto err;
+
+ if (wolfSSL_BN_hex2bn(&Gy, hex + 2 + str_sz) == 0)
+ goto err;
+
+ ret = wolfSSL_EC_POINT_set_affine_coordinates_GFp
+ (group, p, Gx, Gy, ctx);
+
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
+ goto err;
+ }
+ }
+ else if (hex[0] == '0' && (hex[1] == '2' || hex[1] == '3')) {
+ size_t sz = XSTRLEN(hex + 2) / 2;
+ /* compressed mode */
+ octGx[0] = ECC_POINT_COMP_ODD;
+ if (hex_to_bytes(hex + 2, octGx + 1, sz) != sz) {
+ goto err;
+ }
+ if (wolfSSL_ECPoint_d2i(octGx, (word32)key_sz + 1, group, p)
+ != WOLFSSL_SUCCESS) {
+ goto err;
+ }
+ }
+ else
+ goto err;
+
+ wolfSSL_BN_free(Gx);
+ wolfSSL_BN_free(Gy);
+ return p;
+
+err:
+ wolfSSL_BN_free(Gx);
+ wolfSSL_BN_free(Gy);
+ if (p_alloc) {
+ wolfSSL_EC_POINT_free(p);
+ }
+ return NULL;
+
+}
/* Encode the EC point as an uncompressed point in DER.
*
@@ -9871,7 +10349,8 @@ int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
int ret = wc_ecc_export_point_der(group->curve_idx,
(ecc_point*)point->internal, out, len);
/* Check return. When out is NULL, return will be length only error. */
- if ((ret != MP_OKAY) && ((out != NULL) || (ret != LENGTH_ONLY_E))) {
+ if ((ret != MP_OKAY) && ((out != NULL) ||
+ (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)))) {
WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed");
res = 0;
}
@@ -10001,7 +10480,7 @@ size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
int err = 0;
word32 enc_len = (word32)len;
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
- int compressed = ((form == POINT_CONVERSION_COMPRESSED) ? 1 : 0);
+ int compressed = ((form == WC_POINT_CONVERSION_COMPRESSED) ? 1 : 0);
#endif /* !HAVE_SELFTEST */
WOLFSSL_ENTER("wolfSSL_EC_POINT_point2oct");
@@ -10026,7 +10505,7 @@ size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
if (buf != NULL) {
/* Check whether buffer has space. */
if (len < 1) {
- ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+ wolfSSL_ECerr(WOLFSSL_EC_F_EC_GFP_SIMPLE_POINT2OCT, BUFFER_E);
err = 1;
}
else {
@@ -10038,9 +10517,9 @@ size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
/* Not infinity. */
else if (!err) {
/* Validate format. */
- if (form != POINT_CONVERSION_UNCOMPRESSED
+ if (form != WC_POINT_CONVERSION_UNCOMPRESSED
#ifndef HAVE_SELFTEST
- && form != POINT_CONVERSION_COMPRESSED
+ && form != WC_POINT_CONVERSION_COMPRESSED
#endif /* !HAVE_SELFTEST */
) {
WOLFSSL_MSG("Unsupported point form");
@@ -10062,7 +10541,7 @@ size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
/* Check return. When buf is NULL, return will be length only
* error.
*/
- if (ret != ((buf != NULL) ? MP_OKAY : LENGTH_ONLY_E)) {
+ if (ret != ((buf != NULL) ? MP_OKAY : WC_NO_ERR_TRACE(LENGTH_ONLY_E))) {
err = 1;
}
}
@@ -10121,8 +10600,8 @@ int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
* @param [in] group EC group.
* @param [in] point EC point.
* @param [in] form Format of encoding. Valid values:
- * POINT_CONVERSION_UNCOMPRESSED,
- * POINT_CONVERSION_COMPRESSED.
+ * WC_POINT_CONVERSION_UNCOMPRESSED,
+ * WC_POINT_CONVERSION_COMPRESSED.
* @param [in, out] bn BN to hold point value.
* When NULL a new BN is allocated otherwise this is
* returned on success.
@@ -10230,19 +10709,10 @@ int ec_point_convert_to_affine(const WOLFSSL_EC_GROUP *group,
{
int err = 0;
mp_digit mp = 0;
-#ifdef WOLFSSL_SMALL_STACK
- mp_int* modulus;
-#else
- mp_int modulus[1];
-#endif
+ WC_DECLARE_VAR(modulus, mp_int, 1, 0);
-#ifdef WOLFSSL_SMALL_STACK
/* Allocate memory for curve's prime modulus. */
- modulus = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (modulus == NULL) {
- err = 1;
- }
-#endif
+ WC_ALLOC_VAR_EX(modulus, mp_int, 1, NULL, DYNAMIC_TYPE_BIGINT, err=1);
/* Initialize the MP integer. */
if ((!err) && (mp_init(modulus) != MP_OKAY)) {
WOLFSSL_MSG("mp_init failed");
@@ -10279,9 +10749,7 @@ int ec_point_convert_to_affine(const WOLFSSL_EC_GROUP *group,
mp_clear(modulus);
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
+ WC_FREE_VAR_EX(modulus, NULL, DYNAMIC_TYPE_BIGINT);
return err;
}
@@ -10339,10 +10807,10 @@ int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP* group,
}
/* Copy the externally set x and y ordinates. */
- if ((ret == 1) && (BN_copy(x, point->X) == NULL)) {
+ if ((ret == 1) && (wolfSSL_BN_copy(x, point->X) == NULL)) {
ret = 0;
}
- if ((ret == 1) && (BN_copy(y, point->Y) == NULL)) {
+ if ((ret == 1) && (wolfSSL_BN_copy(y, point->Y) == NULL)) {
ret = 0;
}
@@ -10583,11 +11051,9 @@ static int wolfssl_ec_point_add(int curveIdx, ecc_point* r, ecc_point* p1,
mp_clear(mu);
wc_ecc_del_point_h(montP1, NULL);
wc_ecc_del_point_h(montP2, NULL);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
- XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
- XFREE(mu, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
+ WC_FREE_VAR_EX(a, NULL, DYNAMIC_TYPE_BIGINT);
+ WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT);
+ WC_FREE_VAR_EX(mu, NULL, DYNAMIC_TYPE_BIGINT);
return ret;
}
@@ -10843,10 +11309,8 @@ static int wolfssl_ec_point_mul(int curveIdx, ecc_point* r, mp_int* n,
mp_clear(a);
mp_clear(prime);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
- XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
+ WC_FREE_VAR_EX(a, NULL, DYNAMIC_TYPE_BIGINT);
+ WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT);
return ret;
}
@@ -10950,19 +11414,10 @@ int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r,
static int wolfssl_ec_point_invert(int curveIdx, ecc_point* point)
{
int ret = 1;
-#ifdef WOLFSSL_SMALL_STACK
- mp_int* prime = NULL;
-#else
- mp_int prime[1];
-#endif
+ WC_DECLARE_VAR(prime, mp_int, 1, 0);
-#ifdef WOLFSSL_SMALL_STACK
/* Allocate memory for an MP int to hold the prime of the curve. */
- prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
- if (prime == NULL) {
- ret = 0;
- }
-#endif
+ WC_ALLOC_VAR_EX(prime, mp_int, 1, NULL, DYNAMIC_TYPE_BIGINT, ret=0);
/* Initialize MP int. */
if ((ret == 1) && (mp_init(prime) != MP_OKAY)) {
@@ -10986,10 +11441,7 @@ static int wolfssl_ec_point_invert(int curveIdx, ecc_point* point)
/* Dispose of memory associated with MP. */
mp_free(prime);
-#ifdef WOLFSSL_SMALL_STACK
- /* Dispose of dynamically allocated temporaries. */
- XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
-#endif
+ WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT);
return ret;
}
@@ -11096,43 +11548,43 @@ static int ec_point_cmp_jacobian(const WOLFSSL_EC_GROUP* group,
/* Check that the big numbers were allocated. */
if ((at == NULL) || (bt == NULL) || (az == NULL) || (bz == NULL) ||
(mod == NULL)) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Get the modulus for the curve. */
if ((ret == 0) &&
(BN_hex2bn(&mod, ecc_sets[group->curve_idx].prime) != 1)) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 0) {
/* bt = Bx * (Az ^ 2). When Az is one then just copy. */
if (BN_is_one(a->Z)) {
if (BN_copy(bt, b->X) == NULL) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
/* az = Az ^ 2 */
else if ((BN_mod_mul(az, a->Z, a->Z, mod, ctx) != 1)) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* bt = Bx * az = Bx * (Az ^ 2) */
else if (BN_mod_mul(bt, b->X, az, mod, ctx) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
/* at = Ax * (Bz ^ 2). When Bz is one then just copy. */
if (BN_is_one(b->Z)) {
if (BN_copy(at, a->X) == NULL) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
/* bz = Bz ^ 2 */
else if (BN_mod_mul(bz, b->Z, b->Z, mod, ctx) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* at = Ax * bz = Ax * (Bz ^ 2) */
else if (BN_mod_mul(at, a->X, bz, mod, ctx) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
/* Compare x-ordinates. */
@@ -11143,32 +11595,32 @@ static int ec_point_cmp_jacobian(const WOLFSSL_EC_GROUP* group,
/* bt = By * (Az ^ 3). When Az is one then just copy. */
if (BN_is_one(a->Z)) {
if (BN_copy(bt, b->Y) == NULL) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
/* az = az * Az = Az ^ 3 */
else if ((BN_mod_mul(az, az, a->Z, mod, ctx) != 1)) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* bt = By * az = By * (Az ^ 3) */
else if (BN_mod_mul(bt, b->Y, az, mod, ctx) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
/* at = Ay * (Bz ^ 3). When Bz is one then just copy. */
if (BN_is_one(b->Z)) {
if (BN_copy(at, a->Y) == NULL) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
/* bz = bz * Bz = Bz ^ 3 */
else if (BN_mod_mul(bz, bz, b->Z, mod, ctx) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* at = Ay * bz = Ay * (Bz ^ 3) */
else if (BN_mod_mul(at, a->Y, bz, mod, ctx) != 1) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
/* Compare y-ordinates. */
@@ -11208,7 +11660,7 @@ int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group,
if ((group == NULL) || (a == NULL) || (a->internal == NULL) ||
(b == NULL) || (b->internal == NULL)) {
WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret != -1) {
#ifdef WOLFSSL_EC_POINT_CMP_JACOBIAN
@@ -11359,7 +11811,7 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId)
/* Cache heap hint. */
key->heap = heap;
/* Initialize fields to defaults. */
- key->form = POINT_CONVERSION_UNCOMPRESSED;
+ key->form = WC_POINT_CONVERSION_UNCOMPRESSED;
/* Initialize reference count. */
wolfSSL_RefInit(&key->ref, &err);
@@ -11385,7 +11837,7 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId)
if (!err) {
/* Group unknown at creation */
- key->group = wolfSSL_EC_GROUP_new_by_curve_name(NID_undef);
+ key->group = wolfSSL_EC_GROUP_new_by_curve_name(WC_NID_undef);
if (key->group == NULL) {
WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure");
err = 1;
@@ -11549,7 +12001,8 @@ static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src)
if (ret == 0) {
/* Copy private key. */
- ret = mp_copy(wc_ecc_key_get_priv(src), wc_ecc_key_get_priv(dst));
+ ret = mp_copy(wc_ecc_key_get_priv((ecc_key*)src),
+ wc_ecc_key_get_priv(dst));
if (ret != MP_OKAY) {
WOLFSSL_MSG("mp_copy error");
}
@@ -11721,7 +12174,7 @@ int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *key, unsigned char **out)
{
int ret = 1;
size_t len = 0;
- int form = POINT_CONVERSION_UNCOMPRESSED;
+ int form = WC_POINT_CONVERSION_UNCOMPRESSED;
WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey");
@@ -11741,9 +12194,9 @@ int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *key, unsigned char **out)
if (ret == 1) {
#ifdef HAVE_COMP_KEY
/* Default to compressed form if not set */
- form = (key->form != POINT_CONVERSION_UNCOMPRESSED) ?
- POINT_CONVERSION_UNCOMPRESSED :
- POINT_CONVERSION_COMPRESSED;
+ form = (key->form == WC_POINT_CONVERSION_UNCOMPRESSED) ?
+ WC_POINT_CONVERSION_UNCOMPRESSED :
+ WC_POINT_CONVERSION_COMPRESSED;
#endif
/* Calculate length of point encoding. */
@@ -11868,7 +12321,7 @@ WOLFSSL_EC_KEY* wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY** key,
*
* @param [in] key EC key to encode.
* @param [in, out] out On in, reference to buffer to place DER encoding into.
- * On out, reference to buffer adter the encoding.
+ * On out, reference to buffer after the encoding.
* May be NULL.
* @return Length of DER encoding on success.
* @return 0 on error.
@@ -11984,11 +12437,11 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
if ((key == NULL) || (key->internal == NULL) || (derBuf == NULL) ||
(derSz <= 0)) {
WOLFSSL_MSG("Bad function arguments");
- res = -1;
+ res = WOLFSSL_FATAL_ERROR;
}
if ((res == 1) && (opt != WOLFSSL_EC_KEY_LOAD_PRIVATE) &&
(opt != WOLFSSL_EC_KEY_LOAD_PUBLIC)) {
- res = -1;
+ res = WOLFSSL_FATAL_ERROR;
}
if (res == 1) {
@@ -12005,9 +12458,9 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
res = 1;
}
/* Error out on parsing error. */
- else if (ret != ASN_PARSE_E) {
+ else if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header");
- res = -1;
+ res = WOLFSSL_FATAL_ERROR;
}
}
@@ -12024,7 +12477,7 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
ecc_key *tmp = (ecc_key*)XMALLOC(sizeof(ecc_key),
((ecc_key*)key->internal)->heap, DYNAMIC_TYPE_ECC);
if (tmp == NULL) {
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else {
/* We now try again as x.963 [point type][x][opt y]. */
@@ -12056,7 +12509,7 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
else {
WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
}
- res = -1;
+ res = WOLFSSL_FATAL_ERROR;
}
/* Internal key updated - update whether it is a valid key. */
@@ -12066,22 +12519,69 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
/* Set the external EC key based on value in internal. */
if ((res == 1) && (SetECKeyExternal(key) != 1)) {
WOLFSSL_MSG("SetECKeyExternal failed");
- res = -1;
+ res = WOLFSSL_FATAL_ERROR;
}
return res;
}
+
+#ifndef NO_BIO
+
+WOLFSSL_EC_KEY *wolfSSL_d2i_EC_PUBKEY_bio(WOLFSSL_BIO *bio,
+ WOLFSSL_EC_KEY **out)
+{
+ char* data = NULL;
+ int dataSz = 0;
+ int memAlloced = 0;
+ WOLFSSL_EC_KEY* ec = NULL;
+ int err = 0;
+
+ WOLFSSL_ENTER("wolfSSL_d2i_EC_PUBKEY_bio");
+
+ if (bio == NULL)
+ return NULL;
+
+ if (err == 0 && wolfssl_read_bio(bio, &data, &dataSz, &memAlloced) != 0) {
+ WOLFSSL_ERROR_MSG("wolfssl_read_bio failed");
+ err = 1;
+ }
+
+ if (err == 0 && (ec = wolfSSL_EC_KEY_new()) == NULL) {
+ WOLFSSL_ERROR_MSG("wolfSSL_EC_KEY_new failed");
+ err = 1;
+ }
+
+ /* Load the EC key with the public key from the DER encoding. */
+ if (err == 0 && wolfSSL_EC_KEY_LoadDer_ex(ec, (const unsigned char*)data,
+ dataSz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1) {
+ WOLFSSL_ERROR_MSG("wolfSSL_EC_KEY_LoadDer_ex failed");
+ err = 1;
+ }
+
+ if (memAlloced)
+ XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (err) { /* on error */
+ wolfSSL_EC_KEY_free(ec);
+ ec = NULL;
+ }
+ else { /* on success */
+ if (out != NULL)
+ *out = ec;
+ }
+
+ return ec;
+}
+
+#endif /* !NO_BIO */
+
/*
* 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 +12676,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 +12803,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 +12832,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;
@@ -12359,7 +12860,7 @@ int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec)
* @return 0 on error.
*/
int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
- const EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
+ const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
wc_pem_password_cb* cb, void* arg)
{
int ret = 1;
@@ -12407,7 +12908,7 @@ int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
* @return 0 on error.
*/
int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ec,
- const EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
+ const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
unsigned char **pem, int *pLen)
{
#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
@@ -12439,7 +12940,7 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ec,
/* Calculate maximum size of DER encoding.
* 4 > size of pub, priv + ASN.1 additional information */
der_max_len = 4 * (word32)wc_ecc_size((ecc_key*)ec->internal) +
- AES_BLOCK_SIZE;
+ WC_AES_BLOCK_SIZE;
/* Allocate buffer big enough to hold encoding. */
derBuf = (byte*)XMALLOC((size_t)der_max_len, NULL,
@@ -12496,7 +12997,7 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ec,
* @return 0 on error.
*/
int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ec,
- const EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
+ const WOLFSSL_EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
wc_pem_password_cb *cb, void *pass)
{
int ret = 1;
@@ -12534,7 +13035,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
@@ -12599,7 +13100,7 @@ int wolfSSL_EC_KEY_print_fp(XFILE fp, WOLFSSL_EC_KEY* key, int indent)
if ((ret == 1) && (key->pub_key != NULL) && (key->pub_key->exSet)) {
/* Get the public key point as one BN. */
WOLFSSL_BIGNUM* pubBn = wolfSSL_EC_POINT_point2bn(key->group,
- key->pub_key, POINT_CONVERSION_UNCOMPRESSED, NULL, NULL);
+ key->pub_key, WC_POINT_CONVERSION_UNCOMPRESSED, NULL, NULL);
if (pubBn == NULL) {
WOLFSSL_MSG("wolfSSL_EC_POINT_point2bn failed.");
ret = 0;
@@ -12662,7 +13163,7 @@ int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
/* Validate parameter. */
if ((eckey == NULL) || (eckey->internal == NULL)) {
WOLFSSL_MSG("ec key NULL error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else {
ecc_key* key = (ecc_key*)eckey->internal;
@@ -12677,13 +13178,13 @@ int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
if (wc_ecc_copy_point(&key->pubkey,
(ecc_point*)eckey->pub_key->internal) != MP_OKAY) {
WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Set external public key from internal wolfCrypt, public key. */
if ((ret == 1) && (ec_point_external_set(eckey->pub_key) != 1)) {
WOLFSSL_MSG("SetECKeyExternal ec_point_external_set failed");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
@@ -12692,7 +13193,7 @@ int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
(wolfssl_bn_set_value(&eckey->priv_key,
wc_ecc_key_get_priv(key)) != 1)) {
WOLFSSL_MSG("ec priv key error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* External values set when operations succeeded. */
@@ -12720,7 +13221,7 @@ int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
if ((eckey == NULL) || (eckey->internal == NULL) ||
(eckey->group == NULL)) {
WOLFSSL_MSG("ec key NULL error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else {
ecc_key* key = (ecc_key*)eckey->internal;
@@ -12730,7 +13231,7 @@ int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
if ((eckey->group->curve_idx < 0) ||
(wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) {
WOLFSSL_MSG("invalid curve idx");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
@@ -12743,14 +13244,14 @@ int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
if ((ret == 1) && pubSet) {
if (ec_point_internal_set(eckey->pub_key) != 1) {
WOLFSSL_MSG("ec key pub error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Copy public point to key. */
if ((ret == 1) && (wc_ecc_copy_point(
(ecc_point*)eckey->pub_key->internal, &key->pubkey) !=
MP_OKAY)) {
WOLFSSL_MSG("wc_ecc_copy_point error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
@@ -12764,7 +13265,7 @@ int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
if (wolfssl_bn_get_value(eckey->priv_key,
wc_ecc_key_get_priv(key)) != 1) {
WOLFSSL_MSG("ec key priv error");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* private key */
if ((ret == 1) && (!mp_iszero(wc_ecc_key_get_priv(key)))) {
@@ -12790,32 +13291,29 @@ int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
* @return Point conversion format on success.
* @return -1 on error.
*/
-point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(const WOLFSSL_EC_KEY* key)
+wc_point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(
+ const WOLFSSL_EC_KEY* key)
{
- int ret = -1;
-
- if (key != NULL) {
- ret = key->form;
- }
-
- return ret;
+ if (key == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ return key->form;
}
/* Set point conversion format into EC key.
*
* @param [in, out] key EC key to set format into.
* @param [in] form Point conversion format. Valid values:
- * POINT_CONVERSION_UNCOMPRESSED,
- * POINT_CONVERSION_COMPRESSED (when HAVE_COMP_KEY)
+ * WC_POINT_CONVERSION_UNCOMPRESSED,
+ * WC_POINT_CONVERSION_COMPRESSED (when HAVE_COMP_KEY)
*/
void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *key, int form)
{
if (key == NULL) {
WOLFSSL_MSG("Key passed in NULL");
}
- else if (form == POINT_CONVERSION_UNCOMPRESSED
+ else if (form == WC_POINT_CONVERSION_UNCOMPRESSED
#ifdef HAVE_COMP_KEY
- || form == POINT_CONVERSION_COMPRESSED
+ || form == WC_POINT_CONVERSION_COMPRESSED
#endif
) {
key->form = (unsigned char)form;
@@ -13089,11 +13587,7 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
int res = 1;
int initTmpRng = 0;
WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG tmpRng[1];
-#endif
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
@@ -13106,13 +13600,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 +13618,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);
@@ -13138,9 +13655,7 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
/* Dispose of local random number generator if initialized. */
if (initTmpRng) {
wc_FreeRng(rng);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
- #endif
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
}
/* Set the external key from new internal key values. */
@@ -13383,6 +13898,7 @@ WOLFSSL_ECDSA_SIG* wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG** sig,
int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
{
word32 len = 0;
+ int update_p = 1;
/* Validate parameter. */
if (sig != NULL) {
@@ -13402,6 +13918,17 @@ int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
/* Add in the length of the SEQUENCE. */
len += (word32)1 + ASN_LEN_SIZE(len);
+ #ifdef WOLFSSL_I2D_ECDSA_SIG_ALLOC
+ if ((pp != NULL) && (*pp == NULL)) {
+ *pp = (unsigned char *)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (*pp != NULL) {
+ WOLFSSL_MSG("malloc error");
+ return 0;
+ }
+ update_p = 0;
+ }
+ #endif
+
/* Encode only if there is a buffer to encode into. */
if ((pp != NULL) && (*pp != NULL)) {
/* Encode using the internal representations of r and s. */
@@ -13410,7 +13937,7 @@ int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
/* No bytes encoded. */
len = 0;
}
- else {
+ else if (update_p) {
/* Update pointer to after encoding. */
*pp += len;
}
@@ -13489,7 +14016,7 @@ int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key)
{
int err = 0;
int len = 0;
- const EC_GROUP *group = NULL;
+ const WOLFSSL_EC_GROUP *group = NULL;
int bits = 0;
/* Validate parameter. */
@@ -13531,11 +14058,7 @@ WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *dgst, int dLen,
{
int err = 0;
WOLFSSL_ECDSA_SIG *sig = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- byte* out = NULL;
-#else
- byte out[ECC_BUFSIZE];
-#endif
+ WC_DECLARE_VAR(out, byte, ECC_BUFSIZE, 0);
unsigned int outLen = ECC_BUFSIZE;
WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
@@ -13577,10 +14100,7 @@ WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *dgst, int dLen,
sig = wolfSSL_d2i_ECDSA_SIG(NULL, &p, outLen);
}
-#ifdef WOLFSSL_SMALL_STACK
- /* Dispose of any temporary dynamically allocated data. */
- XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return sig;
}
@@ -13614,7 +14134,7 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen,
if ((dgst == NULL) || (sig == NULL) || (key == NULL) ||
(key->internal == NULL)) {
WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* Ensure internal EC key is set from external. */
@@ -13623,7 +14143,7 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen,
if (SetECKeyInternal(key) != 1) {
WOLFSSL_MSG("SetECKeyInternal failed");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
@@ -13634,7 +14154,7 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen,
(mp_int*)sig->s->internal, dgst, (word32)dLen, &verified,
(ecc_key *)key->internal) != MP_OKAY) {
WOLFSSL_MSG("wc_ecc_verify_hash failed");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else if (verified == 0) {
WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
@@ -13648,7 +14168,7 @@ int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen,
(word32)dLen, &verified, (ecc_key*)key->internal);
if (ret != MP_OKAY) {
WOLFSSL_MSG("wc_ecc_verify_hash failed");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else if (verified == 0) {
WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
@@ -13678,11 +14198,7 @@ int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, int digestSz,
{
int ret = 1;
WC_RNG* rng = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- WC_RNG* tmpRng = NULL;
-#else
- WC_RNG tmpRng[1];
-#endif
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
int initTmpRng = 0;
WOLFSSL_ENTER("wolfSSL_ECDSA_sign");
@@ -13712,9 +14228,7 @@ int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, int digestSz,
if (initTmpRng) {
wc_FreeRng(rng);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
- #endif
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
}
return ret;
@@ -13861,12 +14375,2349 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outLen,
/* End ECDH */
-#endif /* OPENSSL_EXTRA */
+#ifndef NO_WOLFSSL_STUB
+const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_OpenSSL(void)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_OpenSSL");
-#endif /* HAVE_ECC */
+ return NULL;
+}
-/*******************************************************************************
- * END OF EC API
+WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_METHOD_new(
+ const WOLFSSL_EC_KEY_METHOD *meth)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_new");
+
+ (void)meth;
+
+ return NULL;
+}
+
+void wolfSSL_EC_KEY_METHOD_free(WOLFSSL_EC_KEY_METHOD *meth)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_free");
+
+ (void)meth;
+}
+
+void wolfSSL_EC_KEY_METHOD_set_init(WOLFSSL_EC_KEY_METHOD *meth,
+ void* a1, void* a2, void* a3, void* a4, void* a5, void* a6)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_init");
+
+ (void)meth;
+ (void)a1;
+ (void)a2;
+ (void)a3;
+ (void)a4;
+ (void)a5;
+ (void)a6;
+}
+
+void wolfSSL_EC_KEY_METHOD_set_sign(WOLFSSL_EC_KEY_METHOD *meth,
+ void* a1, void* a2, void* a3)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_sign");
+
+ (void)meth;
+ (void)a1;
+ (void)a2;
+ (void)a3;
+}
+
+const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_get_method(
+ const WOLFSSL_EC_KEY *key)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_get_method");
+
+ (void)key;
+
+ return NULL;
+}
+
+int wolfSSL_EC_KEY_set_method(WOLFSSL_EC_KEY *key,
+ const WOLFSSL_EC_KEY_METHOD *meth)
+{
+ WOLFSSL_STUB("wolfSSL_EC_KEY_set_method");
+
+ (void)key;
+ (void)meth;
+
+ return 0;
+}
+
+#endif /* !NO_WOLFSSL_STUB */
+
+#endif /* OPENSSL_EXTRA */
+
+#endif /* HAVE_ECC */
+
+/*******************************************************************************
+ * END OF EC API
+ ******************************************************************************/
+
+/*******************************************************************************
+ * START OF EC25519 API
+ ******************************************************************************/
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519)
+
+/* Generate an EC25519 key pair.
+ *
+ * Output keys are in little endian format.
+ *
+ * @param [out] priv EC25519 private key data.
+ * @param [in, out] privSz On in, the size of priv in bytes.
+ * On out, the length of the private key data in bytes.
+ * @param [out] pub EC25519 public key data.
+ * @param [in, out] pubSz On in, the size of pub in bytes.
+ * On out, the length of the public key data in bytes.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
+ unsigned char *pub, unsigned int *pubSz)
+{
+#ifdef WOLFSSL_KEY_GEN
+ int res = 1;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
+ 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);
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
+ }
+
+ 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) {
+ #ifdef WOLFSSL_CURVE25519_BLINDING
+ /* An RNG is needed. */
+ if (wc_curve25519_set_rng(&privkey, wolfssl_make_global_rng()) != 0) {
+ res = 0;
+ }
+ else
+ #endif
+ /* 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;
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
+ 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);
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
+ }
+
+ return res;
+#else
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+#else
+ WOLFSSL_MSG("No ED25519 key export built in");
+#endif
+
+ (void)priv;
+ (void)privSz;
+ (void)pub;
+ (void)pubSz;
+
+ return 0;
+#endif /* WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_EXPORT */
+}
+
+/* Sign a message with Ed25519 using the private key.
+ *
+ * Input and output keys are in little endian format.
+ * Priv is a buffer containing private and public part of key.
+ *
+ * @param [in] msg Message to be signed.
+ * @param [in] msgSz Length of message in bytes.
+ * @param [in] priv ED25519 private key data.
+ * @param [in] privSz Length in bytes of private key data.
+ * @param [out] sig Signature buffer.
+ * @param [in, out] sigSz On in, the length of the signature buffer in bytes.
+ * On out, the length of the signature in bytes.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
+ const unsigned char *priv, unsigned int privSz, unsigned char *sig,
+ unsigned int *sigSz)
+{
+#if defined(HAVE_ED25519_SIGN) && defined(WOLFSSL_KEY_GEN) && \
+ defined(HAVE_ED25519_KEY_IMPORT)
+ ed25519_key key;
+ int res = 1;
+
+ WOLFSSL_ENTER("wolfSSL_ED25519_sign");
+
+ /* Validate parameters. */
+ if ((priv == NULL) || (privSz != ED25519_PRV_KEY_SIZE) ||
+ (msg == NULL) || (sig == NULL) || (sigSz == NULL) ||
+ (*sigSz < ED25519_SIG_SIZE)) {
+ WOLFSSL_MSG("Bad arguments");
+ res = 0;
+ }
+
+ /* Initialize Ed25519 key. */
+ if (res && (wc_ed25519_init(&key) != 0)) {
+ WOLFSSL_MSG("wc_curve25519_init failed");
+ res = 0;
+ }
+ if (res) {
+ /* Import private and public key. */
+ int ret = wc_ed25519_import_private_key(priv, privSz / 2,
+ priv + (privSz / 2), ED25519_PUB_KEY_SIZE, &key);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_ed25519_import_private failed");
+ res = 0;
+ }
+
+ if (res) {
+ /* Sign message with Ed25519. */
+ ret = wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
+ res = 0;
+ }
+ }
+
+ wc_ed25519_free(&key);
+ }
+
+ return res;
+#else
+#if !defined(HAVE_ED25519_SIGN)
+ WOLFSSL_MSG("No ED25519 sign built in");
+#elif !defined(WOLFSSL_KEY_GEN)
+ WOLFSSL_MSG("No Key Gen built in");
+#elif !defined(HAVE_ED25519_KEY_IMPORT)
+ WOLFSSL_MSG("No ED25519 Key import built in");
+#endif
+
+ (void)msg;
+ (void)msgSz;
+ (void)priv;
+ (void)privSz;
+ (void)sig;
+ (void)sigSz;
+
+ return 0;
+#endif /* HAVE_ED25519_SIGN && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */
+}
+
+/* Verify a message with Ed25519 using the public key.
+ *
+ * Input keys are in little endian format.
+ *
+ * @param [in] msg Message to be verified.
+ * @param [in] msgSz Length of message in bytes.
+ * @param [in] pub ED25519 public key data.
+ * @param [in] privSz Length in bytes of public key data.
+ * @param [in] sig Signature buffer.
+ * @param [in] sigSz Length of the signature in bytes.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
+ const unsigned char *pub, unsigned int pubSz, const unsigned char *sig,
+ unsigned int sigSz)
+{
+#if defined(HAVE_ED25519_VERIFY) && defined(WOLFSSL_KEY_GEN) && \
+ defined(HAVE_ED25519_KEY_IMPORT)
+ ed25519_key key;
+ int res = 1;
+
+ WOLFSSL_ENTER("wolfSSL_ED25519_verify");
+
+ /* Validate parameters. */
+ if ((pub == NULL) || (pubSz != ED25519_PUB_KEY_SIZE) || (msg == NULL) ||
+ (sig == NULL) || (sigSz != ED25519_SIG_SIZE)) {
+ WOLFSSL_MSG("Bad arguments");
+ res = 0;
+ }
+
+ /* Initialize Ed25519 key. */
+ if (res && (wc_ed25519_init(&key) != 0)) {
+ WOLFSSL_MSG("wc_curve25519_init failed");
+ res = 0;
+ }
+ if (res) {
+ /* Import public key. */
+ int ret = wc_ed25519_import_public(pub, pubSz, &key);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_ed25519_import_public failed");
+ res = 0;
+ }
+
+ if (res) {
+ int check = 0;
+
+ /* Verify signature with message and public key. */
+ ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz, &check,
+ &key);
+ /* Check for errors in verification process. */
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_ed25519_verify_msg failed");
+ res = 0;
+ }
+ /* Check signature is valid. */
+ else if (!check) {
+ WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)");
+ res = 0;
+ }
+ }
+
+ wc_ed25519_free(&key);
+ }
+
+ return res;
+#else
+#if !defined(HAVE_ED25519_VERIFY)
+ WOLFSSL_MSG("No ED25519 verify built in");
+#elif !defined(WOLFSSL_KEY_GEN)
+ WOLFSSL_MSG("No Key Gen built in");
+#elif !defined(HAVE_ED25519_KEY_IMPORT)
+ WOLFSSL_MSG("No ED25519 Key import built in");
+#endif
+
+ (void)msg;
+ (void)msgSz;
+ (void)pub;
+ (void)pubSz;
+ (void)sig;
+ (void)sigSz;
+
+ return 0;
+#endif /* HAVE_ED25519_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */
+}
+
+#endif /* OPENSSL_EXTRA && HAVE_ED25519 */
+
+/*******************************************************************************
+ * END OF ED25519 API
+ ******************************************************************************/
+
+/*******************************************************************************
+ * START OF EC448 API
+ ******************************************************************************/
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE448)
+/* Generate an EC448 key pair.
+ *
+ * Output keys are in little endian format.
+ *
+ * @param [out] priv EC448 private key data.
+ * @param [in, out] privSz On in, the size of priv in bytes.
+ * On out, the length of the private key data in bytes.
+ * @param [out] pub EC448 public key data.
+ * @param [in, out] pubSz On in, the size of pub in bytes.
+ * On out, the length of the public key data in bytes.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_EC448_generate_key(unsigned char *priv, unsigned int *privSz,
+ unsigned char *pub, unsigned int *pubSz)
+{
+#ifdef WOLFSSL_KEY_GEN
+ int res = 1;
+ int initTmpRng = 0;
+ WC_RNG *rng = NULL;
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
+ 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);
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
+ }
+
+ 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;
+ WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
+ 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);
+ WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
+ }
+
+ return res;
+#else
+#ifndef WOLFSSL_KEY_GEN
+ WOLFSSL_MSG("No Key Gen built in");
+#else
+ WOLFSSL_MSG("No ED448 key export built in");
+#endif
+
+ (void)priv;
+ (void)privSz;
+ (void)pub;
+ (void)pubSz;
+
+ return 0;
+#endif /* WOLFSSL_KEY_GEN && HAVE_ED448_KEY_EXPORT */
+}
+
+/* Sign a message with Ed448 using the private key.
+ *
+ * Input and output keys are in little endian format.
+ * Priv is a buffer containing private and public part of key.
+ *
+ * @param [in] msg Message to be signed.
+ * @param [in] msgSz Length of message in bytes.
+ * @param [in] priv ED448 private key data.
+ * @param [in] privSz Length in bytes of private key data.
+ * @param [out] sig Signature buffer.
+ * @param [in, out] sigSz On in, the length of the signature buffer in bytes.
+ * On out, the length of the signature in bytes.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_ED448_sign(const unsigned char *msg, unsigned int msgSz,
+ const unsigned char *priv, unsigned int privSz, unsigned char *sig,
+ unsigned int *sigSz)
+{
+#if defined(HAVE_ED448_SIGN) && defined(WOLFSSL_KEY_GEN) && \
+ defined(HAVE_ED448_KEY_IMPORT)
+ ed448_key key;
+ int res = 1;
+
+ WOLFSSL_ENTER("wolfSSL_ED448_sign");
+
+ /* Validate parameters. */
+ if ((priv == NULL) || (privSz != ED448_PRV_KEY_SIZE) ||
+ (msg == NULL) || (sig == NULL) || (sigSz == NULL) ||
+ (*sigSz < ED448_SIG_SIZE)) {
+ WOLFSSL_MSG("Bad arguments");
+ res = 0;
+ }
+
+ /* Initialize Ed448 key. */
+ if (res && (wc_ed448_init(&key) != 0)) {
+ WOLFSSL_MSG("wc_curve448_init failed");
+ res = 0;
+ }
+ if (res) {
+ /* Import private and public key. */
+ int ret = wc_ed448_import_private_key(priv, privSz / 2,
+ priv + (privSz / 2), ED448_PUB_KEY_SIZE, &key);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_ed448_import_private failed");
+ res = 0;
+ }
+
+ if (res) {
+ /* Sign message with Ed448 - no context. */
+ ret = wc_ed448_sign_msg(msg, msgSz, sig, sigSz, &key, NULL, 0);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_curve448_shared_secret_ex failed");
+ res = 0;
+ }
+ }
+
+ wc_ed448_free(&key);
+ }
+
+ return res;
+#else
+#if !defined(HAVE_ED448_SIGN)
+ WOLFSSL_MSG("No ED448 sign built in");
+#elif !defined(WOLFSSL_KEY_GEN)
+ WOLFSSL_MSG("No Key Gen built in");
+#elif !defined(HAVE_ED448_KEY_IMPORT)
+ WOLFSSL_MSG("No ED448 Key import built in");
+#endif
+
+ (void)msg;
+ (void)msgSz;
+ (void)priv;
+ (void)privSz;
+ (void)sig;
+ (void)sigSz;
+
+ return 0;
+#endif /* HAVE_ED448_SIGN && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */
+}
+
+/* Verify a message with Ed448 using the public key.
+ *
+ * Input keys are in little endian format.
+ *
+ * @param [in] msg Message to be verified.
+ * @param [in] msgSz Length of message in bytes.
+ * @param [in] pub ED448 public key data.
+ * @param [in] privSz Length in bytes of public key data.
+ * @param [in] sig Signature buffer.
+ * @param [in] sigSz Length of the signature in bytes.
+ * @return 1 on success
+ * @return 0 on failure.
+ */
+int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz,
+ const unsigned char *pub, unsigned int pubSz, const unsigned char *sig,
+ unsigned int sigSz)
+{
+#if defined(HAVE_ED448_VERIFY) && defined(WOLFSSL_KEY_GEN) && \
+ defined(HAVE_ED448_KEY_IMPORT)
+ ed448_key key;
+ int res = 1;
+
+ WOLFSSL_ENTER("wolfSSL_ED448_verify");
+
+ /* Validate parameters. */
+ if ((pub == NULL) || (pubSz != ED448_PUB_KEY_SIZE) || (msg == NULL) ||
+ (sig == NULL) || (sigSz != ED448_SIG_SIZE)) {
+ WOLFSSL_MSG("Bad arguments");
+ res = 0;
+ }
+
+ /* Initialize Ed448 key. */
+ if (res && (wc_ed448_init(&key) != 0)) {
+ WOLFSSL_MSG("wc_curve448_init failed");
+ res = 0;
+ }
+ if (res) {
+ /* Import public key. */
+ int ret = wc_ed448_import_public(pub, pubSz, &key);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_ed448_import_public failed");
+ res = 0;
+ }
+
+ if (res) {
+ int check = 0;
+
+ /* Verify signature with message and public key - no context. */
+ ret = wc_ed448_verify_msg((byte*)sig, sigSz, msg, msgSz, &check,
+ &key, NULL, 0);
+ /* Check for errors in verification process. */
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_ed448_verify_msg failed");
+ res = 0;
+ }
+ /* Check signature is valid. */
+ else if (!check) {
+ WOLFSSL_MSG("wc_ed448_verify_msg failed (signature invalid)");
+ res = 0;
+ }
+ }
+
+ wc_ed448_free(&key);
+ }
+
+ return res;
+#else
+#if !defined(HAVE_ED448_VERIFY)
+ WOLFSSL_MSG("No ED448 verify built in");
+#elif !defined(WOLFSSL_KEY_GEN)
+ WOLFSSL_MSG("No Key Gen built in");
+#elif !defined(HAVE_ED448_KEY_IMPORT)
+ WOLFSSL_MSG("No ED448 Key import built in");
+#endif
+
+ (void)msg;
+ (void)msgSz;
+ (void)pub;
+ (void)pubSz;
+ (void)sig;
+ (void)sigSz;
+
+ return 0;
+#endif /* HAVE_ED448_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */
+}
+#endif /* OPENSSL_EXTRA && HAVE_ED448 */
+
+/*******************************************************************************
+ * END OF ED448 API
+ ******************************************************************************/
+
+/*******************************************************************************
+ * START OF GENERIC PUBLIC KEY PEM APIs
+ ******************************************************************************/
+
+#ifdef OPENSSL_EXTRA
+/* Sets default callback password for PEM.
+ *
+ * @param [out] buf Buffer to hold password.
+ * @param [in] num Number of characters in buffer.
+ * @param [in] rwFlag Read/write flag. Ignored.
+ * @param [in] userData User data - assumed to be default password.
+ * @return Password size on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_def_callback(char* buf, int num, int rwFlag, void* userData)
+{
+ int sz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_def_callback");
+
+ (void)rwFlag;
+
+ /* We assume that the user passes a default password as userdata */
+ if ((buf != NULL) && (userData != NULL)) {
+ sz = (int)XSTRLEN((const char*)userData);
+ sz = (int)min((word32)sz, (word32)num);
+ XMEMCPY(buf, userData, (size_t)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 WC_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 WC_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 WC_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 WC_EVP_PKEY_DH:
+ /* DH public key not supported. */
+ WOLFSSL_MSG("Writing DH PUBKEY not supported!");
+ break;
+#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
+ default:
+ /* Key type not supported. */
+ WOLFSSL_MSG("Unknown Key type!");
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/* Writes a private key to a WOLFSSL_BIO encoded in PEM format.
+ *
+ * @param [in] bio BIO to write to.
+ * @param [in] key Public key to write in PEM format.
+ * @param [in] cipher Encryption cipher to use.
+ * @param [in] passwd Password to use when encrypting.
+ * @param [in] len Length of password.
+ * @param [in] cb Password callback.
+ * @param [in] arg Password callback argument.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
+ const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int len,
+ wc_pem_password_cb* cb, void* arg)
+{
+ int ret = 1;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey");
+
+ (void)cipher;
+ (void)passwd;
+ (void)len;
+ (void)cb;
+ (void)arg;
+
+ /* Validate parameters. */
+ if ((bio == NULL) || (key == NULL)) {
+ WOLFSSL_MSG("Bad Function Arguments");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ #ifdef WOLFSSL_KEY_GEN
+ switch (key->type) {
+ #ifndef NO_RSA
+ case WC_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 WC_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 WC_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 WC_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 WC_EVP_PKEY_DSA:
+ type = DSA_PRIVATEKEY_TYPE;
+ break;
+ #endif
+ #ifdef HAVE_ECC
+ case WC_EVP_PKEY_EC:
+ type = ECC_PRIVATEKEY_TYPE;
+ break;
+ #endif
+ #ifndef NO_DH
+ case WC_EVP_PKEY_DH:
+ type = DH_PRIVATEKEY_TYPE;
+ break;
+ #endif
+ #ifndef NO_RSA
+ case WC_EVP_PKEY_RSA:
+ type = PRIVATEKEY_TYPE;
+ break;
+ #endif
+ default:
+ ret = 0;
+ break;
+ }
+ if (ret == 1) {
+ /* Write using generic API with generic type. */
+ ret = der_write_to_bio_as_pem((byte*)key->pkey.ptr, key->pkey_sz,
+ bio, type);
+ }
+ #endif
+ }
+
+ return ret;
+}
+#endif /* !NO_BIO */
+
+#ifndef NO_BIO
+/* Create a private key object from the data in the BIO.
+ *
+ * @param [in] bio BIO to read from.
+ * @param [in, out] key Public key object. Object used if passed in.
+ * @param [in] cb Password callback.
+ * @param [in] arg Password callback argument.
+ * @return A WOLFSSL_EVP_PKEY object on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY **key, wc_pem_password_cb *cb, void *arg)
+{
+ int err = 0;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ DerBuffer* der = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PUBKEY");
+
+ if (bio == NULL) {
+ err = 1;
+ }
+
+ /* Read the PEM public key from the BIO and convert to DER. */
+ if ((!err) && (pem_read_bio_key(bio, cb, arg, PUBLICKEY_TYPE, NULL,
+ &der) < 0)) {
+ err = 1;
+ }
+
+ if (!err) {
+ const unsigned char* ptr = der->buffer;
+
+ /* Use key passed in if set. */
+ if ((key != NULL) && (*key != NULL)) {
+ pkey = *key;
+ }
+
+ /* Convert DER data to a public key object. */
+ if (wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length) == NULL) {
+ WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
+ pkey = NULL;
+ err = 1;
+ }
+ }
+
+ /* Return the key if possible. */
+ if ((!err) && (key != NULL) && (pkey != NULL)) {
+ *key = pkey;
+ }
+ /* Dispose of the DER encoding. */
+ FreeDer(&der);
+
+ WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PUBKEY", 0);
+
+ return pkey;
+}
+
+/* Create a private key object from the data in the BIO.
+ *
+ * @param [in] bio BIO to read from.
+ * @param [in, out] key Private key object. Object used if passed in.
+ * @param [in] cb Password callback.
+ * @param [in] arg Password callback argument.
+ * @return A WOLFSSL_EVP_PKEY object on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY** key, wc_pem_password_cb* cb, void* arg)
+{
+ int err = 0;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey");
+
+ /* Validate parameters. */
+ if (bio == NULL) {
+ err = 1;
+ }
+
+ /* Read the PEM private key from the BIO and convert to DER. */
+ if ((!err) && (pem_read_bio_key(bio, cb, arg, PRIVATEKEY_TYPE, &keyFormat,
+ &der) < 0)) {
+ err = 1;
+ }
+
+ if (!err) {
+ const unsigned char* ptr = der->buffer;
+ int type;
+
+ /* Set key type based on format returned. */
+ switch (keyFormat) {
+ /* No key format set - default to RSA. */
+ case 0:
+ case RSAk:
+ type = WC_EVP_PKEY_RSA;
+ break;
+ case DSAk:
+ type = WC_EVP_PKEY_DSA;
+ break;
+ case ECDSAk:
+ type = WC_EVP_PKEY_EC;
+ break;
+ case DHk:
+ type = WC_EVP_PKEY_DH;
+ break;
+ default:
+ type = WOLFSSL_FATAL_ERROR;
+ 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;
+}
+
+
+WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_PEM_read_bio_PKCS8_PRIV_KEY_INFO(
+ WOLFSSL_BIO* bio, WOLFSSL_PKCS8_PRIV_KEY_INFO** key, wc_pem_password_cb* cb,
+ void* arg)
+{
+ return wolfSSL_PEM_read_bio_PrivateKey(bio, key, cb, arg);
+}
+#endif /* !NO_BIO */
+
+#if !defined(NO_FILESYSTEM)
+/* Create a private key object from the data in a file.
+ *
+ * @param [in] fp File pointer.
+ * @param [in, out] key Public key object. Object used if passed in.
+ * @param [in] cb Password callback.
+ * @param [in] arg Password callback argument.
+ * @return A WOLFSSL_EVP_PKEY object on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, WOLFSSL_EVP_PKEY **key,
+ wc_pem_password_cb *cb, void *arg)
+{
+ int err = 0;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ DerBuffer* der = NULL;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_PUBKEY");
+
+ /* Validate parameters. */
+ if (fp == XBADFILE) {
+ err = 1;
+ }
+
+ /* Read the PEM public key from the file and convert to DER. */
+ if ((!err) && ((pem_read_file_key(fp, cb, arg, PUBLICKEY_TYPE, NULL,
+ &der) < 0) || (der == NULL))) {
+ err = 1;
+ }
+ if (!err) {
+ const unsigned char* ptr = der->buffer;
+
+ /* Use key passed in if set. */
+ if ((key != NULL) && (*key != NULL)) {
+ pkey = *key;
+ }
+
+ /* Convert DER data to a public key object. */
+ if (wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length) == NULL) {
+ WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
+ pkey = NULL;
+ err = 1;
+ }
+ }
+
+ /* Return the key if possible. */
+ if ((!err) && (key != NULL) && (pkey != NULL)) {
+ *key = pkey;
+ }
+ /* Dispose of the DER encoding. */
+ FreeDer(&der);
+
+ WOLFSSL_LEAVE("wolfSSL_PEM_read_PUBKEY", 0);
+
+ return pkey;
+}
+
+#ifndef NO_CERTS
+/* Create a private key object from the data in a file.
+ *
+ * @param [in] fp File pointer.
+ * @param [in, out] key Private key object. Object used if passed in.
+ * @param [in] cb Password callback.
+ * @param [in] arg Password callback argument.
+ * @return A WOLFSSL_EVP_PKEY object on success.
+ * @return NULL on failure.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY **key,
+ wc_pem_password_cb *cb, void *arg)
+{
+ int err = 0;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ DerBuffer* der = NULL;
+ int keyFormat = 0;
+
+ WOLFSSL_ENTER("wolfSSL_PEM_read_PrivateKey");
+
+ /* Validate parameters. */
+ if (fp == XBADFILE) {
+ err = 1;
+ }
+
+ /* Read the PEM private key from the file and convert to DER. */
+ if ((!err) && (pem_read_file_key(fp, cb, arg, PRIVATEKEY_TYPE, &keyFormat,
+ &der)) < 0) {
+ err = 1;
+ }
+
+ if (!err) {
+ const unsigned char* ptr = der->buffer;
+ int type;
+
+ /* Set key type based on format returned. */
+ switch (keyFormat) {
+ /* No key format set - default to RSA. */
+ case 0:
+ case RSAk:
+ type = WC_EVP_PKEY_RSA;
+ break;
+ case DSAk:
+ type = WC_EVP_PKEY_DSA;
+ break;
+ case ECDSAk:
+ type = WC_EVP_PKEY_EC;
+ break;
+ case DHk:
+ type = WC_EVP_PKEY_DH;
+ break;
+ default:
+ type = WOLFSSL_FATAL_ERROR;
+ 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, (size_t)prefixLen) == 0)) {
+ idx += prefixLen;
+ *start = idx;
+ break;
+ }
+ }
+ /* Find postfix part. */
+ for (; idx < pemLen - postfixLen; idx++) {
+ if ((pem[idx] == postfix[0]) &&
+ (XMEMCMP(pem + idx, postfix, (size_t)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((size_t)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, (size_t)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((size_t)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, (size_t)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, (size_t)nameLen) != 0)) {
+ ret = ASN_NO_PEM_HEADER;
+ }
+ }
+ if (ret == 0) {
+ unsigned char* der = (unsigned char*)pem;
+ word32 derLen;
+
+ /* Convert PEM body to DER. */
+ derLen = (word32)(startEnd - PEM_END_SZ - start);
+ ret = Base64_Decode(der + start, derLen, der, &derLen);
+ if (ret == 0) {
+ /* Return the DER data. */
+ *data = der;
+ *len = derLen;
+ }
+ }
+
+ return ret;
+}
+
+/* Encode the DER data in PEM format into a newly allocated buffer.
+ *
+ * @param [in] name Header/footer name.
+ * @param [in] header Encryption header.
+ * @param [in] data DER data.
+ * @param [in] len Length of DER data.
+ * @param [out] pemOut PEM encoded data.
+ * @param [out] pemOutLen Length of PEM encoded data.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+static int pem_write_data(const char *name, const char *header,
+ const unsigned char *data, long len, char** pemOut, word32* pemOutLen)
+{
+ int ret = 0;
+ int nameLen;
+ int headerLen;
+ char* pem = NULL;
+ word32 pemLen;
+ word32 derLen = (word32)len;
+ byte* p;
+
+ nameLen = (int)XSTRLEN(name);
+ headerLen = (int)XSTRLEN(header);
+
+ /* DER encode for PEM. */
+ pemLen = (derLen + 2) / 3 * 4;
+ pemLen += (pemLen + 63) / 64;
+ /* Header */
+ pemLen += (word32)(PEM_BEGIN_SZ + nameLen + PEM_HDR_FIN_EOL_SZ);
+ if (headerLen > 0) {
+ /* Encryption lines plus extra carriage return. */
+ pemLen += (word32)headerLen + 1;
+ }
+ /* Trailer */
+ pemLen += (word32)(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, (size_t)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, (size_t)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, (size_t)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);
+ }
+ else {
+ /* Dispose of any allocated memory. */
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ pem = NULL;
+ }
+
+ 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((size_t)pemLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (p == NULL) {
+ res = 0;
+ }
+ else {
+ /* Copy the data into new buffer. */
+ XMEMCPY(p, pem, (size_t)pemLen);
+ pem = p;
+ }
+ }
+
+ /* Read the PEM data. */
+ if ((res == 1) && (pem_read_data(pem, pemLen, name, header, data, len) !=
+ 0)) {
+ /* Dispose of any allocated memory. */
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(*name, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(*header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ *name = NULL;
+ *header = NULL;
+ res = 0;
+ }
+
+ return res;
+}
+
+/* Encode the DER data in PEM format into a BIO.
+ *
+ * @param [in] bio BIO to write to.
+ * @param [in] name Header/footer name.
+ * @param [in] header Encryption header.
+ * @param [in] data DER data.
+ * @param [in] len Length of DER data.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_bio(WOLFSSL_BIO* bio, const char *name,
+ const char *header, const unsigned char *data, long len)
+{
+ int err = 0;
+ char* pem = NULL;
+ word32 pemLen = 0;
+
+ /* Validate parameters. */
+ if ((bio == NULL) || (name == NULL) || (header == NULL) || (data == NULL)) {
+ err = BAD_FUNC_ARG;
+ }
+
+ /* Encode into a buffer. */
+ if (!err) {
+ err = pem_write_data(name, header, data, len, &pem, &pemLen);
+ }
+
+ /* Write PEM into BIO. */
+ if ((!err) && (wolfSSL_BIO_write(bio, pem, (int)pemLen) != (int)pemLen)) {
+ err = IO_FAILED_E;
+ }
+
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return (!err) ? (int)pemLen : 0;
+}
+#endif /* !NO_BIO */
+
+#if !defined(NO_FILESYSTEM)
+/* Read PEM encoded data from a file.
+ *
+ * Reads the entire contents in.
+ *
+ * @param [in] bio BIO to read from.
+ * @param [out] name Name of content type.
+ * @param [out] header Encryption headers.
+ * @param [out] data DER encoding from PEM.
+ * @param [out] len Length of DER data.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_read(XFILE fp, char **name, char **header, unsigned char **data,
+ long *len)
+{
+ int res = 1;
+ char* pem = NULL;
+ int pemLen = 0;
+
+ /* Validate parameters. */
+ if ((fp == XBADFILE) || (name == NULL) || (header == NULL) ||
+ (data == NULL) || (len == NULL)) {
+ res = 0;
+ }
+
+ /* Load all the data from the file. */
+ if ((res == 1) && (wolfssl_read_file(fp, &pem, &pemLen) != 0)) {
+ res = 0;
+ }
+
+ /* Read the PEM data. */
+ if ((res == 1) && (pem_read_data(pem, pemLen, name, header, data, len) !=
+ 0)) {
+ /* Dispose of any allocated memory. */
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(*name, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(*header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ *name = NULL;
+ *header = NULL;
+ res = 0;
+ }
+
+ return res;
+}
+
+/* Encode the DER data in PEM format into a file.
+ *
+ * @param [in] fp File pointer to write to.
+ * @param [in] name Header/footer name.
+ * @param [in] header Encryption header.
+ * @param [in] data DER data.
+ * @param [in] len Length of DER data.
+ * @return 0 on success.
+ * @return MEMORY_E when dynamic memory allocation fails.
+ */
+int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header,
+ const unsigned char *data, long len)
+{
+ int err = 0;
+ char* pem = NULL;
+ word32 pemLen = 0;
+
+ /* Validate parameters. */
+ if ((fp == XBADFILE) || (name == NULL) || (header == NULL) ||
+ (data == NULL)) {
+ err = 1;
+ }
+
+ /* Encode into a buffer. */
+ if ((!err) && (pem_write_data(name, header, data, len, &pem, &pemLen) !=
+ 0)) {
+ pemLen = 0;
+ err = 1;
+ }
+
+ /* Write PEM to a file. */
+ if ((!err) && (XFWRITE(pem, 1, pemLen, fp) != pemLen)) {
+ pemLen = 0;
+ }
+
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return (int)pemLen;
+}
+#endif
+
+/* Get EVP cipher info from encryption header string.
+ *
+ * @param [in] header Encryption header.
+ * @param [out] cipher EVP Cipher info.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_get_EVP_CIPHER_INFO(const char* header, EncryptedInfo* cipher)
+{
+ int res = 1;
+
+ /* Validate parameters. */
+ if ((header == NULL) || (cipher == NULL)) {
+ res = 0;
+ }
+
+ if (res == 1) {
+ XMEMSET(cipher, 0, sizeof(*cipher));
+
+ if (wc_EncryptedInfoParse(cipher, &header, XSTRLEN(header)) != 0) {
+ res = 0;
+ }
+ }
+
+ return res;
+}
+
+/* Apply cipher to DER data.
+ *
+ * @param [in] cipher EVP cipher info.
+ * @param [in, out] data On in, encrypted DER data.
+ * On out, unencrypted DER data.
+ * @param [in, out] len On in, length of encrypted DER data.
+ * On out, length of unencrypted DER data.
+ * @param [in] cb Password callback.
+ * @param [in] ctx Context for password callback.
+ * @return 1 on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_do_header(EncryptedInfo* cipher, unsigned char* data, long* len,
+ wc_pem_password_cb* cb, void* ctx)
+{
+ int ret = 1;
+ char password[NAME_SZ];
+ int passwordSz = 0;
+
+ /* Validate parameters. */
+ if ((cipher == NULL) || (data == NULL) || (len == NULL) || (cb == NULL)) {
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ /* Get password and length. */
+ passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx);
+ if (passwordSz < 0) {
+ ret = 0;
+ }
+ }
+
+ if (ret == 1) {
+ /* Decrypt the data using password and MD5. */
+ if (wc_BufferKeyDecrypt(cipher, data, (word32)*len, (byte*)password,
+ passwordSz, WC_MD5) != 0) {
+ ret = WOLFSSL_FAILURE;
+ }
+ }
+
+ if (passwordSz > 0) {
+ /* Ensure password is erased from memory. */
+ ForceZero(password, (word32)passwordSz);
+ }
+
+ return ret;
+}
+
+#endif /* !NO_CERTS */
+#endif /* OPENSSL_EXTRA */
+
+#ifdef OPENSSL_ALL
+#if !defined(NO_PWDBASED) && defined(HAVE_PKCS8)
+
+/* 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.
+ */
+int 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->pkcs8HeaderSz,
+ (word32)pkey->pkey_sz - pkey->pkcs8HeaderSz,
+ key, keySz, passwd, passwdSz, PKCS5, PBES2, encAlgId,
+ NULL, 0, WC_PKCS12_ITT_DEFAULT, &rng, NULL);
+ if (ret > 0) {
+ *keySz = (word32)ret;
+ }
+ }
+ /* Dispose of random number generator. */
+ wc_FreeRng(&rng);
+ }
+
+ return ret;
+}
+
+/* Encode private key in PKCS#8 format.
+ *
+ * @param [in] pkey Private key.
+ * @param [out] key Buffer to hold encoding.
+ * @param [in, out] keySz On in, size of buffer in bytes.
+ * @param On out, size of encoded key in bytes.
+ * @return 0 on success.
+ */
+int pkcs8_encode(WOLFSSL_EVP_PKEY* pkey, byte* key, word32* keySz)
+{
+ int ret = 0;
+ int algId = 0;
+ const byte* curveOid = 0;
+ word32 oidSz = 0;
+
+ /* Get the details of the private key. */
+#ifdef HAVE_ECC
+ if (pkey->type == WC_EVP_PKEY_EC) {
+ /* ECC private and get curve OID information. */
+ algId = ECDSAk;
+ ret = wc_ecc_get_oid((word32)pkey->ecc->group->curve_oid, &curveOid,
+ &oidSz);
+ }
+ else
+#endif
+ if (pkey->type == WC_EVP_PKEY_RSA) {
+ /* RSA private has no curve information. */
+ algId = RSAk;
+ curveOid = NULL;
+ oidSz = 0;
+ }
+ else if (pkey->type == WC_EVP_PKEY_DSA) {
+ /* DSA has no curve information. */
+ algId = DSAk;
+ curveOid = NULL;
+ oidSz = 0;
+ }
+#ifndef NO_DH
+ else if (pkey->type == WC_EVP_PKEY_DH) {
+ if (pkey->dh == NULL)
+ return BAD_FUNC_ARG;
+
+ if (pkey->dh->priv_key != NULL || pkey->dh->pub_key != NULL) {
+ /* Special case. DH buffer is always in PKCS8 format */
+ if (keySz == NULL)
+ return BAD_FUNC_ARG;
+
+ *keySz = (word32)pkey->pkey_sz;
+ if (key == NULL)
+ return LENGTH_ONLY_E;
+
+ XMEMCPY(key, pkey->pkey.ptr, pkey->pkey_sz);
+ return pkey->pkey_sz;
+ }
+
+ /* DH has no curve information. */
+ algId = DHk;
+ curveOid = NULL;
+ oidSz = 0;
+ }
+#endif
+ 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->pkcs8HeaderSz, (word32)pkey->pkey_sz - pkey->pkcs8HeaderSz,
+ algId, curveOid, oidSz);
+ }
+
+ return ret;
+}
+
+#if !defined(NO_BIO) || (!defined(NO_FILESYSTEM) && \
+ !defined(NO_STDIO_FILESYSTEM))
+/* Write PEM encoded, PKCS#8 formatted private key to BIO.
+ *
+ * @param [out] pem Buffer holding PEM encoding.
+ * @param [out] pemSz Size of data in buffer in bytes.
+ * @param [in] pkey Private key to write.
+ * @param [in] enc Encryption information to use. May be NULL.
+ * @param [in] passwd Password to use when encrypting. May be NULL.
+ * @param [in] passwdSz Size of password in bytes.
+ * @param [in] cb Password callback. Used when passwd is NULL. May be
+ * NULL.
+ * @param [in] ctx Context for password callback.
+ * @return Length of PEM encoding on success.
+ * @return 0 on failure.
+ */
+static int pem_write_mem_pkcs8privatekey(byte** pem, int* pemSz,
+ WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_CIPHER* enc, char* passwd,
+ int passwdSz, wc_pem_password_cb* cb, void* ctx)
+{
+ int res = 1;
+ int ret = 0;
+ char password[NAME_SZ];
+ byte* key = NULL;
+ word32 keySz = 0;
+ int type = PKCS8_PRIVATEKEY_TYPE;
+
+ /* Validate parameters. */
+ if (pkey == NULL) {
+ res = 0;
+ }
+
+ if (res == 1) {
+ /* Guestimate key size and PEM size. */
+ if (pkcs8_encode(pkey, NULL, &keySz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
+ res = 0;
+ }
+ }
+ if (res == 1) {
+ if (enc != NULL) {
+ /* Add on enough for extra DER data when encrypting. */
+ keySz += 128;
+ }
+ /* PEM encoding size from DER size. */
+ *pemSz = (int)(keySz + 2) / 3 * 4;
+ *pemSz += (*pemSz + 63) / 64;
+ /* Header and footer. */
+ if (enc != NULL) {
+ /* Name is: 'ENCRYPTED PRIVATE KEY'. */
+ *pemSz += 74;
+ }
+ else {
+ /* Name is: 'PRIVATE KEY'. */
+ *pemSz += 54;
+ }
+
+ /* Allocate enough memory to hold PEM encoded encrypted key. */
+ *pem = (byte*)XMALLOC((size_t)*pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (*pem == NULL) {
+ res = 0;
+ }
+ else {
+ /* Use end of PEM buffer for key data. */
+ key = *pem + *pemSz - keySz;
+ }
+ }
+
+ if ((res == 1) && (enc != NULL)) {
+ /* Set type for PEM. */
+ type = PKCS8_ENC_PRIVATEKEY_TYPE;
+
+ if (passwd == NULL) {
+ /* Get the password by using callback. */
+ passwdSz = cb(password, sizeof(password), 1, ctx);
+ if (passwdSz < 0) {
+ res = 0;
+ }
+ passwd = password;
+ }
+
+ if (res == 1) {
+ /* Encrypt the private key. */
+ ret = pkcs8_encrypt(pkey, enc, passwd, passwdSz, key, &keySz);
+ if (ret <= 0) {
+ res = 0;
+ }
+ }
+
+ /* Zeroize the password from memory. */
+ if ((password == passwd) && (passwdSz > 0)) {
+ ForceZero(password, (word32)passwdSz);
+ }
+ }
+ else if ((res == 1) && (enc == NULL)) {
+ /* Set type for PEM. */
+ type = PKCS8_PRIVATEKEY_TYPE;
+
+ /* Encode private key in PKCS#8 format. */
+ ret = pkcs8_encode(pkey, key, &keySz);
+ if (ret < 0) {
+ res = 0;
+ }
+ }
+
+ if (res == 1) {
+ /* Encode PKCS#8 formatted key to PEM. */
+ ret = wc_DerToPemEx(key, keySz, *pem, (word32)*pemSz, NULL, type);
+ if (ret < 0) {
+ res = 0;
+ }
+ else {
+ *pemSz = ret;
+ }
+ }
+
+ /* Return appropriate return code. */
+ return (res == 0) ? 0 : ret;
+
+}
+#endif /* !NO_BIO || (!NO_FILESYSTEM && !NO_STDIO_FILESYSTEM) */
+
+#ifndef NO_BIO
+/* Write PEM encoded, PKCS#8 formatted private key to BIO.
+ *
+ * TODO: OpenSSL returns 1 and 0 only.
+ *
+ * @param [in] bio BIO to write to.
+ * @param [in] pkey Private key to write.
+ * @param [in] enc Encryption information to use. May be NULL.
+ * @param [in] passwd Password to use when encrypting. May be NULL.
+ * @param [in] passwdSz Size of password in bytes.
+ * @param [in] cb Password callback. Used when passwd is NULL. May be
+ * NULL.
+ * @param [in] ctx Context for password callback.
+ * @return Length of PEM encoding on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_CIPHER* enc, char* passwd,
+ int passwdSz, wc_pem_password_cb* cb, void* ctx)
+{
+ byte* pem = NULL;
+ int pemSz = 0;
+ int res = 1;
+
+ /* Validate parameters. */
+ if (bio == NULL) {
+ res = 0;
+ }
+ if (res == 1) {
+ /* Write private key to memory. */
+ res = pem_write_mem_pkcs8privatekey(&pem, &pemSz, pkey, enc, passwd,
+ passwdSz, cb, ctx);
+ }
+
+ /* Write encoded key to BIO. */
+ if ((res >= 1) && (wolfSSL_BIO_write(bio, pem, pemSz) != pemSz)) {
+ res = 0;
+ }
+
+ /* Dispose of dynamically allocated memory (pem and key). */
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return res;
+}
+
+int wolfSSL_PEM_write_bio_PKCS8_PRIV_KEY_INFO(WOLFSSL_BIO* bio,
+ PKCS8_PRIV_KEY_INFO* keyInfo)
+{
+ return wolfSSL_PEM_write_bio_PKCS8PrivateKey(bio, keyInfo, NULL, NULL, 0,
+ NULL, NULL);
+}
+#endif /* !NO_BIO */
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
+/* Write PEM encoded, PKCS#8 formatted private key to BIO.
+ *
+ * TODO: OpenSSL returns 1 and 0 only.
+ *
+ * @param [in] f File pointer.
+ * @param [in] pkey Private key to write.
+ * @param [in] enc Encryption information to use. May be NULL.
+ * @param [in] passwd Password to use when encrypting. May be NULL.
+ * @param [in] passwdSz Size of password in bytes.
+ * @param [in] cb Password callback. Used when passwd is NULL. May be
+ * NULL.
+ * @param [in] ctx Context for password callback.
+ * @return Length of PEM encoding on success.
+ * @return 0 on failure.
+ */
+int wolfSSL_PEM_write_PKCS8PrivateKey(XFILE f, WOLFSSL_EVP_PKEY* pkey,
+ const WOLFSSL_EVP_CIPHER* enc, char* passwd, int passwdSz,
+ wc_pem_password_cb* cb, void* ctx)
+{
+ byte* pem = NULL;
+ int pemSz = 0;
+ int res = 1;
+
+ /* Validate parameters. */
+ if (f == XBADFILE) {
+ res = 0;
+ }
+ if (res == 1) {
+ /* Write private key to memory. */
+ res = pem_write_mem_pkcs8privatekey(&pem, &pemSz, pkey, enc, passwd,
+ passwdSz, cb, ctx);
+ }
+
+ /* Write encoded key to file. */
+ if ((res >= 1) && (XFWRITE(pem, 1, (size_t)pemSz, f) != (size_t)pemSz)) {
+ res = 0;
+ }
+
+ /* Dispose of dynamically allocated memory (pem and key). */
+ XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return res;
+}
+#endif /* !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
+
+#endif /* !NO_PWDBASED && HAVE_PKCS8 */
+#endif /* OPENSSL_ALL */
+
+/*******************************************************************************
+ * END OF GENERIC PUBLIC KEY PEM APIs
******************************************************************************/
#endif /* !WOLFSSL_PK_INCLUDED */
diff --git a/src/src/quic.c b/src/src/quic.c
index 02622a7..21f6490 100644
--- a/src/src/quic.c
+++ b/src/src/quic.c
@@ -1,12 +1,12 @@
/* quic.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,14 +19,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+#include
/* Name change compatibility layer no longer needs to be included here */
-#ifdef HAVE_CONFIG_H
- #include
-#endif
-
-#include
#ifdef NO_INLINE
#include
#else
@@ -82,7 +78,12 @@ static QuicRecord *quic_record_make(WOLFSSL *ssl,
qr->capacity = qr->len = (word32)len;
}
else {
- qr->capacity = qr->len = qr_length(data, len);
+ qr->capacity = qr->len = (word32) qr_length(data, len);
+ if (qr->capacity > WOLFSSL_QUIC_MAX_RECORD_CAPACITY) {
+ WOLFSSL_MSG("QUIC length read larger than expected");
+ quic_record_free(ssl, qr);
+ return NULL;
+ }
}
if (qr->capacity == 0) {
qr->capacity = 2*1024;
@@ -118,17 +119,25 @@ static int quic_record_append(WOLFSSL *ssl, QuicRecord *qr, const uint8_t *data,
missing = 4 - qr->end;
if (len < missing) {
XMEMCPY(qr->data + qr->end, data, len);
- qr->end += len;
+ qr->end += (word32)len;
consumed = len;
goto cleanup; /* len consumed, but qr->len still unknown */
}
XMEMCPY(qr->data + qr->end, data, missing);
- qr->end += missing;
+ qr->end += (word32)missing;
len -= missing;
data += missing;
consumed = missing;
- qr->len = qr_length(qr->data, qr->end);
+ qr->len = (word32)qr_length(qr->data, qr->end);
+
+ /* sanity check on length read from wire before use */
+ if (qr->len > WOLFSSL_QUIC_MAX_RECORD_CAPACITY) {
+ WOLFSSL_MSG("Length read for quic is larger than expected");
+ ret = BUFFER_E;
+ goto cleanup;
+ }
+
if (qr->len > qr->capacity) {
uint8_t *ndata = (uint8_t*)XREALLOC(qr->data, qr->len, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
@@ -141,17 +150,15 @@ static int quic_record_append(WOLFSSL *ssl, QuicRecord *qr, const uint8_t *data,
}
}
- if (quic_record_complete(qr) || len == 0) {
- return 0;
- }
-
- missing = qr->len - qr->end;
- if (len > missing) {
- len = missing;
+ if (!quic_record_complete(qr) && len != 0) {
+ missing = qr->len - qr->end;
+ if (len > missing) {
+ len = missing;
+ }
+ XMEMCPY(qr->data + qr->end, data, len);
+ qr->end += (word32)len;
+ consumed += len;
}
- XMEMCPY(qr->data + qr->end, data, len);
- qr->end += len;
- consumed += len;
cleanup:
*pconsumed = (ret == WOLFSSL_SUCCESS) ? consumed : 0;
@@ -159,7 +166,7 @@ static int quic_record_append(WOLFSSL *ssl, QuicRecord *qr, const uint8_t *data,
}
-static word32 add_rec_header(byte* output, word32 length, int type)
+static word32 add_rec_header(byte* output, word32 length, byte type)
{
RecordLayerHeader* rl;
@@ -175,15 +182,21 @@ static word32 add_rec_header(byte* output, word32 length, int type)
return RECORD_HEADER_SZ;
}
-static word32 quic_record_transfer(QuicRecord* qr, byte* buf, word32 sz)
+static sword32 quic_record_transfer(QuicRecord* qr, byte* buf, word32 sz)
{
word32 len = qr->end - qr->start;
word32 offset = 0;
- word16 rlen;
+ word32 rlen;
if (len <= 0) {
return 0;
}
+
+ /* We check if the buf is at least RECORD_HEADER_SZ */
+ if (sz < RECORD_HEADER_SZ) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+
if (qr->rec_hdr_remain == 0) {
/* start a new TLS record */
rlen = (qr->len <= (word32)MAX_RECORD_SIZE) ?
@@ -205,7 +218,7 @@ static word32 quic_record_transfer(QuicRecord* qr, byte* buf, word32 sz)
qr->start += len;
qr->rec_hdr_remain -= len;
}
- return len + offset;
+ return (sword32)(len + offset);
}
@@ -223,7 +236,7 @@ const QuicTransportParam* QuicTransportParam_new(const uint8_t* data,
return NULL;
}
XMEMCPY((uint8_t*)tp->data, data, len);
- tp->len = len;
+ tp->len = (word16)len;
return tp;
}
@@ -595,11 +608,6 @@ int wolfSSL_quic_do_handshake(WOLFSSL* ssl)
else {
ret = wolfSSL_read_early_data(ssl, tmpbuffer,
sizeof(tmpbuffer), &len);
- if (ret < 0 && ssl->error == ZERO_RETURN) {
- /* this is expected, since QUIC handles the actual early
- * data separately. */
- ret = WOLFSSL_SUCCESS;
- }
}
if (ret < 0) {
goto cleanup;
@@ -615,7 +623,9 @@ int wolfSSL_quic_do_handshake(WOLFSSL* ssl)
cleanup:
if (ret <= 0
&& ssl->options.handShakeState == HANDSHAKE_DONE
- && (ssl->error == ZERO_RETURN || ssl->error == WANT_READ)) {
+ && (ssl->error == WC_NO_ERR_TRACE(ZERO_RETURN) ||
+ ssl->error == WC_NO_ERR_TRACE(WANT_READ)))
+ {
ret = WOLFSSL_SUCCESS;
}
if (ret == WOLFSSL_SUCCESS) {
@@ -753,7 +763,7 @@ int wolfSSL_provide_quic_data(WOLFSSL* ssl, WOLFSSL_ENCRYPTION_LEVEL level,
/* Called internally when SSL wants a certain amount of input. */
int wolfSSL_quic_receive(WOLFSSL* ssl, byte* buf, word32 sz)
{
- word32 n = 0;
+ sword32 n = 0;
int transferred = 0;
WOLFSSL_ENTER("wolfSSL_quic_receive");
@@ -761,6 +771,11 @@ int wolfSSL_quic_receive(WOLFSSL* ssl, byte* buf, word32 sz)
n = 0;
if (ssl->quic.input_head) {
n = quic_record_transfer(ssl->quic.input_head, buf, sz);
+
+ /* record too small to be fit into a RecordLayerHeader struct. */
+ if (n == -1) {
+ return WOLFSSL_FATAL_ERROR;
+ }
if (quic_record_done(ssl->quic.input_head)) {
QuicRecord* qr = ssl->quic.input_head;
ssl->quic.input_head = qr->next;
@@ -778,9 +793,9 @@ int wolfSSL_quic_receive(WOLFSSL* ssl, byte* buf, word32 sz)
ssl->error = transferred = WANT_READ;
goto cleanup;
}
- sz -= n;
+ sz -= (word32)n;
buf += n;
- transferred += n;
+ transferred += (int)n;
}
cleanup:
WOLFSSL_LEAVE("wolfSSL_quic_receive", transferred);
@@ -823,8 +838,8 @@ static int wolfSSL_quic_send_internal(WOLFSSL* ssl)
goto cleanup;
}
output += len;
- length -= len;
- ssl->quic.output_rec_remain -= len;
+ length -= (word32)len;
+ ssl->quic.output_rec_remain -= (word32)len;
}
else {
/* at start of a TLS Record */
@@ -901,8 +916,12 @@ int wolfSSL_quic_forward_secrets(WOLFSSL* ssl, int ktype, int side)
goto cleanup;
}
- ret = !ssl->quic.method->set_encryption_secrets(
- ssl, level, rx_secret, tx_secret, ssl->specs.hash_size);
+ if(!ssl->quic.method->set_encryption_secrets(
+ ssl, level, rx_secret, tx_secret, ssl->specs.hash_size)) {
+ WOLFSSL_MSG("WOLFSSL_QUIC_FORWARD_SECRETS failed");
+ ret = WOLFSSL_FATAL_ERROR;
+ goto cleanup;
+ }
/* Having installed the secrets, any future read/write will happen
* at the level. Except early data, which is detected on the record
@@ -965,23 +984,29 @@ const WOLFSSL_EVP_CIPHER* wolfSSL_quic_get_aead(WOLFSSL* ssl)
switch (cipher->cipherSuite) {
#if !defined(NO_AES) && defined(HAVE_AESGCM)
+ #ifdef WOLFSSL_AES_128
case TLS_AES_128_GCM_SHA256:
evp_cipher = wolfSSL_EVP_aes_128_gcm();
break;
+ #endif
+ #ifdef WOLFSSL_AES_256
case TLS_AES_256_GCM_SHA384:
evp_cipher = wolfSSL_EVP_aes_256_gcm();
break;
+ #endif
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
case TLS_CHACHA20_POLY1305_SHA256:
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
@@ -998,7 +1023,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 */
@@ -1021,27 +1047,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;
@@ -1059,8 +1098,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
@@ -1070,45 +1108,25 @@ size_t wolfSSL_quic_get_aead_tag_len(const WOLFSSL_EVP_CIPHER* aead_cipher)
XMEMSET(ctx, 0, sizeof(*ctx));
if (wolfSSL_EVP_CipherInit(ctx, aead_cipher, NULL, NULL, 0)
== WOLFSSL_SUCCESS) {
- ret = ctx->authTagSz;
+ ret = (size_t)ctx->authTagSz;
} else {
ret = 0;
}
(void)wolfSSL_EVP_CIPHER_CTX_cleanup(ctx);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ WC_FREE_VAR_EX(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
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)
@@ -1170,7 +1188,7 @@ int wolfSSL_quic_hkdf_extract(uint8_t* dest, const WOLFSSL_EVP_MD* md,
WOLFSSL_ENTER("wolfSSL_quic_hkdf_extract");
- pctx = wolfSSL_EVP_PKEY_CTX_new_id(NID_hkdf, NULL);
+ pctx = wolfSSL_EVP_PKEY_CTX_new_id(WC_NID_hkdf, NULL);
if (pctx == NULL) {
ret = WOLFSSL_FAILURE;
goto cleanup;
@@ -1178,7 +1196,7 @@ int wolfSSL_quic_hkdf_extract(uint8_t* dest, const WOLFSSL_EVP_MD* md,
if (wolfSSL_EVP_PKEY_derive_init(pctx) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_PKEY_CTX_hkdf_mode(
- pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) != WOLFSSL_SUCCESS
+ pctx, WOLFSSL_EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_PKEY_CTX_set_hkdf_md(pctx, md) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_PKEY_CTX_set1_hkdf_salt(
pctx, (byte*)salt, (int)saltlen) != WOLFSSL_SUCCESS
@@ -1207,7 +1225,7 @@ int wolfSSL_quic_hkdf_expand(uint8_t* dest, size_t destlen,
WOLFSSL_ENTER("wolfSSL_quic_hkdf_expand");
- pctx = wolfSSL_EVP_PKEY_CTX_new_id(NID_hkdf, NULL);
+ pctx = wolfSSL_EVP_PKEY_CTX_new_id(WC_NID_hkdf, NULL);
if (pctx == NULL) {
ret = WOLFSSL_FAILURE;
goto cleanup;
@@ -1215,7 +1233,7 @@ int wolfSSL_quic_hkdf_expand(uint8_t* dest, size_t destlen,
if (wolfSSL_EVP_PKEY_derive_init(pctx) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_PKEY_CTX_hkdf_mode(
- pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) != WOLFSSL_SUCCESS
+ pctx, WOLFSSL_EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_PKEY_CTX_set_hkdf_md(pctx, md) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_PKEY_CTX_set1_hkdf_salt(
pctx, (byte*)"", 0) != WOLFSSL_SUCCESS
@@ -1230,7 +1248,7 @@ int wolfSSL_quic_hkdf_expand(uint8_t* dest, size_t destlen,
cleanup:
if (pctx)
- EVP_PKEY_CTX_free(pctx);
+ wolfSSL_EVP_PKEY_CTX_free(pctx);
WOLFSSL_LEAVE("wolfSSL_quic_hkdf_expand", ret);
return ret;
}
@@ -1247,7 +1265,7 @@ int wolfSSL_quic_hkdf(uint8_t* dest, size_t destlen,
WOLFSSL_ENTER("wolfSSL_quic_hkdf");
- pctx = wolfSSL_EVP_PKEY_CTX_new_id(NID_hkdf, NULL);
+ pctx = wolfSSL_EVP_PKEY_CTX_new_id(WC_NID_hkdf, NULL);
if (pctx == NULL) {
ret = WOLFSSL_FAILURE;
goto cleanup;
@@ -1255,7 +1273,7 @@ int wolfSSL_quic_hkdf(uint8_t* dest, size_t destlen,
if (wolfSSL_EVP_PKEY_derive_init(pctx) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_PKEY_CTX_hkdf_mode(
- pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) != WOLFSSL_SUCCESS
+ pctx, WOLFSSL_EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_PKEY_CTX_set_hkdf_md(pctx, md) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_PKEY_CTX_set1_hkdf_salt(
pctx, (byte*)salt, (int)saltlen) != WOLFSSL_SUCCESS
@@ -1270,7 +1288,7 @@ int wolfSSL_quic_hkdf(uint8_t* dest, size_t destlen,
cleanup:
if (pctx)
- EVP_PKEY_CTX_free(pctx);
+ wolfSSL_EVP_PKEY_CTX_free(pctx);
WOLFSSL_LEAVE("wolfSSL_quic_hkdf", ret);
return ret;
}
@@ -1323,7 +1341,7 @@ int wolfSSL_quic_aead_encrypt(uint8_t* dest, WOLFSSL_EVP_CIPHER_CTX* ctx,
ctx, dest, &len, plain, (int)plainlen) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_CipherFinal(ctx, dest + len, &len) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_CIPHER_CTX_ctrl(
- ctx, EVP_CTRL_AEAD_GET_TAG, ctx->authTagSz, dest + plainlen)
+ ctx, WOLFSSL_EVP_CTRL_AEAD_GET_TAG, ctx->authTagSz, dest + plainlen)
!= WOLFSSL_SUCCESS) {
return WOLFSSL_FAILURE;
}
@@ -1345,12 +1363,12 @@ int wolfSSL_quic_aead_decrypt(uint8_t* dest, WOLFSSL_EVP_CIPHER_CTX* ctx,
return WOLFSSL_FAILURE;
}
- enclen -= ctx->authTagSz;
+ enclen -= (size_t)ctx->authTagSz;
tag = enc + enclen;
if (wolfSSL_EVP_CipherInit(ctx, NULL, NULL, iv, 0) != WOLFSSL_SUCCESS
|| wolfSSL_EVP_CIPHER_CTX_ctrl(
- ctx, EVP_CTRL_AEAD_SET_TAG, ctx->authTagSz, (uint8_t*)tag)
+ ctx, WOLFSSL_EVP_CTRL_AEAD_SET_TAG, ctx->authTagSz, (uint8_t*)tag)
!= WOLFSSL_SUCCESS
|| wolfSSL_EVP_CipherUpdate(ctx, NULL, &len, aad, (int)aadlen)
!= WOLFSSL_SUCCESS
diff --git a/src/src/sniffer.c b/src/src/sniffer.c
index d5fc5c1..6854d58 100644
--- a/src/src/sniffer.c
+++ b/src/src/sniffer.c
@@ -1,12 +1,12 @@
/* sniffer.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,14 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
-
-#ifdef HAVE_CONFIG_H
- #include
-#endif
-
-#include
-#include
-#include
+#include
#ifdef WOLFSSL_ASYNC_CRYPT
#include
@@ -34,6 +27,7 @@
/* Build Options:
* WOLFSSL_SNIFFER_NO_RECOVERY: Do not track missed data count.
+ * SNIFFER_SINGLE_SESSION_CACHE: Do not cache more than one session.
*/
@@ -227,8 +221,8 @@ BOOL APIENTRY DllMain( HMODULE hModule,
#endif /* _WIN32 */
-static WOLFSSL_GLOBAL int TraceOn = 0; /* Trace is off by default */
-static WOLFSSL_GLOBAL XFILE TraceFile = 0;
+static WC_THREADSHARED int TraceOn = 0; /* Trace is off by default */
+static WC_THREADSHARED XFILE TraceFile = 0;
/* windows uses .rc table for this */
@@ -453,7 +447,6 @@ typedef struct Flags {
byte serverCipherOn; /* indicates whether cipher is active */
byte clientCipherOn; /* indicates whether cipher is active */
byte resuming; /* did this session come from resumption */
- byte cached; /* have we cached this session yet */
byte clientHello; /* processed client hello yet, for SSLv2 */
byte finCount; /* get both FINs before removing */
byte fatalError; /* fatal error state */
@@ -469,6 +462,9 @@ typedef struct Flags {
#ifdef WOLFSSL_ASYNC_CRYPT
byte wasPolled;
#endif
+#ifdef SNIFFER_SINGLE_SESSION_CACHE
+ byte cached; /* have we cached this session yet */
+#endif
} Flags;
@@ -508,11 +504,6 @@ typedef struct KeyShareInfo {
int curve_id;
} KeyShareInfo;
-/* maximum previous acks to capture */
-#ifndef WC_SNIFFER_HS_ACK_HIST_MAX
-#define WC_SNIFFER_HS_ACK_HIST_MAX 10
-#endif
-
/* Sniffer Session holds info for each client/server SSL/TLS session */
typedef struct SnifferSession {
SnifferServer* context; /* server context */
@@ -524,10 +515,10 @@ typedef struct SnifferSession {
word16 cliPort; /* client port */
word32 cliSeqStart; /* client start sequence */
word32 srvSeqStart; /* server start sequence */
+ word32 cliSeqLast; /* client last sequence */
+ word32 srvSeqLast; /* server last sequence */
word32 cliExpected; /* client expected sequence (relative) */
word32 srvExpected; /* server expected sequence (relative) */
- word32 cliAcks[WC_SNIFFER_HS_ACK_HIST_MAX]; /* history of acks during handshake */
- word32 srvAcks[WC_SNIFFER_HS_ACK_HIST_MAX]; /* history of acks during handshake */
FinCapture finCapture; /* retain out of order FIN s */
Flags flags; /* session flags */
time_t lastUsed; /* last used ticks */
@@ -566,52 +557,52 @@ typedef struct SnifferSession {
/* Sniffer Server List and mutex */
-static THREAD_LS_T WOLFSSL_GLOBAL SnifferServer* ServerList = NULL;
+static THREAD_LS_T SnifferServer* ServerList = NULL;
#ifndef HAVE_C___ATOMIC
-static WOLFSSL_GLOBAL wolfSSL_Mutex ServerListMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(ServerListMutex);
+static WC_THREADSHARED wolfSSL_Mutex ServerListMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(ServerListMutex);
#endif
/* Session Hash Table, mutex, and count */
-static THREAD_LS_T WOLFSSL_GLOBAL SnifferSession* SessionTable[HASH_SIZE];
+static THREAD_LS_T SnifferSession* SessionTable[HASH_SIZE];
#ifndef HAVE_C___ATOMIC
-static WOLFSSL_GLOBAL wolfSSL_Mutex SessionMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(SessionMutex);
+static WC_THREADSHARED wolfSSL_Mutex SessionMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(SessionMutex);
#endif
-static THREAD_LS_T WOLFSSL_GLOBAL int SessionCount = 0;
+static THREAD_LS_T int SessionCount = 0;
-static WOLFSSL_GLOBAL int RecoveryEnabled = 0; /* global switch */
-static WOLFSSL_GLOBAL int MaxRecoveryMemory = -1;
+static WC_THREADSHARED int RecoveryEnabled = 0; /* global switch */
+static WC_THREADSHARED int MaxRecoveryMemory = -1;
/* per session max recovery memory */
#ifndef WOLFSSL_SNIFFER_NO_RECOVERY
/* Recovery of missed data switches and stats */
-static WOLFSSL_GLOBAL wolfSSL_Mutex RecoveryMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(RecoveryMutex); /* for stats */
+static WC_THREADSHARED wolfSSL_Mutex RecoveryMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(RecoveryMutex); /* for stats */
/* # of sessions with missed data */
-static WOLFSSL_GLOBAL word32 MissedDataSessions = 0;
+static WC_THREADSHARED word32 MissedDataSessions = 0;
#endif
/* Connection Info Callback */
-static WOLFSSL_GLOBAL SSLConnCb ConnectionCb;
-static WOLFSSL_GLOBAL void* ConnectionCbCtx = NULL;
+static WC_THREADSHARED SSLConnCb ConnectionCb;
+static WC_THREADSHARED void* ConnectionCbCtx = NULL;
#ifdef WOLFSSL_SNIFFER_STATS
/* Sessions Statistics */
-static WOLFSSL_GLOBAL SSLStats SnifferStats;
-static WOLFSSL_GLOBAL wolfSSL_Mutex StatsMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(StatsMutex);
+static WC_THREADSHARED SSLStats SnifferStats;
+static WC_THREADSHARED wolfSSL_Mutex StatsMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(StatsMutex);
#endif
#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
-static WOLFSSL_GLOBAL SSLKeyCb KeyCb;
-static WOLFSSL_GLOBAL void* KeyCbCtx = NULL;
+static WC_THREADSHARED SSLKeyCb KeyCb;
+static WC_THREADSHARED void* KeyCbCtx = NULL;
#endif
#ifdef WOLFSSL_SNIFFER_WATCH
/* Watch Key Callback */
-static WOLFSSL_GLOBAL SSLWatchCb WatchCb;
-static WOLFSSL_GLOBAL void* WatchCbCtx = NULL;
+static WC_THREADSHARED SSLWatchCb WatchCb;
+static WC_THREADSHARED void* WatchCbCtx = NULL;
#endif
#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
/* Store Data Callback */
-static WOLFSSL_GLOBAL SSLStoreDataCb StoreDataCb;
+static WC_THREADSHARED SSLStoreDataCb StoreDataCb;
#endif
@@ -656,7 +647,7 @@ static void UpdateMissedDataSessions(void)
#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
- static WOLFSSL_GLOBAL int CryptoDeviceId = INVALID_DEVID;
+ static WC_THREADSHARED int CryptoDeviceId = INVALID_DEVID;
#endif
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
@@ -851,14 +842,11 @@ static void FreeSnifferSession(SnifferSession* session)
XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
#endif
#ifdef WOLFSSL_TLS13
- if (session->cliKeyShare)
- XFREE(session->cliKeyShare, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(session->cliKeyShare, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef HAVE_MAX_FRAGMENT
- if (session->tlsFragBuf) {
- XFREE(session->tlsFragBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- session->tlsFragBuf = NULL;
- }
+ XFREE(session->tlsFragBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ session->tlsFragBuf = NULL;
#endif
}
XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
@@ -1659,31 +1647,31 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
int ret = -1;
if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (keySz == 0) {
/* load from file */
file = XFOPEN(keyFile, "rb");
- if (file == XBADFILE) return -1;
+ if (file == XBADFILE) return WOLFSSL_FATAL_ERROR;
if(XFSEEK(file, 0, XSEEK_END) != 0) {
XFCLOSE(file);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
fileSz = XFTELL(file);
if (fileSz > MAX_WOLFSSL_FILE_SIZE || fileSz < 0) {
XFCLOSE(file);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if(XFSEEK(file, 0, XSEEK_SET) != 0) {
XFCLOSE(file);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
loadBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_FILE);
if (loadBuf == NULL) {
XFCLOSE(file);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
ret = (int)XFREAD(loadBuf, 1, fileSz, file);
@@ -1691,14 +1679,14 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
if (ret != fileSz) {
XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
else {
/* use buffer directly */
loadBuf = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_FILE);
if (loadBuf == NULL) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
fileSz = keySz;
XMEMCPY(loadBuf, keyFile, fileSz);
@@ -1735,7 +1723,7 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
}
if (ret < 0) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
return ret;
@@ -1754,14 +1742,14 @@ static int CreateWatchSnifferServer(char* error)
DYNAMIC_TYPE_SNIFFER_SERVER);
if (sniffer == NULL) {
SetError(MEMORY_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
InitSnifferServer(sniffer);
sniffer->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
if (!sniffer->ctx) {
SetError(MEMORY_STR, error, NULL, 0);
FreeSnifferServer(sniffer);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
if (CryptoDeviceId != INVALID_DEVID)
@@ -1803,7 +1791,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY);
if (namedKey == NULL) {
SetError(MEMORY_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
XMEMSET(namedKey, 0, sizeof(NamedKey));
@@ -1818,7 +1806,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
if (ret < 0) {
SetError(KEY_FILE_STR, error, NULL, 0);
FreeNamedKey(namedKey);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
#endif
@@ -1852,7 +1840,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
#ifdef HAVE_SNI
FreeNamedKey(namedKey);
#endif
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
InitSnifferServer(sniffer);
@@ -1868,7 +1856,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
FreeNamedKey(namedKey);
#endif
FreeSnifferServer(sniffer);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
if (CryptoDeviceId != INVALID_DEVID)
@@ -1909,7 +1897,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
SetError(KEY_FILE_STR, error, NULL, 0);
if (isNew)
FreeSnifferServer(sniffer);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#ifdef WOLF_CRYPTO_CB
wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
@@ -2127,7 +2115,7 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error)
if (version != IPV6) {
SetError(BAD_IPVER_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* Here, we need to move onto next header if not TCP. */
@@ -2137,7 +2125,7 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error)
int hdrsz = (exthdr->length + 1) * 8;
if (hdrsz > length - exthdrsz) {
SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
exthdrsz += hdrsz;
exthdr = (Ip6ExtHdr*)((byte*)exthdr + hdrsz);
@@ -2149,7 +2137,7 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error)
#ifndef WOLFSSL_SNIFFER_WATCH
if (!IsServerRegistered6(iphdr->src) && !IsServerRegistered6(iphdr->dst)) {
SetError(SERVER_NOT_REG_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#endif
@@ -2183,12 +2171,12 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error,
if (version != IPV4) {
SetError(BAD_IPVER_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (iphdr->protocol != TCP_PROTOCOL) {
SetError(BAD_PROTO_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
info->length = IP_HL(iphdr);
@@ -2237,8 +2225,23 @@ static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
XMEMCPY(rh, input, RECORD_HEADER_SZ);
*size = (rh->length[0] << 8) | rh->length[1];
+ /* make sure length is valid */
if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
return LENGTH_ERROR;
+ /* make sure the record type is valid */
+ if (rh->type < change_cipher_spec ||
+ #ifdef WOLFSSL_DTLS13
+ rh->type > ack
+ #else
+ rh->type > dtls12_cid
+ #endif
+ ) {
+ return UNKNOWN_RECORD_TYPE;
+ }
+ /* make sure version is valid */
+ if (rh->pvMajor > SSLv3_MAJOR || rh->pvMinor > TLSv1_3_MINOR) {
+ return VERSION_ERROR;
+ }
return 0;
}
@@ -2481,7 +2484,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
args = (SetupKeysArgs*)ssl->async->args;
ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* Check for error */
if (ret < 0)
goto exit_sk;
@@ -2580,7 +2583,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
if (args->length > *sslBytes) {
SetError(PARTIAL_INPUT_STR, error, session,
FATAL_ERROR_STATE);
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
@@ -2803,7 +2806,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
if (args->length > *sslBytes) {
SetError(PARTIAL_INPUT_STR, error, session,
FATAL_ERROR_STATE);
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
/* if curve not provided in key share data, then use private
@@ -2896,7 +2899,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
if (args->length > *sslBytes) {
SetError(PARTIAL_INPUT_STR, error, session,
FATAL_ERROR_STATE);
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
@@ -2979,7 +2982,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
if (args->length > *sslBytes) {
SetError(PARTIAL_INPUT_STR, error, session,
FATAL_ERROR_STATE);
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 0) {
@@ -3089,7 +3092,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#endif /* HAVE_CURVE448 */
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* Handle async pending response */
ret = wolfSSL_AsyncPush(ssl, asyncDev);
break;
@@ -3165,13 +3168,13 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
if (SetCipherSpecs(session->sslServer) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
- ret = -1; break;
+ ret = WOLFSSL_FATAL_ERROR; break;
}
if (SetCipherSpecs(session->sslClient) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
- ret = -1; break;
+ ret = WOLFSSL_FATAL_ERROR; break;
}
#ifdef WOLFSSL_TLS13
@@ -3203,7 +3206,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
}
if (ret != 0) {
SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
- ret = -1; break;
+ ret = WOLFSSL_FATAL_ERROR; break;
}
#ifdef SHOW_SECRETS
@@ -3228,7 +3231,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
exit_sk:
/* Handle async pending response */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return ret;
}
#endif /* WOLFSSL_ASYNC_CRYPT */
@@ -3263,7 +3266,7 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
session->sslServer->buffers.key->length == 0) {
SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#endif
@@ -3276,25 +3279,28 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
static int ProcessKeyShare(KeyShareInfo* info, const byte* input, int len,
word16 filter_group)
{
- int index = 0;
- while (index < len) {
+ int idx = 0;
+ while (idx < len) {
/* clear info (reset dh_key_bits and curve_id) */
XMEMSET(info, 0, sizeof(KeyShareInfo));
/* Named group and public key */
- info->named_group = (word16)((input[index] << 8) | input[index+1]);
- index += OPAQUE16_LEN;
+ if (idx + OPAQUE16_LEN > len) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ info->named_group = (word16)((input[idx] << 8) | input[idx+1]);
+ idx += OPAQUE16_LEN;
info->key_len = 0;
info->key = NULL;
/* If key was provided... (a hello_retry_request will not send a key) */
- if (index + 2 <= len) {
- info->key_len = (word16)((input[index] << 8) | input[index+1]);
- index += OPAQUE16_LEN;
- if (info->key_len == 0 || info->key_len > len - index) {
- return -1;
+ if (idx + 2 <= len) {
+ info->key_len = (word16)((input[idx] << 8) | input[idx+1]);
+ idx += OPAQUE16_LEN;
+ if (info->key_len == 0 || info->key_len > len - idx) {
+ return WOLFSSL_FATAL_ERROR;
}
- info->key = &input[index];
- index += info->key_len;
+ info->key = &input[idx];
+ idx += info->key_len;
}
switch (info->named_group) {
@@ -3395,7 +3401,7 @@ static int ProcessServerKeyShare(SnifferSession* session, const byte* input, int
}
if (ret != 0) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
return ret;
@@ -3420,7 +3426,7 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
/* make sure can read through hint len */
if (TICKET_HINT_LEN > *sslBytes) {
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
input += TICKET_HINT_LEN; /* skip over hint len */
*sslBytes -= TICKET_HINT_LEN;
@@ -3431,7 +3437,7 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
/* make sure can read through hint age and nonce len */
if (TICKET_HINT_AGE_LEN + 1 > *sslBytes) {
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
input += TICKET_HINT_AGE_LEN; /* skip over hint age */
*sslBytes -= TICKET_HINT_AGE_LEN;
@@ -3440,7 +3446,7 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
len = input[0];
if (len > MAX_TICKET_NONCE_STATIC_SZ) {
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
input += OPAQUE8_LEN;
*sslBytes -= OPAQUE8_LEN;
@@ -3458,7 +3464,7 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
/* make sure can read through len */
if (OPAQUE16_LEN > *sslBytes) {
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
len = (word16)((input[0] << 8) | input[1]);
@@ -3468,7 +3474,7 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
/* make sure can read through ticket */
if (len > *sslBytes) {
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#ifdef WOLFSSL_TLS13
@@ -3476,18 +3482,20 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
if (IsAtLeastTLSv1_3(ssl->version)) {
/* Note: Must use server session for sessions */
#ifdef HAVE_SESSION_TICKET
+ WOLFSSL_SESSION* sess;
if (SetTicket(session->sslServer, input, len) != 0) {
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* set haveSessionId to use the wolfSession cache */
session->sslServer->options.haveSessionId = 1;
+ #ifdef SNIFFER_SINGLE_SESSION_CACHE
/* Use the wolf Session cache to retain resumption secret */
if (session->flags.cached == 0) {
- WOLFSSL_SESSION* sess = wolfSSL_GetSession(session->sslServer,
- NULL, 0);
+ #endif /* SNIFFER_SINGLE_SESSION_CACHE */
+ sess = wolfSSL_GetSession(session->sslServer, NULL, 0);
if (sess == NULL) {
SetupSession(session->sslServer);
AddSession(session->sslServer); /* don't re add */
@@ -3495,8 +3503,10 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
INC_STAT(SnifferStats.sslResumptionInserts);
#endif
}
+ #ifdef SNIFFER_SINGLE_SESSION_CACHE
session->flags.cached = 1;
}
+ #endif /* SNIFFER_SINGLE_SESSION_CACHE */
#endif /* HAVE_SESSION_TICKET */
}
else
@@ -3505,7 +3515,7 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
/* capture last part of sessionID as macID (32 bytes) */
if (len < ID_LEN) {
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* store session with macID as sessionID */
session->sslServer->options.haveSessionId = 1;
@@ -3549,7 +3559,7 @@ static int DoResume(SnifferSession* session, char* error)
INC_STAT(SnifferStats.sslResumeMisses);
#endif
SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
@@ -3574,13 +3584,13 @@ static int DoResume(SnifferSession* session, char* error)
if (SetCipherSpecs(session->sslServer) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (SetCipherSpecs(session->sslClient) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#ifdef WOLFSSL_TLS13
@@ -3619,7 +3629,7 @@ static int DoResume(SnifferSession* session, char* error)
if (ret != 0) {
SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
return ret;
@@ -3648,7 +3658,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
/* make sure can read through session len */
if (toRead > *sslBytes) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
XMEMCPY(&pv, input, VERSION_SZ);
@@ -3673,7 +3683,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
/* make sure can read through compression */
if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (b) {
#ifdef WOLFSSL_TLS13
@@ -3721,7 +3731,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
if (b) {
SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* extensions */
@@ -3732,7 +3742,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
/* make sure can read len */
if (SUITE_LEN > *sslBytes) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
len = (word16)((input[0] << 8) | input[1]);
input += SUITE_LEN;
@@ -3740,7 +3750,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
/* make sure can read through all extensions */
if (len > *sslBytes) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
@@ -3759,7 +3769,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
if (extLen > *sslBytes) {
SetError(SERVER_HELLO_INPUT_STR, error, session,
FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#ifdef DEBUG_SNIFFER
printf("\tserver_hello ext: 0x%02x (len %d)\n", extType, extLen);
@@ -3772,7 +3782,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
if (ret != 0) {
SetError(SERVER_HELLO_INPUT_STR, error, session,
FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
break;
#endif
@@ -3838,14 +3848,14 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
#ifndef WOLFSSL_TLS13
SetError(UNSUPPORTED_TLS_VER_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#endif
}
else {
#ifdef WOLFSSL_NO_TLS12
SetError(UNSUPPORTED_TLS_VER_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#endif
}
@@ -3857,8 +3867,10 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
#endif
if (session->sslServer->options.haveSessionId) {
- if (XMEMCMP(session->sslServer->arrays->sessionID,
- session->sslClient->arrays->sessionID, ID_LEN) == 0) {
+ if (session->sslServer->arrays->sessionIDSz == ID_LEN &&
+ session->sslClient->arrays->sessionIDSz == ID_LEN &&
+ XMEMCMP(session->sslServer->arrays->sessionID,
+ session->sslClient->arrays->sessionID, ID_LEN) == 0) {
doResume = 1;
}
}
@@ -3897,7 +3909,8 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
- if (session->sslServer->error != WC_PENDING_E && session->pendSeq == 0)
+ if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) &&
+ session->pendSeq == 0)
#endif
{
/* hash server_hello */
@@ -3931,7 +3944,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
session, error, &session->cliKs);
if (ret != 0) {
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return ret;
}
#endif
@@ -4009,7 +4022,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
/* make sure can read up to session len */
if (toRead > *sslBytes) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* skip, get negotiated one from server hello */
@@ -4031,7 +4044,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
if (bLen) {
if (ID_LEN > *sslBytes) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
Trace(CLIENT_RESUME_TRY_STR);
#ifdef WOLFSSL_TLS13
@@ -4057,7 +4070,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
/* make sure can read len */
if (SUITE_LEN > *sslBytes) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
len = (word16)((input[0] << 8) | input[1]);
input += SUITE_LEN;
@@ -4065,7 +4078,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
/* make sure can read suites + comp len */
if (len + ENUM_LEN > *sslBytes) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
input += len;
*sslBytes -= len;
@@ -4076,7 +4089,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
/* make sure can read len */
if (bLen > *sslBytes) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
input += bLen;
*sslBytes -= bLen;
@@ -4090,7 +4103,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
/* make sure can read len */
if (SUITE_LEN > *sslBytes) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
len = (word16)((input[0] << 8) | input[1]);
input += SUITE_LEN;
@@ -4098,7 +4111,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
/* make sure can read through all extensions */
if (len > *sslBytes) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
@@ -4116,7 +4129,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
/* make sure can read through individual extension */
if (extLen > *sslBytes) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#ifdef DEBUG_SNIFFER
@@ -4165,7 +4178,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
word16 ksLen = (word16)((input[0] << 8) | input[1]);
if (ksLen + OPAQUE16_LEN > extLen) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* cache key share data till server_hello */
session->cliKeyShareSz = ksLen;
@@ -4189,7 +4202,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
idsLen = (word16)((input[idx] << 8) | input[idx+1]);
if (idsLen + OPAQUE16_LEN + idx > extLen) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
idx += OPAQUE16_LEN;
@@ -4197,7 +4210,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
idLen = (word16)((input[idx] << 8) | input[idx+1]);
if (idLen + OPAQUE16_LEN + idx > extLen) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
idx += OPAQUE16_LEN;
identity = &input[idx];
@@ -4213,7 +4226,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
bindersLen = (word16)((input[idx] << 8) | input[idx+1]);
if (bindersLen + OPAQUE16_LEN + idx > extLen) {
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
idx += OPAQUE16_LEN;
binders = &input[idx];
@@ -4248,7 +4261,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
if (extLen && extLen < ID_LEN) {
SetError(CLIENT_HELLO_INPUT_STR, error, session,
FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (extLen) {
if (session->ticketID == NULL) {
@@ -4257,7 +4270,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
if (session->ticketID == 0) {
SetError(MEMORY_STR, error, session,
FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
@@ -4294,12 +4307,12 @@ static int KeyWatchCall(SnifferSession* session, const byte* data, int dataSz,
char* error)
{
int ret;
- Sha256 sha;
- byte digest[SHA256_DIGEST_SIZE];
+ wc_Sha256 sha;
+ byte digest[WC_SHA256_DIGEST_SIZE];
if (WatchCb == NULL) {
SetError(WATCH_CB_MISSING_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
ret = wc_InitSha256(&sha);
@@ -4309,7 +4322,7 @@ static int KeyWatchCall(SnifferSession* session, const byte* data, int dataSz,
ret = wc_Sha256Final(&sha, digest);
if (ret != 0) {
SetError(WATCH_HASH_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
ret = WatchCb((void*)session, digest, sizeof(digest),
@@ -4319,7 +4332,7 @@ static int KeyWatchCall(SnifferSession* session, const byte* data, int dataSz,
INC_STAT(SnifferStats.sslKeysUnmatched);
#endif
SetError(WATCH_FAIL_STR, error, session, FATAL_ERROR_STATE);
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
else {
#ifdef WOLFSSL_SNIFFER_STATS
@@ -4343,7 +4356,7 @@ static int ProcessCertificate(const byte* input, int* sslBytes,
if (*sslBytes < CERT_HEADER_SZ) {
SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#ifdef WOLFSSL_TLS13
@@ -4360,14 +4373,14 @@ static int ProcessCertificate(const byte* input, int* sslBytes,
if (*sslBytes < (int)certChainSz) {
SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
ato24(input, &certSz);
input += OPAQUE24_LEN;
if (*sslBytes < (int)certSz) {
SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
*sslBytes -= certChainSz;
@@ -4412,7 +4425,11 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
return ret;
}
- if (ret == 0 && session->flags.cached == 0) {
+ if (ret == 0
+ #ifdef SNIFFER_SINGLE_SESSION_CACHE
+ && session->flags.cached == 0
+ #endif
+ ) {
if (session->sslServer->options.haveSessionId) {
#ifndef NO_SESSION_CACHE
WOLFSSL_SESSION* sess = wolfSSL_GetSession(session->sslServer, NULL, 0);
@@ -4423,7 +4440,9 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
INC_STAT(SnifferStats.sslResumptionInserts);
#endif
}
- session->flags.cached = 1;
+ #ifdef SNIFFER_SINGLE_SESSION_CACHE
+ session->flags.cached = 1;
+ #endif
#endif
}
}
@@ -4445,7 +4464,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
if (ret != 0) {
SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
session->flags.gotFinished = 1;
@@ -4481,7 +4500,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
if (ret != 0) {
SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
#endif
@@ -4531,7 +4550,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
if (*sslBytes < HANDSHAKE_HEADER_SZ) {
SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
type = input[0];
size = (input[1] << 16) | (input[2] << 8) | input[3];
@@ -4578,7 +4597,8 @@ static int DoHandShake(const byte* input, int* sslBytes,
#ifdef WOLFSSL_TLS13
if (type != client_hello && type != server_hello
#ifdef WOLFSSL_ASYNC_CRYPT
- && session->sslServer->error != WC_PENDING_E && session->pendSeq == 0
+ && session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E)
+ && session->pendSeq == 0
#endif
) {
/* For resumption the hash is before / after client_hello PSK binder */
@@ -4596,7 +4616,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
if (HashUpdate(session->hash, input, size) != 0) {
SetError(EXTENDED_MASTER_HASH_STR, error,
session, FATAL_ERROR_STATE);
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
goto exit;
}
}
@@ -4630,7 +4650,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
/* can't know temp key passively */
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
session->verboseErr = 1;
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
#if defined(WOLFSSL_SNIFFER_STATS)
INC_STAT(SnifferStats.sslEphemeralMisses);
@@ -4681,7 +4701,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
else {
SetError(EXTENDED_MASTER_HASH_STR, error,
session, FATAL_ERROR_STATE);
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
XMEMSET(session->hash, 0, sizeof(HsHashes));
XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
@@ -4696,7 +4716,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
if (ret == 0) {
ret = ProcessClientKeyExchange(input, sslBytes, session, error);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
#endif
if (ret != 0) {
@@ -4713,7 +4733,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
break;
default:
SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
break;
}
@@ -4721,10 +4741,8 @@ static int DoHandShake(const byte* input, int* sslBytes,
exit:
#endif
#ifdef HAVE_MAX_FRAGMENT
- if (session->tlsFragBuf) {
- XFREE(session->tlsFragBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- session->tlsFragBuf = NULL;
- }
+ XFREE(session->tlsFragBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ session->tlsFragBuf = NULL;
#endif
*sslBytes = startBytes - size; /* actual bytes of full process */
@@ -4763,7 +4781,7 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev);
}
#endif
@@ -4781,7 +4799,7 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
#endif
ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
}
#endif
@@ -4826,7 +4844,7 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
ssl->decrypt.additional, AEAD_AUTH_DATA_SZ,
NULL, 0)) < 0) {
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
}
#endif
@@ -4884,9 +4902,9 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input,
#ifdef WOLFSSL_ASYNC_CRYPT
if (ssl->decrypt.state != CIPHER_STATE_BEGIN) {
ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
- if (ret != WC_NO_PENDING_E) {
+ if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
/* check for still pending */
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
ssl->error = 0; /* clear async */
@@ -4942,7 +4960,7 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input,
#ifdef WOLFSSL_ASYNC_CRYPT
/* If pending, return now */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return ret;
}
#endif
@@ -4994,7 +5012,7 @@ static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz,
}
#ifdef WOLFSSL_ASYNC_CRYPT
/* for async the symmetric operations are blocking */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
do {
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
} while (ret == 0);
@@ -5009,6 +5027,7 @@ static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz,
return NULL;
}
+ ssl->curSize = sz;
ssl->keys.encryptSz = sz;
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
output += ssl->specs.block_size; /* go past TLSv1.1 IV */
@@ -5123,6 +5142,12 @@ static void RemoveStaleSessions(void)
}
}
+void ssl_RemoveStaleSessions(void)
+{
+ LOCK_SESSION();
+ RemoveStaleSessions();
+ UNLOCK_SESSION();
+}
/* Create a new Sniffer Session */
static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
@@ -5249,14 +5274,14 @@ static int DoOldHello(SnifferSession* session, const byte* sslFrame,
if (*rhSize > *sslBytes) {
SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
(word16)*rhSize);
- if (ret < 0 && ret != MATCH_SUITE_ERROR) {
+ if (ret < 0 && ret != WC_NO_ERR_TRACE(MATCH_SUITE_ERROR)) {
SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
Trace(OLD_CLIENT_OK_STR);
@@ -5322,7 +5347,7 @@ static int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
/* field, but tcp checksum offloading could negate calculation */
if (checksum == 0)
return 0;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#endif
@@ -5345,7 +5370,7 @@ static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
/* ip header */
if (length < IP_HDR_SZ) {
SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
version = IP_V(iphdr);
@@ -5359,31 +5384,31 @@ static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
}
if (CheckIpHdr(iphdr, ipInfo, length, error, trace) != 0)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#ifndef WOLFSSL_SNIFFER_WATCH
if (checkReg &&
!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
SetError(SERVER_NOT_REG_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#endif
/* tcp header */
if (length < (ipInfo->length + TCP_HDR_SZ)) {
SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
tcphdr = (TcpHdr*)(packet + ipInfo->length);
if (CheckTcpHdr(tcphdr, tcpInfo, error, trace) != 0)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#ifndef WOLFSSL_SNIFFER_WATCH
if (checkReg &&
!IsPortRegistered(tcpInfo->srcPort) &&
!IsPortRegistered(tcpInfo->dstPort)) {
SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#endif
@@ -5391,7 +5416,7 @@ static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
*sslFrame = packet + ipInfo->length + tcpInfo->length;
if (*sslFrame > packet + length) {
SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* We only care about the data in the TCP/IP record. There may be extra
@@ -5433,7 +5458,7 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
return 1;
SetError(MEMORY_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
return 1;
}
@@ -5456,7 +5481,7 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
#endif
SetError(BAD_SESSION_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
return 0;
@@ -5517,12 +5542,12 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
if (MaxRecoveryMemory != -1 &&
(int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
if (add == NULL) {
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
*front = add;
*reassemblyMemory += sslBytes;
@@ -5539,12 +5564,12 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
if (MaxRecoveryMemory -1 &&
(int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
if (add == NULL) {
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
add->next = curr;
*front = add;
@@ -5581,13 +5606,13 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
if (MaxRecoveryMemory != -1 &&
(int)(*reassemblyMemory + added) > MaxRecoveryMemory) {
SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
&bytesLeft);
if (add == NULL) {
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
add->next = prev->next;
prev->next = add;
@@ -5611,47 +5636,6 @@ static int AddFinCapture(SnifferSession* session, word32 sequence)
return 1;
}
-static int FindPrevAck(SnifferSession* session, word32 realAck)
-{
- int i;
- word32* acks = (session->flags.side == WOLFSSL_SERVER_END) ?
- session->cliAcks : session->srvAcks;
- /* if previous ack found return 1, otherwise 0 */
- for (i=0; iflags.side == WOLFSSL_SERVER_END) ?
- session->cliAcks : session->srvAcks;
- /* find first empty ack slot */
- for (i=0; iflags.side == WOLFSSL_SERVER_END) ?
- session->cliSeqStart :session->srvSeqStart;
+ session->cliSeqStart : session->srvSeqStart;
+ word32* seqLast = (session->flags.side == WOLFSSL_SERVER_END) ?
+ &session->cliSeqLast : &session->srvSeqLast;
word32 real = tcpInfo->sequence - seqStart;
word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
&session->cliExpected : &session->srvExpected;
@@ -5676,10 +5662,11 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
TraceRelativeSequence(*expected, real);
if (real < *expected) {
+ int overlap = *expected - real;
if (real + *sslBytes > *expected) {
#ifdef WOLFSSL_ASYNC_CRYPT
- if (session->sslServer->error != WC_PENDING_E &&
+ if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) &&
session->pendSeq != tcpInfo->sequence)
#endif
{
@@ -5690,7 +5677,6 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
* same action but for a different setup case. If changing this
* block be sure to also update the block below. */
if (reassemblyList) {
- int overlap = *expected - real;
word32 newEnd;
/* adjust to expected, remove duplicate */
@@ -5719,11 +5705,23 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
newEnd - reassemblyList->end, session, error);
}
}
- else {
- /* DUP overlap, allow */
- if (*sslBytes > 0) {
- skipPartial = 0; /* do not reset sslBytes */
+ else if (*sslBytes > 0) {
+ if (real + *sslBytes - 1 > *seqLast) {
+ /* fix segment overlap */
+ #ifdef DEBUG_SNIFFER
+ WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
+ session->sslServer : session->sslClient;
+ printf("\tSegment %d overlap (%d -> %d)\n",
+ *sslBytes,
+ ssl->buffers.inputBuffer.length - overlap,
+ ssl->buffers.inputBuffer.length + *sslBytes - overlap - 1);
+ #endif
+ *sslBytes -= overlap;
+ *sslFrame += overlap;
}
+
+ /* DUP overlap, allow */
+ skipPartial = 0; /* do not reset sslBytes */
}
ret = 0;
}
@@ -5732,13 +5730,13 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
* possible spurious retransmission. */
if (*sslBytes > 0) {
/* If packet has data attempt to process packet, if hasn't
- * already been ack'd during handshake */
+ * already been received */
if (
#ifdef WOLFSSL_ASYNC_CRYPT
- session->sslServer->error != WC_PENDING_E &&
+ session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) &&
session->pendSeq != tcpInfo->sequence &&
#endif
- FindPrevAck(session, real)) {
+ real + *sslBytes -1 <= *seqLast) {
Trace(DUPLICATE_STR);
ret = 1;
}
@@ -5810,7 +5808,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
*expected += 1;
}
if (*sslBytes > 0) {
- AddAck(session, real);
+ *seqLast = real + *sslBytes - 1;
}
if (*sslBytes > 0 && skipPartial) {
*sslBytes = 0;
@@ -5857,7 +5855,7 @@ static int FindNextRecordInAssembly(SnifferSession* session,
if ( *sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) {
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
@@ -5949,7 +5947,7 @@ static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
TraceAck(real, expected);
if (real > expected)
- return -1; /* we missed a packet, ACKing data we never saw */
+ return WOLFSSL_FATAL_ERROR; /* we missed a packet, ACKing data we never saw */
}
return 0;
}
@@ -5998,7 +5996,7 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
UpdateMissedDataSessions();
#endif
SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
else {
SetError(ACK_MISSED_STR, error, session, 0);
@@ -6025,8 +6023,7 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
/* returns 0 on success (continue), -1 on error, 1 on success (end) */
static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
const byte** sslFrame, SnifferSession** pSession,
- int* sslBytes, const byte** end,
- void* vChain, word32 chainSz, char* error)
+ int* sslBytes, const byte** end, char* error)
{
word32 length;
SnifferSession* session = *pSession;
@@ -6039,7 +6036,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
#ifdef WOLFSSL_ASYNC_CRYPT
/* if this is a pending async packet do not "grow" on partial (we already did) */
if (session->pendSeq == tcpInfo->sequence) {
- if (session->sslServer->error == WC_PENDING_E) {
+ if (session->sslServer->error == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return 0; /* don't check pre-record again */
}
/* if record check already done then restore, otherwise process normal */
@@ -6069,13 +6066,13 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
if (session->flags.fatalError == FATAL_ERROR_STATE) {
SetError(FATAL_ERROR_STR, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (skipPartial) {
if (FindNextRecordInAssembly(session,
sslFrame, sslBytes, end, error) < 0) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
@@ -6093,56 +6090,15 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
- if (vChain == NULL) {
- XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
- *sslFrame, *sslBytes);
- *sslBytes += length;
- ssl->buffers.inputBuffer.length = *sslBytes;
- *sslFrame = ssl->buffers.inputBuffer.buffer;
- *end = *sslFrame + *sslBytes;
- }
- else {
- #ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
- struct iovec* chain = (struct iovec*)vChain;
- word32 i, offset, headerSz, qty, remainder;
-
- Trace(CHAIN_INPUT_STR);
- headerSz = (word32)((const byte*)*sslFrame - (const byte*)chain[0].iov_base);
- remainder = *sslBytes;
-
- if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
- if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
- SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
- return -1;
- }
- }
-
- qty = min(*sslBytes, (word32)chain[0].iov_len - headerSz);
- XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
- (byte*)chain[0].iov_base + headerSz, qty);
- offset = length;
- for (i = 1; i < chainSz; i++) {
- offset += qty;
- remainder -= qty;
-
- if (chain[i].iov_len > remainder)
- qty = remainder;
- else
- qty = (word32)chain[i].iov_len;
- XMEMCPY(ssl->buffers.inputBuffer.buffer + offset,
- chain[i].iov_base, qty);
- }
-
- *sslBytes += length;
- ssl->buffers.inputBuffer.length = *sslBytes;
- *sslFrame = ssl->buffers.inputBuffer.buffer;
- *end = *sslFrame + *sslBytes;
- #endif
- (void)chainSz;
- }
+ XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
+ *sslFrame, *sslBytes);
+ *sslBytes += length;
+ ssl->buffers.inputBuffer.length = *sslBytes;
+ *sslFrame = ssl->buffers.inputBuffer.buffer;
+ *end = *sslFrame + *sslBytes;
}
if (session->flags.clientHello == 0 && **sslFrame != handshake) {
@@ -6154,7 +6110,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
#ifdef OLD_HELLO_ALLOWED
int ret = DoOldHello(session, *sslFrame, &rhSize, sslBytes, error);
if (ret < 0)
- return -1; /* error already set */
+ return WOLFSSL_FATAL_ERROR; /* error already set */
if (*sslBytes <= 0)
return 1;
#endif
@@ -6265,7 +6221,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
rhSize = 0;
if (sslBytes < 0) {
SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (sslBytes >= RECORD_HEADER_SZ) {
if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
@@ -6287,7 +6243,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
@@ -6325,11 +6281,11 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
}
if (ssl->decrypt.setup != 1) {
SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (CheckAvailableSize(ssl, rhSize) < 0) {
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
@@ -6353,7 +6309,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
if (errCode != 0) {
if ((enum ContentType)rh.type == application_data) {
SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* do not end session for failures on handshake packets */
return 0;
@@ -6371,14 +6327,14 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
Trace(GOT_HANDSHAKE_STR);
ret = DoHandShake(sslFrame, &sslBytes, session, error, rhSize);
#ifdef WOLFSSL_ASYNC_CRYPT
- if (ret == WC_PENDING_E)
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
#endif
if (ret != 0 || sslBytes > startIdx) {
if (session->flags.fatalError == 0)
SetError(BAD_HANDSHAKE_STR, error, session,
FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* DoHandShake now fully decrements sslBytes to remaining */
@@ -6414,12 +6370,33 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
Trace(GOT_APP_DATA_STR);
{
word32 inOutIdx = 0;
+ int ivExtra = 0;
ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx, SNIFF);
if (ret == 0) {
ret = ssl->buffers.clearOutputBuffer.length;
+ #ifndef WOLFSSL_AEAD_ONLY
+ if (ssl->specs.cipher_type == block) {
+ if (ssl->options.tls1_1)
+ ivExtra = ssl->specs.block_size;
+ }
+ else
+ #endif
+ if (ssl->specs.cipher_type == aead) {
+ if (!ssl->options.tls1_3 &&
+ ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
+ ivExtra = AESGCM_EXP_IV_SZ;
+ }
+
+ ret -= ivExtra;
+
+ #if defined(HAVE_ENCRYPT_THEN_MAC) && \
+ !defined(WOLFSSL_AEAD_ONLY)
+ if (ssl->options.startedETMRead)
+ ret -= MacSize(ssl);
+ #endif
TraceGotData(ret);
- if (ret) { /* may be blank message */
+ if (ret > 0) { /* may be blank message */
if (data != NULL) {
byte* tmpData; /* don't leak on realloc free */
/* add an extra byte at end of allocation in case
@@ -6432,7 +6409,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
*data = NULL;
SetError(MEMORY_STR, error, session,
FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
*data = tmpData;
XMEMCPY(*data + decoded,
@@ -6452,7 +6429,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
stored = StoreDataCb(buf, bufSz, offset,
ctx);
if (stored <= 0) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
offset += stored;
} while (offset < bufSz);
@@ -6460,24 +6437,34 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
else {
SetError(STORE_DATA_CB_MISSING_STR, error,
session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
#else
(void)ctx;
SetError(NO_DATA_DEST_STR, error, session,
FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
#endif
}
TraceAddedData(ret, decoded);
decoded += ret;
ssl->buffers.clearOutputBuffer.length = 0;
}
+ else if (ret < 0){
+ #ifdef DEBUG_SNIFFER
+ printf("Invalid data offset calculation! "
+ "ret %d, inOutIdx %d, ivExtra %d\n",
+ ret, inOutIdx, ivExtra);
+ #endif
+ /* set error, but do not treat fatal */
+ SetError(BAD_APP_DATA_STR, error, session, 0);
+ return WOLFSSL_FATAL_ERROR;
+ }
}
else {
/* set error, but do not treat fatal */
- SetError(BAD_APP_DATA_STR, error,session, 0);
- return -1;
+ SetError(BAD_APP_DATA_STR, error, session, 0);
+ return WOLFSSL_FATAL_ERROR;
}
if (ssl->buffers.outputBuffer.dynamicFlag)
ShrinkOutputBuffer(ssl);
@@ -6498,14 +6485,16 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
case ack:
/* TODO */
#endif /* WOLFSSL_DTLS13 */
+ case dtls12_cid:
case no_type:
default:
SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
- /* do we have another msg in record ? */
- if (sslFrame < recordEnd) {
+ /* do we have another msg in record (if app data did we decode bytes?) */
+ if (sslFrame < recordEnd && ((enum ContentType)rh.type != application_data ||
+ ((enum ContentType)rh.type == application_data && decoded))) {
Trace(ANOTHER_MSG_STR);
goto doPart;
}
@@ -6617,27 +6606,33 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
{
TcpInfo tcpInfo;
IpInfo ipInfo;
+ byte* tmpPacket = NULL; /* Assemble the chain */
const byte* sslFrame;
const byte* end;
int sslBytes; /* ssl bytes unconsumed */
int ret;
SnifferSession* session = NULL;
- void* vChain = NULL;
- word32 chainSz = 0;
if (isChain) {
#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
struct iovec* chain;
word32 i;
- vChain = (void*)packet;
- chainSz = (word32)length;
+ word32 chainSz = (word32)length;
+
+ chain = (struct iovec*)packet;
+ length = 0;
+ for (i = 0; i < chainSz; i++) length += chain[i].iov_len;
+
+ tmpPacket = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_SNIFFER_CHAIN_BUFFER);
+ if (tmpPacket == NULL) return MEMORY_E;
- chain = (struct iovec*)vChain;
length = 0;
- for (i = 0; i < chainSz; i++)
+ for (i = 0; i < chainSz; i++) {
+ XMEMCPY(tmpPacket+length,chain[i].iov_base,chain[i].iov_len);
length += chain[i].iov_len;
- packet = (const byte*)chain[0].iov_base;
+ }
+ packet = (const byte*)tmpPacket;
#else
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
return WOLFSSL_SNIFFER_ERROR;
@@ -6646,18 +6641,27 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
error, 1, 1) != 0) {
- return WOLFSSL_SNIFFER_ERROR;
+ ret = WOLFSSL_SNIFFER_ERROR;
+ goto exit_decode;
}
end = sslFrame + sslBytes;
ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
- if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
- return WOLFSSL_SNIFFER_FATAL_ERROR;
+ if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
+ ret = WOLFSSL_SNIFFER_FATAL_ERROR;
+ goto exit_decode;
+ }
#ifdef WOLFSSL_ASYNC_CRYPT
- else if (ret == WC_PENDING_E) return WC_PENDING_E;
+ else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
+ ret = WC_PENDING_E;
+ goto exit_decode;
+ }
#endif
- else if (ret == -1) return WOLFSSL_SNIFFER_ERROR;
+ else if (ret == -1) {
+ ret = WOLFSSL_SNIFFER_ERROR;
+ goto exit_decode;
+ }
else if (ret == 1) {
#ifdef WOLFSSL_SNIFFER_STATS
if (sslBytes > 0) {
@@ -6670,7 +6674,8 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
INC_STAT(SnifferStats.sslDecryptedPackets);
}
#endif
- return 0; /* done for now */
+ ret = 0;
+ goto exit_decode; /* done for now */
}
#ifdef WOLFSSL_ASYNC_CRYPT
@@ -6678,43 +6683,56 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
#endif
ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
- if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
- return WOLFSSL_SNIFFER_FATAL_ERROR;
- else if (ret == -1) return WOLFSSL_SNIFFER_ERROR;
+ if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
+ ret = WOLFSSL_SNIFFER_FATAL_ERROR;
+ goto exit_decode;
+ }
+ else if (ret == -1) {
+ ret = WOLFSSL_SNIFFER_ERROR;
+ goto exit_decode;
+ }
else if (ret == 1) {
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslDecryptedPackets);
#endif
- return 0; /* done for now */
+ ret = 0;
+ goto exit_decode; /* done for now */
}
else if (ret != 0) {
- /* return specific error case */
- return ret;
+ goto exit_decode; /* return specific error case */
}
ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
- &end, vChain, chainSz, error);
- if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
- return WOLFSSL_SNIFFER_FATAL_ERROR;
- else if (ret == -1) return WOLFSSL_SNIFFER_ERROR;
+ &end, error);
+ if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
+ ret = WOLFSSL_SNIFFER_FATAL_ERROR;
+ goto exit_decode;
+ }
+ else if (ret == -1) {
+ ret = WOLFSSL_SNIFFER_ERROR;
+ goto exit_decode;
+ }
else if (ret == 1) {
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslDecryptedPackets);
#endif
- return 0; /* done for now */
+ ret = 0;
+ goto exit_decode; /* done for now */
}
#ifdef WOLFSSL_ASYNC_CRYPT
/* make sure this server was polled */
- if (asyncOkay && session->sslServer->error == WC_PENDING_E &&
+ if (asyncOkay &&
+ session->sslServer->error == WC_NO_ERR_TRACE(WC_PENDING_E) &&
!session->flags.wasPolled) {
- return WC_PENDING_E;
+ ret = WC_PENDING_E;
+ goto exit_decode;
}
#endif
#ifdef WOLFSSL_SNIFFER_STATS
#ifdef WOLFSSL_ASYNC_CRYPT
- if (session->sslServer->error != WC_PENDING_E)
+ if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
if (sslBytes > 0) {
@@ -6736,7 +6754,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
session->sslServer->error = ret;
#ifdef WOLFSSL_ASYNC_CRYPT
/* capture the seq pending for this session */
- if (ret == WC_PENDING_E) {
+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
session->flags.wasPolled = 0;
session->pendSeq = tcpInfo.sequence;
if (!asyncOkay || CryptoDeviceId == INVALID_DEVID) {
@@ -6745,23 +6763,29 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
wolfSSL_AsyncPoll(session->sslServer, WOLF_POLL_FLAG_CHECK_HW);
}
else {
- return ret; /* return to caller */
+ goto exit_decode; /* return to caller */
}
}
else {
session->pendSeq = 0;
}
- } while (ret == WC_PENDING_E);
+ } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
#else
(void)asyncOkay;
#endif
- if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
- return WOLFSSL_SNIFFER_FATAL_ERROR;
+ if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
+ ret = WOLFSSL_SNIFFER_FATAL_ERROR;
+ goto exit_decode;
+ }
if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) {
CopySessionInfo(session, sslInfo);
}
+exit_decode:
+ if (isChain) {
+ XFREE(tmpPacket, NULL, DYNAMIC_TYPE_SNIFFER_CHAIN_BUFFER);
+ }
return ret;
}
@@ -6848,7 +6872,7 @@ int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error)
(void)error;
if (sz < 0) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (data != NULL) {
@@ -6868,11 +6892,15 @@ int ssl_Trace(const char* traceFile, char* error)
if (traceFile) {
/* Don't try to reopen the file */
if (TraceFile == NULL) {
- TraceFile = XFOPEN(traceFile, "a");
- if (!TraceFile) {
- SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
- return -1;
- }
+ if (XSTRCMP(traceFile, "-") == 0) {
+ TraceFile = stdout;
+ } else {
+ TraceFile = XFOPEN(traceFile, "a");
+ if (!TraceFile) {
+ SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
TraceOn = 1;
}
}
@@ -6941,7 +6969,7 @@ int ssl_GetSessionStats(unsigned int* active, unsigned int* total,
return 0;
else {
SetError(BAD_SESSION_STATS, error, NULL, 0);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
}
@@ -6982,7 +7010,7 @@ int ssl_ResetStatistics(void)
int ssl_ReadStatistics(SSLStats* stats)
{
if (stats == NULL)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
LOCK_STAT();
XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
@@ -6996,7 +7024,7 @@ int ssl_ReadStatistics(SSLStats* stats)
int ssl_ReadResetStatistics(SSLStats* stats)
{
if (stats == NULL)
- return -1;
+ return WOLFSSL_FATAL_ERROR;
LOCK_STAT();
XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
@@ -7042,10 +7070,10 @@ int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz,
int ret;
if (vSniffer == NULL) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (key == NULL || keySz == 0) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
sniffer = (SnifferSession*)vSniffer;
@@ -7074,7 +7102,7 @@ int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz,
if (ret != WOLFSSL_SUCCESS) {
SetError(KEY_FILE_STR, error, sniffer, FATAL_ERROR_STATE);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
return 0;
@@ -7088,10 +7116,10 @@ int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType,
int ret;
if (vSniffer == NULL) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
if (keyFile == NULL) {
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
/* Remap the keyType from what the user can use to
@@ -7103,7 +7131,7 @@ int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType,
if (ret < 0) {
SetError(KEY_FILE_STR, error, NULL, 0);
XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509);
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
ret = ssl_SetWatchKey_buffer(vSniffer, keyBuf, keyBufSz, FILETYPE_DER,
@@ -7238,11 +7266,11 @@ typedef struct SecretNode {
#define WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE HASH_SIZE
#endif
-static THREAD_LS_T WOLFSSL_GLOBAL
+static THREAD_LS_T
SecretNode*
secretHashTable[WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE] = {NULL};
#ifndef HAVE_C___ATOMIC
-static WOLFSSL_GLOBAL wolfSSL_Mutex secretListMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(secretListMutex);
+static WC_THREADSHARED wolfSSL_Mutex secretListMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(secretListMutex);
#endif
static unsigned int secretHashFunction(unsigned char* clientRandom);
@@ -7285,7 +7313,7 @@ static int addSecretNode(unsigned char* clientRandom,
unsigned char* secret,
char* error)
{
- int index = 0;
+ int idx = 0;
int ret = 0;
SecretNode* node = NULL;
@@ -7295,8 +7323,8 @@ static int addSecretNode(unsigned char* clientRandom,
LOCK_SECRET_LIST();
- index = secretHashFunction(clientRandom);
- node = secretHashTable[index];
+ idx = secretHashFunction(clientRandom);
+ node = secretHashTable[idx];
while(node) {
/* Node already exists, so just add the requested secret */
@@ -7321,8 +7349,8 @@ static int addSecretNode(unsigned char* clientRandom,
XMEMCPY(node->clientRandom, clientRandom, CLIENT_RANDOM_LENGTH);
XMEMCPY(node->secrets[type], secret, SECRET_LENGTH);
- node->next = secretHashTable[index];
- secretHashTable[index] = node;
+ node->next = secretHashTable[idx];
+ secretHashTable[idx] = node;
unlockReturn:
@@ -7339,12 +7367,12 @@ static unsigned char* findSecret(unsigned char* clientRandom, int type)
{
unsigned char* secret = NULL;
SecretNode* node = NULL;
- unsigned int index = 0;
+ unsigned int idx = 0;
LOCK_SECRET_LIST();
- index = secretHashFunction(clientRandom);
- node = secretHashTable[index];
+ idx = secretHashFunction(clientRandom);
+ node = secretHashTable[idx];
while (node != NULL) {
if (XMEMCMP(node->clientRandom,
@@ -7616,6 +7644,106 @@ int ssl_LoadSecretsFromKeyLogFile(const char* keylogfile, char* error)
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
+/*
+ * Removes a session from the SessionTable based on client/server IP & ports
+ * Returns 0 if a session was found and freed, -1 otherwise
+ */
+int ssl_RemoveSession(const char* clientIp, int clientPort,
+ const char* serverIp, int serverPort,
+ char* error)
+{
+ IpAddrInfo clientAddr;
+ IpAddrInfo serverAddr;
+ IpInfo ipInfo;
+ TcpInfo tcpInfo;
+ SnifferSession* session;
+ int ret = -1; /* Default to not found */
+ word32 row;
+
+ if (clientIp == NULL || serverIp == NULL) {
+ SetError(BAD_IPVER_STR, error, NULL, 0);
+ return ret;
+ }
+
+ /* Set up client IP address */
+ clientAddr.version = IPV4;
+ clientAddr.ip4 = XINET_ADDR(clientIp);
+ if (clientAddr.ip4 == XINADDR_NONE) {
+ #ifdef FUSION_RTOS
+ if (XINET_PTON(AF_INET6, clientIp, clientAddr.ip6,
+ sizeof(clientAddr.ip4)) == 1)
+ #else
+ if (XINET_PTON(AF_INET6, clientIp, clientAddr.ip6) == 1)
+ #endif
+ {
+ clientAddr.version = IPV6;
+ }
+ else {
+ SetError(BAD_IPVER_STR, error, NULL, 0);
+ return ret;
+ }
+ }
+
+ /* Set up server IP address */
+ serverAddr.version = IPV4;
+ serverAddr.ip4 = XINET_ADDR(serverIp);
+ if (serverAddr.ip4 == XINADDR_NONE) {
+ #ifdef FUSION_RTOS
+ if (XINET_PTON(AF_INET6, serverIp, serverAddr.ip6,
+ sizeof(serverAddr.ip4)) == 1)
+ #else
+ if (XINET_PTON(AF_INET6, serverIp, serverAddr.ip6) == 1)
+ #endif
+ {
+ serverAddr.version = IPV6;
+ }
+ else {
+ SetError(BAD_IPVER_STR, error, NULL, 0);
+ return ret;
+ }
+ }
+
+ XMEMSET(&ipInfo, 0, sizeof(ipInfo));
+ XMEMSET(&tcpInfo, 0, sizeof(tcpInfo));
+
+ /* Set up client->server direction */
+ ipInfo.src = clientAddr;
+ ipInfo.dst = serverAddr;
+ tcpInfo.srcPort = clientPort;
+ tcpInfo.dstPort = serverPort;
+
+ /* Calculate the hash row for this session */
+ row = SessionHash(&ipInfo, &tcpInfo);
+
+ LOCK_SESSION();
+
+ /* Search only the specific row in the session table */
+ session = SessionTable[row];
+
+ while (session) {
+ SnifferSession* next = session->next;
+
+ /* Check if this session matches the specified client/server IP/port */
+ if (MatchAddr(session->client, clientAddr) &&
+ MatchAddr(session->server, serverAddr) &&
+ session->cliPort == clientPort &&
+ session->srvPort == serverPort) {
+
+ /* Use RemoveSession to remove and free the session */
+ RemoveSession(session, NULL, NULL, row);
+ ret = 0; /* Session found and freed */
+ break;
+ }
+
+ session = next;
+ }
+
+ UNLOCK_SESSION();
+
+ return ret;
+}
+
+
#undef ERROR_OUT
#endif /* WOLFSSL_SNIFFER */
diff --git a/src/src/ssl.c b/src/src/ssl.c
index 1d501f8..9b69597 100644
--- a/src/src/ssl.c
+++ b/src/src/ssl.c
@@ -1,12 +1,12 @@
/* ssl.c
*
- * Copyright (C) 2006-2023 wolfSSL Inc.
+ * Copyright (C) 2006-2025 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
@@ -19,16 +19,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+#include
-#ifdef HAVE_CONFIG_H
- #include
-#endif
-
-#include
-#if defined(OPENSSL_EXTRA) && !defined(_WIN32)
+#if defined(OPENSSL_EXTRA) && !defined(_WIN32) && !defined(_GNU_SOURCE)
/* turn on GNU extensions for XISASCII */
- #undef _GNU_SOURCE
- #define _GNU_SOURCE
+ #define _GNU_SOURCE 1
#endif
#if !defined(WOLFCRYPT_ONLY) || defined(OPENSSL_EXTRA) || \
@@ -54,7 +49,8 @@
#if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \
&& !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \
&& !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448)
- #error "No cipher suites defined because DH disabled, ECC disabled, and no static suites defined. Please see top of README"
+ #error "No cipher suites defined because DH disabled, ECC disabled, " \
+ "and no static suites defined. Please see top of README"
#endif
#ifdef WOLFSSL_CERT_GEN
/* need access to Cert struct for creating certificate */
@@ -115,14 +111,15 @@
#include
#include
#include
- #if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
#include
#endif /* HAVE_FALCON */
#if defined(HAVE_DILITHIUM)
#include
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
+ #if defined(HAVE_SPHINCS)
+ #include
+ #endif /* HAVE_SPHINCS */
#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL)
#ifdef HAVE_OCSP
#include
@@ -137,12 +134,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 +151,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 +187,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)) && \
@@ -223,93 +198,44 @@
*
* For OpenSSL compatibility.
*
- * This function shouldn't exist!
- * Uses defines in wolfssl/openssl/evp.h.
- * Uses EccEnumToNID which uses defines in wolfssl/openssl/ec.h.
- *
* @param [in] sn Short name of OID.
* @return NID corresponding to shortname on success.
- * @return NID_undef when not recognized.
+ * @return WC_NID_undef when not recognized.
*/
int wc_OBJ_sn2nid(const char *sn)
{
- const struct {
- const char *sn;
- int nid;
- } sn2nid[] = {
-#ifndef NO_CERTS
- {WOLFSSL_COMMON_NAME, NID_commonName},
- {WOLFSSL_COUNTRY_NAME, NID_countryName},
- {WOLFSSL_LOCALITY_NAME, NID_localityName},
- {WOLFSSL_STATE_NAME, NID_stateOrProvinceName},
- {WOLFSSL_ORG_NAME, NID_organizationName},
- {WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName},
- #ifdef WOLFSSL_CERT_NAME_ALL
- {WOLFSSL_NAME, NID_name},
- {WOLFSSL_INITIALS, NID_initials},
- {WOLFSSL_GIVEN_NAME, NID_givenName},
- {WOLFSSL_DNQUALIFIER, NID_dnQualifier},
- #endif
- {WOLFSSL_EMAIL_ADDR, NID_emailAddress},
-#endif
- {"SHA1", NID_sha1},
- {NULL, -1}};
- int i;
-#ifdef HAVE_ECC
- char curveName[ECC_MAXNAME + 1];
- int eccEnum;
-#endif
-
+ const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info;
+ size_t i;
WOLFSSL_ENTER("wc_OBJ_sn2nid");
-
- for(i=0; sn2nid[i].sn != NULL; i++) {
- if (XSTRCMP(sn, sn2nid[i].sn) == 0) {
- return sn2nid[i].nid;
- }
- }
-
-#ifdef HAVE_ECC
- if (XSTRLEN(sn) > ECC_MAXNAME)
- return NID_undef;
-
- /* Nginx uses this OpenSSL string. */
- if (XSTRCMP(sn, "prime256v1") == 0)
- sn = "SECP256R1";
- /* OpenSSL allows lowercase curve names */
- for (i = 0; i < (int)(sizeof(curveName) - 1) && *sn; i++) {
- curveName[i] = (char)XTOUPPER((unsigned char) *sn++);
- }
- curveName[i] = '\0';
- /* find based on name and return NID */
- for (i = 0;
-#ifndef WOLFSSL_ECC_CURVE_STATIC
- ecc_sets[i].size != 0 && ecc_sets[i].name != NULL;
-#else
- ecc_sets[i].size != 0;
-#endif
- i++) {
- if (XSTRCMP(curveName, ecc_sets[i].name) == 0) {
- eccEnum = ecc_sets[i].id;
- /* Convert enum value in ecc_curve_id to OpenSSL NID */
- return EccEnumToNID(eccEnum);
- }
+ for (i = 0; i < wolfssl_object_info_sz; i++, obj_info++) {
+ if (XSTRCMP(sn, obj_info->sName) == 0)
+ return obj_info->nid;
}
-#endif /* HAVE_ECC */
-
- return NID_undef;
+ WOLFSSL_MSG("short name not found in table");
+ return WC_NID_undef;
}
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
#ifndef WOLFCRYPT_ONLY
+
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+/* The system wide crypto-policy. Configured by wolfSSL_crypto_policy_enable.
+ * */
+static struct SystemCryptoPolicy crypto_policy;
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
#if !defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC) || \
(defined(OPENSSL_EXTRA) && defined(WOLFSSL_KEY_GEN) && !defined(NO_DSA))
#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);
+#if defined(OPENSSL_EXTRA) || !defined(WOLFSSL_MUTEX_INITIALIZER)
+static WC_MAYBE_UNUSED wolfSSL_Mutex globalRNGMutex
+ WOLFSSL_MUTEX_INITIALIZER_CLAUSE(globalRNGMutex);
+#endif
#ifndef WOLFSSL_MUTEX_INITIALIZER
static int globalRNGMutex_valid = 0;
#endif
@@ -373,30 +299,36 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local);
WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local)
{
WC_RNG* ret = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ int freeRng = 0;
- /* Assume not local until one created. */
- *local = 0;
+ /* Allocate RNG object . */
+ if (rng == NULL) {
+ rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ freeRng = 1;
+ }
+#endif
+ if (rng != NULL) {
+ if (wc_InitRng(rng) == 0) {
+ ret = rng;
+ *local = 1;
+ }
+ else {
+ WOLFSSL_MSG("Bad RNG Init");
#ifdef WOLFSSL_SMALL_STACK
- /* Allocate RNG object . */
- rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
+ if (freeRng) {
+ XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+ rng = NULL;
+ }
#endif
- /* Check we have a local RNG object and initialize. */
- if ((rng != NULL) && (wc_InitRng(rng) == 0)) {
- ret = rng;
- *local = 1;
+ }
}
if (ret == NULL) {
- #ifdef HAVE_GLOBAL_RNG
- WOLFSSL_MSG("Bad RNG Init, trying global");
- #endif
- ret = wolfssl_make_global_rng();
- }
-
- if (ret != rng) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
+#ifdef HAVE_GLOBAL_RNG
+ WOLFSSL_MSG("trying global RNG");
#endif
+ ret = wolfssl_make_global_rng();
}
return ret;
@@ -408,7 +340,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
@@ -426,48 +359,50 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local)
#define WOLFSSL_PK_INCLUDED
#include "src/pk.c"
-#include
+#if defined(OPENSSL_EXTRA) || defined(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;
-#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
-const WOLF_EC_NIST_NAME kNistCurves[] = {
- {XSTR_SIZEOF("P-192"), "P-192", NID_X9_62_prime192v1},
- {XSTR_SIZEOF("P-256"), "P-256", NID_X9_62_prime256v1},
- {XSTR_SIZEOF("P-112"), "P-112", NID_secp112r1},
- {XSTR_SIZEOF("P-112-2"), "P-112-2", NID_secp112r2},
- {XSTR_SIZEOF("P-128"), "P-128", NID_secp128r1},
- {XSTR_SIZEOF("P-128-2"), "P-128-2", NID_secp128r2},
- {XSTR_SIZEOF("P-160"), "P-160", NID_secp160r1},
- {XSTR_SIZEOF("P-160-2"), "P-160-2", NID_secp160r2},
- {XSTR_SIZEOF("P-224"), "P-224", NID_secp224r1},
- {XSTR_SIZEOF("P-384"), "P-384", NID_secp384r1},
- {XSTR_SIZEOF("P-521"), "P-521", NID_secp521r1},
- {XSTR_SIZEOF("K-160"), "K-160", NID_secp160k1},
- {XSTR_SIZEOF("K-192"), "K-192", NID_secp192k1},
- {XSTR_SIZEOF("K-224"), "K-224", NID_secp224k1},
- {XSTR_SIZEOF("K-256"), "K-256", NID_secp256k1},
- {XSTR_SIZEOF("B-160"), "B-160", NID_brainpoolP160r1},
- {XSTR_SIZEOF("B-192"), "B-192", NID_brainpoolP192r1},
- {XSTR_SIZEOF("B-224"), "B-224", NID_brainpoolP224r1},
- {XSTR_SIZEOF("B-256"), "B-256", NID_brainpoolP256r1},
- {XSTR_SIZEOF("B-320"), "B-320", NID_brainpoolP320r1},
- {XSTR_SIZEOF("B-384"), "B-384", NID_brainpoolP384r1},
- {XSTR_SIZEOF("B-512"), "B-512", NID_brainpoolP512r1},
-#ifdef HAVE_PQC
- {XSTR_SIZEOF("KYBER_LEVEL1"), "KYBER_LEVEL1", WOLFSSL_KYBER_LEVEL1},
- {XSTR_SIZEOF("KYBER_LEVEL3"), "KYBER_LEVEL3", WOLFSSL_KYBER_LEVEL3},
- {XSTR_SIZEOF("KYBER_LEVEL5"), "KYBER_LEVEL5", WOLFSSL_KYBER_LEVEL5},
-#ifdef HAVE_LIBOQS
- {XSTR_SIZEOF("P256_KYBER_LEVEL1"), "P256_KYBER_LEVEL1", WOLFSSL_P256_KYBER_LEVEL1},
- {XSTR_SIZEOF("P384_KYBER_LEVEL3"), "P384_KYBER_LEVEL3", WOLFSSL_P384_KYBER_LEVEL3},
- {XSTR_SIZEOF("P521_KYBER_LEVEL5"), "P521_KYBER_LEVEL5", WOLFSSL_P521_KYBER_LEVEL5},
-#endif
-#endif
-#ifdef WOLFSSL_SM2
- {XSTR_SIZEOF("SM2"), "SM2", NID_sm2},
-#endif
- {0, NULL, 0},
-};
-#endif
+ *out = *in;
+}
+
+
+#if defined(OPENSSL_ALL)
+static WOLFSSL_X509_OBJECT* wolfSSL_X509_OBJECT_dup(WOLFSSL_X509_OBJECT* obj)
+{
+ WOLFSSL_X509_OBJECT* ret = NULL;
+ if (obj) {
+ ret = wolfSSL_X509_OBJECT_new();
+ if (ret) {
+ ret->type = obj->type;
+ switch (ret->type) {
+ case WOLFSSL_X509_LU_NONE:
+ break;
+ case WOLFSSL_X509_LU_X509:
+ ret->data.x509 = wolfSSL_X509_dup(obj->data.x509);
+ break;
+ case WOLFSSL_X509_LU_CRL:
+ #if defined(HAVE_CRL)
+ ret->data.crl = wolfSSL_X509_CRL_dup(obj->data.crl);
+ #endif
+ break;
+ }
+ }
+ }
+ return ret;
+}
+#endif /* OPENSSL_ALL */
+
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+#define WOLFSSL_SSL_SK_INCLUDED
+#include "src/ssl_sk.c"
+
+
+#include
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
/* create the hpke key and ech config to send to clients */
@@ -476,6 +411,8 @@ int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
{
int ret = 0;
word16 encLen = DHKEM_X25519_ENC_LEN;
+ WOLFSSL_EchConfig* newConfig;
+ WOLFSSL_EchConfig* parentConfig;
#ifdef WOLFSSL_SMALL_STACK
Hpke* hpke = NULL;
WC_RNG* rng;
@@ -487,29 +424,24 @@ int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
if (ctx == NULL || publicName == NULL)
return BAD_FUNC_ARG;
-#ifdef WOLFSSL_SMALL_STACK
- rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG);
- if (rng == NULL)
- return MEMORY_E;
-#endif
+ WC_ALLOC_VAR_EX(rng, WC_RNG, 1, ctx->heap, DYNAMIC_TYPE_RNG,
+ return MEMORY_E);
ret = wc_InitRng(rng);
if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG);
- #endif
+ WC_FREE_VAR_EX(rng, ctx->heap, DYNAMIC_TYPE_RNG);
return ret;
}
- ctx->echConfigs = (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
+ newConfig = (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ctx->echConfigs == NULL)
+ if (newConfig == NULL)
ret = MEMORY_E;
else
- XMEMSET(ctx->echConfigs, 0, sizeof(WOLFSSL_EchConfig));
+ XMEMSET(newConfig, 0, sizeof(WOLFSSL_EchConfig));
/* set random config id */
if (ret == 0)
- ret = wc_RNG_GenerateByte(rng, &ctx->echConfigs->configId);
+ ret = wc_RNG_GenerateByte(rng, &newConfig->configId);
/* if 0 is selected for algorithms use default, may change with draft */
if (kemId == 0)
@@ -523,19 +455,20 @@ int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
if (ret == 0) {
/* set the kem id */
- ctx->echConfigs->kemId = kemId;
+ newConfig->kemId = kemId;
/* set the cipher suite, only 1 for now */
- ctx->echConfigs->numCipherSuites = 1;
- ctx->echConfigs->cipherSuites = (EchCipherSuite*)XMALLOC(
- sizeof(EchCipherSuite), ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ newConfig->numCipherSuites = 1;
+ newConfig->cipherSuites =
+ (EchCipherSuite*)XMALLOC(sizeof(EchCipherSuite), ctx->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
- if (ctx->echConfigs->cipherSuites == NULL) {
+ if (newConfig->cipherSuites == NULL) {
ret = MEMORY_E;
}
else {
- ctx->echConfigs->cipherSuites[0].kdfId = kdfId;
- ctx->echConfigs->cipherSuites[0].aeadId = aeadId;
+ newConfig->cipherSuites[0].kdfId = kdfId;
+ newConfig->cipherSuites[0].aeadId = aeadId;
}
}
@@ -552,48 +485,108 @@ int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
/* generate the receiver private key */
if (ret == 0)
- ret = wc_HpkeGenerateKeyPair(hpke, &ctx->echConfigs->receiverPrivkey,
- rng);
+ ret = wc_HpkeGenerateKeyPair(hpke, &newConfig->receiverPrivkey, rng);
/* done with RNG */
wc_FreeRng(rng);
/* serialize the receiver key */
if (ret == 0)
- ret = wc_HpkeSerializePublicKey(hpke, ctx->echConfigs->receiverPrivkey,
- ctx->echConfigs->receiverPubkey, &encLen);
+ ret = wc_HpkeSerializePublicKey(hpke, newConfig->receiverPrivkey,
+ newConfig->receiverPubkey, &encLen);
if (ret == 0) {
- ctx->echConfigs->publicName = (char*)XMALLOC(XSTRLEN(publicName) + 1,
+ newConfig->publicName = (char*)XMALLOC(XSTRLEN(publicName) + 1,
ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (ctx->echConfigs->publicName == NULL) {
+ if (newConfig->publicName == NULL) {
ret = MEMORY_E;
}
else {
- XMEMCPY(ctx->echConfigs->publicName, publicName,
+ XMEMCPY(newConfig->publicName, publicName,
XSTRLEN(publicName) + 1);
}
}
if (ret != 0) {
- if (ctx->echConfigs) {
- XFREE(ctx->echConfigs->cipherSuites, ctx->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(ctx->echConfigs->publicName, ctx->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(ctx->echConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- /* set to null to avoid double free in cleanup */
- ctx->echConfigs = NULL;
+ if (newConfig) {
+ XFREE(newConfig->cipherSuites, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(newConfig->publicName, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(newConfig, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ }
+ else {
+ parentConfig = ctx->echConfigs;
+
+ if (parentConfig == NULL) {
+ ctx->echConfigs = newConfig;
+ }
+ else {
+ while (parentConfig->next != NULL) {
+ parentConfig = parentConfig->next;
+ }
+
+ parentConfig->next = newConfig;
}
}
if (ret == 0)
ret = WOLFSSL_SUCCESS;
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(hpke, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG);
-#endif
+ WC_FREE_VAR_EX(hpke, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WC_FREE_VAR_EX(rng, ctx->heap, DYNAMIC_TYPE_RNG);
+
+ return ret;
+}
+
+int wolfSSL_CTX_SetEchConfigsBase64(WOLFSSL_CTX* ctx, const char* echConfigs64,
+ word32 echConfigs64Len)
+{
+ int ret = 0;
+ word32 decodedLen = echConfigs64Len * 3 / 4 + 1;
+ byte* decodedConfigs;
+
+ if (ctx == NULL || echConfigs64 == NULL || echConfigs64Len == 0)
+ return BAD_FUNC_ARG;
+
+ decodedConfigs = (byte*)XMALLOC(decodedLen, ctx->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+
+ if (decodedConfigs == NULL)
+ return MEMORY_E;
+
+ decodedConfigs[decodedLen - 1] = 0;
+
+ /* decode the echConfigs */
+ ret = Base64_Decode((const byte*)echConfigs64, echConfigs64Len,
+ decodedConfigs, &decodedLen);
+
+ if (ret != 0) {
+ XFREE(decodedConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ ret = wolfSSL_CTX_SetEchConfigs(ctx, decodedConfigs, decodedLen);
+
+ XFREE(decodedConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
+
+int wolfSSL_CTX_SetEchConfigs(WOLFSSL_CTX* ctx, const byte* echConfigs,
+ word32 echConfigsLen)
+{
+ int ret;
+
+ if (ctx == NULL || echConfigs == NULL || echConfigsLen == 0)
+ return BAD_FUNC_ARG;
+
+ FreeEchConfigs(ctx->echConfigs, ctx->heap);
+ ctx->echConfigs = NULL;
+ ret = SetEchConfigsEx(&ctx->echConfigs, ctx->heap, echConfigs,
+ echConfigsLen);
+
+ if (ret == 0)
+ return WOLFSSL_SUCCESS;
return ret;
}
@@ -605,13 +598,24 @@ int wolfSSL_CTX_GetEchConfigs(WOLFSSL_CTX* ctx, byte* output,
return BAD_FUNC_ARG;
/* if we don't have ech configs */
- if (ctx->echConfigs == NULL) {
+ if (ctx->echConfigs == NULL)
return WOLFSSL_FATAL_ERROR;
- }
return GetEchConfigsEx(ctx->echConfigs, output, outputLen);
}
+void wolfSSL_CTX_SetEchEnable(WOLFSSL_CTX* ctx, byte enable)
+{
+ if (ctx != NULL) {
+ ctx->disableECH = !enable;
+ if (ctx->disableECH) {
+ TLSX_Remove(&ctx->extensions, TLSX_ECH, ctx->heap);
+ FreeEchConfigs(ctx->echConfigs, ctx->heap);
+ ctx->echConfigs = NULL;
+ }
+ }
+}
+
/* set the ech config from base64 for our client ssl object, base64 is the
* format ech configs are sent using dns records */
int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64,
@@ -656,21 +660,9 @@ int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64,
/* set the ech config from a raw buffer, this is the format ech configs are
* sent using retry_configs from the ech server */
int wolfSSL_SetEchConfigs(WOLFSSL* ssl, const byte* echConfigs,
- word32 echConfigsLen)
+ word32 echConfigsLen)
{
- int ret = 0;
- int i;
- int j;
- word16 totalLength;
- word16 version;
- word16 length;
- word16 hpkePubkeyLen;
- word16 cipherSuitesLen;
- word16 publicNameLen;
- WOLFSSL_EchConfig* configList = NULL;
- WOLFSSL_EchConfig* workingConfig = NULL;
- WOLFSSL_EchConfig* lastConfig = NULL;
- byte* echConfig = NULL;
+ int ret;
if (ssl == NULL || echConfigs == NULL || echConfigsLen == 0)
return BAD_FUNC_ARG;
@@ -680,203 +672,48 @@ int wolfSSL_SetEchConfigs(WOLFSSL* ssl, const byte* echConfigs,
return WOLFSSL_FATAL_ERROR;
}
- /* check that the total length is well formed */
- ato16(echConfigs, &totalLength);
+ ret = SetEchConfigsEx(&ssl->echConfigs, ssl->heap, echConfigs,
+ echConfigsLen);
- if (totalLength != echConfigsLen - 2) {
- return WOLFSSL_FATAL_ERROR;
+ /* if we found valid configs */
+ if (ret == 0) {
+ ssl->options.useEch = 1;
+ return WOLFSSL_SUCCESS;
}
- /* skip the total length uint16_t */
- i = 2;
+ return ret;
+}
- do {
- echConfig = (byte*)echConfigs + i;
- ato16(echConfig, &version);
- ato16(echConfig + 2, &length);
+/* get the raw ech config from our struct */
+int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
+{
+ int i;
+ word16 totalLen = 0;
- /* if the version does not match */
- if (version != TLSX_ECH) {
- /* we hit the end of the configs */
- if ( (word32)i + 2 >= echConfigsLen ) {
- break;
- }
+ if (config == NULL || (output == NULL && outputLen == NULL))
+ return BAD_FUNC_ARG;
- /* skip this config, +4 for version and length */
- i += length + 4;
- continue;
- }
+ /* 2 for version */
+ totalLen += 2;
+ /* 2 for length */
+ totalLen += 2;
+ /* 1 for configId */
+ totalLen += 1;
+ /* 2 for kemId */
+ totalLen += 2;
+ /* 2 for hpke_len */
+ totalLen += 2;
- /* check if the length will overrun the buffer */
- if ((word32)i + length + 4 > echConfigsLen) {
+ /* hpke_pub_key */
+ switch (config->kemId) {
+ case DHKEM_P256_HKDF_SHA256:
+ totalLen += DHKEM_P256_ENC_LEN;
break;
- }
-
- if (workingConfig == NULL) {
- workingConfig =
- (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
- ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- configList = workingConfig;
- if (workingConfig != NULL) {
- workingConfig->next = NULL;
- }
- }
- else {
- lastConfig = workingConfig;
- workingConfig->next =
- (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
- ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- workingConfig = workingConfig->next;
- }
-
- if (workingConfig == NULL) {
- ret = MEMORY_E;
+ case DHKEM_P384_HKDF_SHA384:
+ totalLen += DHKEM_P384_ENC_LEN;
break;
- }
-
- XMEMSET(workingConfig, 0, sizeof(WOLFSSL_EchConfig));
-
- /* rawLen */
- workingConfig->rawLen = length + 4;
-
- /* raw body */
- workingConfig->raw = (byte*)XMALLOC(workingConfig->rawLen,
- ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (workingConfig->raw == NULL) {
- ret = MEMORY_E;
- break;
- }
-
- XMEMCPY(workingConfig->raw, echConfig, workingConfig->rawLen);
-
- /* skip over version and length */
- echConfig += 4;
-
- /* configId, 1 byte */
- workingConfig->configId = *(echConfig);
- echConfig++;
- /* kemId, 2 bytes */
- ato16(echConfig, &workingConfig->kemId);
- echConfig += 2;
- /* hpke public_key length, 2 bytes */
- ato16(echConfig, &hpkePubkeyLen);
- echConfig += 2;
- /* hpke public_key */
- XMEMCPY(workingConfig->receiverPubkey, echConfig, hpkePubkeyLen);
- echConfig += hpkePubkeyLen;
- /* cipherSuitesLen */
- ato16(echConfig, &cipherSuitesLen);
-
- workingConfig->cipherSuites = (EchCipherSuite*)XMALLOC(cipherSuitesLen,
- ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (workingConfig->cipherSuites == NULL) {
- ret = MEMORY_E;
- break;
- }
-
- echConfig += 2;
- workingConfig->numCipherSuites = cipherSuitesLen / 4;
- /* cipherSuites */
- for (j = 0; j < workingConfig->numCipherSuites; j++) {
- ato16(echConfig + j * 4, &workingConfig->cipherSuites[j].kdfId);
- ato16(echConfig + j * 4 + 2,
- &workingConfig->cipherSuites[j].aeadId);
- }
- echConfig += cipherSuitesLen;
- /* publicNameLen */
- ato16(echConfig, &publicNameLen);
- workingConfig->publicName = (char*)XMALLOC(publicNameLen + 1,
- ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (workingConfig->publicName == NULL) {
- ret = MEMORY_E;
- break;
- }
-
- echConfig += 2;
- /* publicName */
- XMEMCPY(workingConfig->publicName, echConfig, publicNameLen);
- /* null terminated */
- workingConfig->publicName[publicNameLen] = 0;
-
- /* add length to go to next config, +4 for version and length */
- i += length + 4;
-
- /* check that we support this config */
- for (j = 0; j < HPKE_SUPPORTED_KEM_LEN; j++) {
- if (hpkeSupportedKem[j] == workingConfig->kemId)
- break;
- }
-
- /* if we don't support the kem or at least one cipher suite */
- if (j >= HPKE_SUPPORTED_KEM_LEN ||
- EchConfigGetSupportedCipherSuite(workingConfig) < 0)
- {
- XFREE(workingConfig->cipherSuites, ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(workingConfig->publicName, ssl->heap,
- DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(workingConfig->raw, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- workingConfig = lastConfig;
- }
- } while ((word32)i < echConfigsLen);
-
- /* if we found valid configs */
- if (ret == 0 && configList != NULL) {
- ssl->options.useEch = 1;
- ssl->echConfigs = configList;
-
- return WOLFSSL_SUCCESS;
- }
-
- workingConfig = configList;
-
- while (workingConfig != NULL) {
- lastConfig = workingConfig;
- workingConfig = workingConfig->next;
-
- XFREE(lastConfig->cipherSuites, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(lastConfig->publicName, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(lastConfig->raw, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
-
- XFREE(lastConfig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- }
-
- if (ret == 0)
- return WOLFSSL_FATAL_ERROR;
-
- return ret;
-}
-
-/* get the raw ech config from our struct */
-int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
-{
- int i;
- word16 totalLen = 0;
-
- if (config == NULL || (output == NULL && outputLen == NULL))
- return BAD_FUNC_ARG;
-
- /* 2 for version */
- totalLen += 2;
- /* 2 for length */
- totalLen += 2;
- /* 1 for configId */
- totalLen += 1;
- /* 2 for kemId */
- totalLen += 2;
- /* 2 for hpke_len */
- totalLen += 2;
-
- /* hpke_pub_key */
- switch (config->kemId) {
- case DHKEM_P256_HKDF_SHA256:
- totalLen += DHKEM_P256_ENC_LEN;
- break;
- case DHKEM_P384_HKDF_SHA384:
- totalLen += DHKEM_P384_ENC_LEN;
- break;
- case DHKEM_P521_HKDF_SHA512:
- totalLen += DHKEM_P521_ENC_LEN;
+ case DHKEM_P521_HKDF_SHA512:
+ totalLen += DHKEM_P521_ENC_LEN;
break;
case DHKEM_X25519_HKDF_SHA256:
totalLen += DHKEM_X25519_ENC_LEN;
@@ -900,7 +737,7 @@ int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
if (output == NULL) {
*outputLen = totalLen;
- return LENGTH_ONLY_E;
+ return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
}
if (totalLen > *outputLen) {
@@ -969,9 +806,13 @@ int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
output += 2;
}
+ /* set maximum name length to 0 */
+ *output = 0;
+ output++;
+
/* publicName len */
- c16toa(XSTRLEN(config->publicName), output);
- output += 2;
+ *output = XSTRLEN(config->publicName);
+ output++;
/* publicName */
XMEMCPY(output, config->publicName,
@@ -1001,277 +842,293 @@ int wolfSSL_GetEchConfigs(WOLFSSL* ssl, byte* output, word32* outputLen)
return GetEchConfigsEx(ssl->echConfigs, output, outputLen);
}
-/* get the raw ech configs from our linked list of ech config structs */
-int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen)
+void wolfSSL_SetEchEnable(WOLFSSL* ssl, byte enable)
+{
+ if (ssl != NULL) {
+ ssl->options.disableECH = !enable;
+ if (ssl->options.disableECH) {
+ TLSX_Remove(&ssl->extensions, TLSX_ECH, ssl->heap);
+ FreeEchConfigs(ssl->echConfigs, ssl->heap);
+ ssl->echConfigs = NULL;
+ }
+ }
+}
+
+int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap,
+ const byte* echConfigs, word32 echConfigsLen)
{
int ret = 0;
+ int i;
+ int j;
+ word16 totalLength;
+ word16 version;
+ word16 length;
+ word16 hpkePubkeyLen;
+ word16 cipherSuitesLen;
+ word16 publicNameLen;
+ WOLFSSL_EchConfig* configList = NULL;
WOLFSSL_EchConfig* workingConfig = NULL;
- byte* outputStart = output;
- word32 totalLen = 2;
- word32 workingOutputLen;
+ WOLFSSL_EchConfig* lastConfig = NULL;
+ byte* echConfig = NULL;
- if (configs == NULL || outputLen == NULL)
+ if (outputConfigs == NULL || echConfigs == NULL || echConfigsLen == 0)
return BAD_FUNC_ARG;
- workingOutputLen = *outputLen - totalLen;
+ /* check that the total length is well formed */
+ ato16(echConfigs, &totalLength);
- /* skip over total length which we fill in later */
- if (output != NULL)
- output += 2;
+ if (totalLength != echConfigsLen - 2) {
+ return WOLFSSL_FATAL_ERROR;
+ }
- workingConfig = configs;
+ /* skip the total length uint16_t */
+ i = 2;
- while (workingConfig != NULL) {
- /* get this config */
- ret = GetEchConfig(workingConfig, output, &workingOutputLen);
+ do {
+ echConfig = (byte*)echConfigs + i;
+ ato16(echConfig, &version);
+ ato16(echConfig + 2, &length);
- if (output != NULL)
- output += workingOutputLen;
+ /* if the version does not match */
+ if (version != TLSX_ECH) {
+ /* we hit the end of the configs */
+ if ( (word32)i + 2 >= echConfigsLen ) {
+ break;
+ }
- /* add this config's length to the total length */
- totalLen += workingOutputLen;
+ /* skip this config, +4 for version and length */
+ i += length + 4;
+ continue;
+ }
- if (totalLen > *outputLen)
- workingOutputLen = 0;
- else
- workingOutputLen = *outputLen - totalLen;
+ /* check if the length will overrun the buffer */
+ if ((word32)i + length + 4 > echConfigsLen) {
+ break;
+ }
- /* only error we break on, other 2 we need to keep finding length */
- if (ret == BAD_FUNC_ARG)
- return BAD_FUNC_ARG;
+ if (workingConfig == NULL) {
+ workingConfig =
+ (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig), heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ configList = workingConfig;
+ if (workingConfig != NULL) {
+ workingConfig->next = NULL;
+ }
+ }
+ else {
+ lastConfig = workingConfig;
+ workingConfig->next =
+ (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
+ heap, DYNAMIC_TYPE_TMP_BUFFER);
+ workingConfig = workingConfig->next;
+ }
- workingConfig = workingConfig->next;
- }
+ if (workingConfig == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
- if (output == NULL) {
- *outputLen = totalLen;
- return LENGTH_ONLY_E;
- }
+ XMEMSET(workingConfig, 0, sizeof(WOLFSSL_EchConfig));
- if (totalLen > *outputLen) {
- *outputLen = totalLen;
- return INPUT_SIZE_E;
- }
+ /* rawLen */
+ workingConfig->rawLen = length + 4;
- /* total size -2 for size itself */
- c16toa(totalLen - 2, outputStart);
+ /* raw body */
+ workingConfig->raw = (byte*)XMALLOC(workingConfig->rawLen,
+ heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (workingConfig->raw == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
- *outputLen = totalLen;
+ XMEMCPY(workingConfig->raw, echConfig, workingConfig->rawLen);
- return WOLFSSL_SUCCESS;
-}
-#endif /* WOLFSSL_TLS13 && HAVE_ECH */
+ /* skip over version and length */
+ echConfig += 4;
+ /* configId, 1 byte */
+ workingConfig->configId = *(echConfig);
+ echConfig++;
+ /* kemId, 2 bytes */
+ ato16(echConfig, &workingConfig->kemId);
+ echConfig += 2;
+ /* hpke public_key length, 2 bytes */
+ ato16(echConfig, &hpkePubkeyLen);
+ echConfig += 2;
+ /* hpke public_key */
+ XMEMCPY(workingConfig->receiverPubkey, echConfig, hpkePubkeyLen);
+ echConfig += hpkePubkeyLen;
+ /* cipherSuitesLen */
+ ato16(echConfig, &cipherSuitesLen);
-#if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS)
-#include
-#endif
+ workingConfig->cipherSuites = (EchCipherSuite*)XMALLOC(cipherSuitesLen,
+ heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (workingConfig->cipherSuites == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
-#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;
- }
+ echConfig += 2;
+ workingConfig->numCipherSuites = cipherSuitesLen / 4;
+ /* cipherSuites */
+ for (j = 0; j < workingConfig->numCipherSuites; j++) {
+ ato16(echConfig + j * 4, &workingConfig->cipherSuites[j].kdfId);
+ ato16(echConfig + j * 4 + 2,
+ &workingConfig->cipherSuites[j].aeadId);
+ }
+ echConfig += cipherSuitesLen;
+ /* ignore the maximum name length */
+ echConfig++;
+ /* publicNameLen */
+ publicNameLen = *(echConfig);
+ workingConfig->publicName = (char*)XMALLOC(publicNameLen + 1,
+ heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (workingConfig->publicName == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
+ echConfig++;
+ /* publicName */
+ XMEMCPY(workingConfig->publicName, echConfig, publicNameLen);
+ /* null terminated */
+ workingConfig->publicName[publicNameLen] = 0;
- /* sanity checks on buffer and protocol are done in internal function */
- return wolfSSL_session_import_internal(ssl, buf, sz, WOLFSSL_EXPORT_DTLS);
-}
+ /* add length to go to next config, +4 for version and length */
+ i += length + 4;
+ /* check that we support this config */
+ for (j = 0; j < HPKE_SUPPORTED_KEM_LEN; j++) {
+ if (hpkeSupportedKem[j] == workingConfig->kemId)
+ break;
+ }
-/* 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)
-{
+ /* if we don't support the kem or at least one cipher suite */
+ if (j >= HPKE_SUPPORTED_KEM_LEN ||
+ EchConfigGetSupportedCipherSuite(workingConfig) < 0)
+ {
+ XFREE(workingConfig->cipherSuites, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(workingConfig->publicName, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(workingConfig->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ workingConfig = lastConfig;
+ }
+ } while ((word32)i < echConfigsLen);
- WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export");
+ /* if we found valid configs */
+ if (ret == 0 && configList != NULL) {
+ *outputConfigs = configList;
- /* purposefully allow func to be NULL */
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
+ return ret;
}
- ctx->dtls_export = func;
-
- return WOLFSSL_SUCCESS;
-}
-
+ workingConfig = configList;
-/* 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)
-{
+ while (workingConfig != NULL) {
+ lastConfig = workingConfig;
+ workingConfig = workingConfig->next;
- WOLFSSL_ENTER("wolfSSL_dtls_set_export");
+ XFREE(lastConfig->cipherSuites, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(lastConfig->publicName, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(lastConfig->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
- /* purposefully allow func to be NULL */
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
+ XFREE(lastConfig, heap, DYNAMIC_TYPE_TMP_BUFFER);
}
- ssl->dtls_export = func;
+ if (ret == 0)
+ return WOLFSSL_FATAL_ERROR;
- return WOLFSSL_SUCCESS;
+ return ret;
}
-
-/* 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)
+/* get the raw ech configs from our linked list of ech config structs */
+int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen)
{
- WOLFSSL_ENTER("wolfSSL_dtls_export");
+ int ret = 0;
+ WOLFSSL_EchConfig* workingConfig = NULL;
+ byte* outputStart = output;
+ word32 totalLen = 2;
+ word32 workingOutputLen = 0;
- if (ssl == NULL || sz == NULL) {
+ if (configs == NULL || outputLen == NULL ||
+ (output != NULL && *outputLen < totalLen)) {
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;
+ /* skip over total length which we fill in later */
+ if (output != NULL) {
+ workingOutputLen = *outputLen - totalLen;
+ output += 2;
}
-
- /* 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;
+ else {
+ /* caller getting the size only, set current 2 byte length size */
+ *outputLen = totalLen;
}
- if (buf == NULL) {
- *sz = MAX_EXPORT_STATE_BUFFER;
- return 0;
- }
+ workingConfig = configs;
- /* if not DTLS do nothing */
- if (!ssl->options.dtls) {
- WOLFSSL_MSG("Currently only DTLS export state is supported");
- return 0;
- }
+ while (workingConfig != NULL) {
+ /* get this config */
+ ret = GetEchConfig(workingConfig, output, &workingOutputLen);
- /* copy over keys, options, and dtls state struct */
- return wolfSSL_dtls_export_state_internal(ssl, buf, *sz);
-}
+ if (output != NULL)
+ output += workingOutputLen;
+ /* add this config's length to the total length */
+ totalLen += workingOutputLen;
-/* returns 0 on success */
-int wolfSSL_send_session(WOLFSSL* ssl)
-{
- int ret;
- byte* buf;
- word32 bufSz = MAX_EXPORT_BUFFER;
+ if (totalLen > *outputLen)
+ workingOutputLen = 0;
+ else
+ workingOutputLen = *outputLen - totalLen;
- WOLFSSL_ENTER("wolfSSL_send_session");
+ /* only error we break on, other 2 we need to keep finding length */
+ if (ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG))
+ return BAD_FUNC_ARG;
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
+ workingConfig = workingConfig->next;
}
- buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (buf == NULL) {
- return MEMORY_E;
+ if (output == NULL) {
+ *outputLen = totalLen;
+ return WC_NO_ERR_TRACE(LENGTH_ONLY_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;
+ if (totalLen > *outputLen) {
+ *outputLen = totalLen;
+ return INPUT_SIZE_E;
}
- /* 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;
- }
+ /* total size -2 for size itself */
+ c16toa(totalLen - 2, outputStart);
- /* 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;
- }
+ *outputLen = totalLen;
- XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return 0;
+ return WOLFSSL_SUCCESS;
}
-#endif /* WOLFSSL_DTLS */
-#endif /* WOLFSSL_SESSION_EXPORT */
+#endif /* WOLFSSL_TLS13 && HAVE_ECH */
+
+#ifdef OPENSSL_EXTRA
+static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
+ Suites* suites, const char* list);
+#endif
+
+#if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS)
+#include
+#endif
/* 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 */
+static volatile WC_THREADSHARED int initRefCount = 0;
+/* init ref count mutex */
+static WC_THREADSHARED 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;
+static WC_THREADSHARED volatile int inits_count_mutex_valid = 0;
+#endif
+
+#ifdef NO_TLS
+static const WOLFSSL_METHOD gNoTlsMethod;
#endif
/* Create a new WOLFSSL_CTX struct and return the pointer to created struct.
@@ -1291,15 +1148,18 @@ WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap)
if (ret != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("wolfSSL_Init failed");
WOLFSSL_LEAVE("wolfSSL_CTX_new_ex", 0);
- if (method != NULL) {
- XFREE(method, heap, DYNAMIC_TYPE_METHOD);
- }
+ XFREE(method, heap, DYNAMIC_TYPE_METHOD);
return NULL;
}
}
+#ifndef NO_TLS
if (method == NULL)
return ctx;
+#else
+ /* a blank TLS method */
+ method = (WOLFSSL_METHOD*)&gNoTlsMethod;
+#endif
ctx = (WOLFSSL_CTX*)XMALLOC(sizeof(WOLFSSL_CTX), heap, DYNAMIC_TYPE_CTX);
if (ctx) {
@@ -1336,11 +1196,11 @@ WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap)
#ifdef OPENSSL_COMPATIBLE_DEFAULTS
if (ctx) {
- wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
- wolfSSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL);
+ wolfSSL_CTX_set_mode(ctx, WOLFSSL_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
@@ -1352,6 +1212,30 @@ WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap)
}
#endif
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ /* Load the crypto-policy ciphers if configured. */
+ if (ctx && wolfSSL_crypto_policy_is_enabled()) {
+ const char * list = wolfSSL_crypto_policy_get_ciphers();
+ int ret = 0;
+
+ if (list != NULL && *list != '\0') {
+ if (AllocateCtxSuites(ctx) != 0) {
+ WOLFSSL_MSG("allocate ctx suites failed");
+ wolfSSL_CTX_free(ctx);
+ ctx = NULL;
+ }
+ else {
+ ret = wolfSSL_parse_cipher_list(ctx, NULL, ctx->suites, list);
+ if (ret != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("parse cipher list failed");
+ wolfSSL_CTX_free(ctx);
+ ctx = NULL;
+ }
+ }
+ }
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
WOLFSSL_LEAVE("wolfSSL_CTX_new_ex", 0);
return ctx;
}
@@ -1372,7 +1256,7 @@ WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method)
int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx)
{
int ret;
- wolfSSL_RefInc(&ctx->ref, &ret);
+ wolfSSL_RefWithMutexInc(&ctx->ref, &ret);
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
return ((ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE);
#else
@@ -1386,18 +1270,6 @@ void wolfSSL_CTX_free(WOLFSSL_CTX* ctx)
{
WOLFSSL_ENTER("wolfSSL_CTX_free");
if (ctx) {
-#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
-&& !defined(NO_SHA256) && !defined(WC_NO_RNG)
- if (ctx->srp != NULL) {
- if (ctx->srp_password != NULL){
- XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
- ctx->srp_password = NULL;
- }
- wc_SrpTerm(ctx->srp);
- XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
- ctx->srp = NULL;
- }
-#endif
FreeSSL_Ctx(ctx);
}
@@ -1517,7 +1389,7 @@ void wolfSSL_free(WOLFSSL* ssl)
WOLFSSL_ENTER("wolfSSL_free");
if (ssl) {
- WOLFSSL_MSG_EX("Free SSL: %p", (uintptr_t)ssl);
+ WOLFSSL_MSG_EX("Free SSL: %p", (wc_ptr_t)ssl);
FreeSSL(ssl, ssl->ctx->heap);
}
else {
@@ -1610,8 +1482,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;
@@ -1883,7 +1755,7 @@ int wolfSSL_get_ciphers(char* buf, int len)
for (i = 0; i < ciphersSz; i++) {
int cipherNameSz = (int)XSTRLEN(ciphers[i].name);
if (cipherNameSz + 1 < len) {
- XSTRNCPY(buf, ciphers[i].name, len);
+ XSTRNCPY(buf, ciphers[i].name, (size_t)len);
buf += cipherNameSz;
if (i < ciphersSz - 1)
@@ -1920,7 +1792,7 @@ int wolfSSL_get_ciphers_iana(char* buf, int len)
#endif
cipherNameSz = (int)XSTRLEN(ciphers[i].name_iana);
if (cipherNameSz + 1 < len) {
- XSTRNCPY(buf, ciphers[i].name_iana, len);
+ XSTRNCPY(buf, ciphers[i].name_iana, (size_t)len);
buf += cipherNameSz;
if (i < ciphersSz - 1)
@@ -1945,8 +1817,8 @@ const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len)
return NULL;
cipher = wolfSSL_get_cipher_name_iana(ssl);
- len = min(len, (int)(XSTRLEN(cipher) + 1));
- XMEMCPY(buf, cipher, len);
+ len = (int)min((word32)len, (word32)(XSTRLEN(cipher) + 1));
+ XMEMCPY(buf, cipher, (size_t)len);
return buf;
}
@@ -1961,6 +1833,17 @@ int wolfSSL_get_fd(const WOLFSSL* ssl)
return fd;
}
+int wolfSSL_get_wfd(const WOLFSSL* ssl)
+{
+ int fd = -1;
+ WOLFSSL_ENTER("wolfSSL_get_fd");
+ if (ssl) {
+ fd = ssl->wfd;
+ }
+ WOLFSSL_LEAVE("wolfSSL_get_fd", fd);
+ return fd;
+}
+
int wolfSSL_dtls(WOLFSSL* ssl)
{
@@ -1983,7 +1866,7 @@ int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
- if (ctx->method->side == WOLFSSL_CLIENT_END)
+ if (ctx->method->side != WOLFSSL_SERVER_END)
return SIDE_ERROR;
ctx->mutualAuth = (byte)req;
@@ -1996,14 +1879,14 @@ int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req)
*
* ssl The SSL/TLS object.
* req 1 to indicate required and 0 when not.
- * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3,
- * SIDE_ERROR when not a client and 0 on success.
+ * returns BAD_FUNC_ARG when ssl is NULL and
+ * SIDE_ERROR when not a server and 0 on success.
*/
int wolfSSL_mutual_auth(WOLFSSL* ssl, int req)
{
if (ssl == NULL)
return BAD_FUNC_ARG;
- if (ssl->options.side == WOLFSSL_SERVER_END)
+ if (ssl->options.side != WOLFSSL_SERVER_END)
return SIDE_ERROR;
ssl->options.mutualAuth = (word16)req;
@@ -2093,38 +1976,105 @@ int wolfSSL_dtls_free_peer(void* addr)
}
#endif
+#ifdef WOLFSSL_DTLS
+static int SockAddrSet(WOLFSSL_SOCKADDR* sockAddr, void* peer,
+ unsigned int peerSz, void* heap)
+{
+ if (peer == NULL || peerSz == 0) {
+ if (sockAddr->sa != NULL)
+ XFREE(sockAddr->sa, heap, DYNAMIC_TYPE_SOCKADDR);
+ sockAddr->sa = NULL;
+ sockAddr->sz = 0;
+ sockAddr->bufSz = 0;
+ return WOLFSSL_SUCCESS;
+ }
+
+ if (peerSz > sockAddr->bufSz) {
+ if (sockAddr->sa != NULL)
+ XFREE(sockAddr->sa, heap, DYNAMIC_TYPE_SOCKADDR);
+ sockAddr->sa =
+ (void*)XMALLOC(peerSz, heap, DYNAMIC_TYPE_SOCKADDR);
+ if (sockAddr->sa == NULL) {
+ sockAddr->sz = 0;
+ sockAddr->bufSz = 0;
+ return WOLFSSL_FAILURE;
+ }
+ sockAddr->bufSz = peerSz;
+ }
+ XMEMCPY(sockAddr->sa, peer, peerSz);
+ sockAddr->sz = peerSz;
+ return WOLFSSL_SUCCESS;
+}
+#endif
+
int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
{
#ifdef WOLFSSL_DTLS
- void* sa;
+ int ret;
if (ssl == NULL)
return WOLFSSL_FAILURE;
-
- if (peer == NULL || peerSz == 0) {
- if (ssl->buffers.dtlsCtx.peer.sa != NULL)
- XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
- ssl->buffers.dtlsCtx.peer.sa = NULL;
- ssl->buffers.dtlsCtx.peer.sz = 0;
- ssl->buffers.dtlsCtx.peer.bufSz = 0;
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_LockRwLock_Wr(&ssl->buffers.dtlsCtx.peerLock) != 0)
+ return WOLFSSL_FAILURE;
+#endif
+ ret = SockAddrSet(&ssl->buffers.dtlsCtx.peer, peer, peerSz, ssl->heap);
+ if (ret == WOLFSSL_SUCCESS && !(peer == NULL || peerSz == 0))
+ ssl->buffers.dtlsCtx.userSet = 1;
+ else
ssl->buffers.dtlsCtx.userSet = 0;
- return WOLFSSL_SUCCESS;
- }
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
+ ret = WOLFSSL_FAILURE;
+#endif
+ return ret;
+#else
+ (void)ssl;
+ (void)peer;
+ (void)peerSz;
+ return WOLFSSL_NOT_IMPLEMENTED;
+#endif
+}
- sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
- if (sa != NULL) {
- if (ssl->buffers.dtlsCtx.peer.sa != NULL) {
- XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
- ssl->buffers.dtlsCtx.peer.sa = NULL;
+#if defined(WOLFSSL_DTLS_CID) && !defined(WOLFSSL_NO_SOCK)
+int wolfSSL_dtls_set_pending_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
+{
+#ifdef WOLFSSL_DTLS
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
+ return WOLFSSL_FAILURE;
+#endif
+ if (ssl->buffers.dtlsCtx.peer.sa != NULL &&
+ ssl->buffers.dtlsCtx.peer.sz == peerSz &&
+ sockAddrEqual((SOCKADDR_S*)ssl->buffers.dtlsCtx.peer.sa,
+ (XSOCKLENT)ssl->buffers.dtlsCtx.peer.sz, (SOCKADDR_S*)peer,
+ (XSOCKLENT)peerSz)) {
+ /* Already the current peer. */
+ if (ssl->buffers.dtlsCtx.pendingPeer.sa != NULL) {
+ /* Clear any other pendingPeer */
+ XFREE(ssl->buffers.dtlsCtx.pendingPeer.sa, ssl->heap,
+ DYNAMIC_TYPE_SOCKADDR);
+ ssl->buffers.dtlsCtx.pendingPeer.sa = NULL;
+ ssl->buffers.dtlsCtx.pendingPeer.sz = 0;
+ ssl->buffers.dtlsCtx.pendingPeer.bufSz = 0;
}
- XMEMCPY(sa, peer, peerSz);
- ssl->buffers.dtlsCtx.peer.sa = sa;
- ssl->buffers.dtlsCtx.peer.sz = peerSz;
- ssl->buffers.dtlsCtx.peer.bufSz = peerSz;
- ssl->buffers.dtlsCtx.userSet = 1;
- return WOLFSSL_SUCCESS;
+ ret = WOLFSSL_SUCCESS;
}
- return WOLFSSL_FAILURE;
+ else {
+ ret = SockAddrSet(&ssl->buffers.dtlsCtx.pendingPeer, peer, peerSz,
+ ssl->heap);
+ }
+ if (ret == WOLFSSL_SUCCESS)
+ ssl->buffers.dtlsCtx.processingPendingRecord = 0;
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
+ ret = WOLFSSL_FAILURE;
+#endif
+ return ret;
#else
(void)ssl;
(void)peer;
@@ -2132,22 +2082,30 @@ int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
return WOLFSSL_NOT_IMPLEMENTED;
#endif
}
+#endif /* WOLFSSL_DTLS_CID && !WOLFSSL_NO_SOCK */
int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz)
{
#ifdef WOLFSSL_DTLS
- if (ssl == NULL) {
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ if (ssl == NULL)
return WOLFSSL_FAILURE;
- }
-
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
+ return WOLFSSL_FAILURE;
+#endif
if (peer != NULL && peerSz != NULL
&& *peerSz >= ssl->buffers.dtlsCtx.peer.sz
&& ssl->buffers.dtlsCtx.peer.sa != NULL) {
*peerSz = ssl->buffers.dtlsCtx.peer.sz;
XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz);
- return WOLFSSL_SUCCESS;
+ ret = WOLFSSL_SUCCESS;
}
- return WOLFSSL_FAILURE;
+#ifdef WOLFSSL_RW_THREADED
+ if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
+ ret = WOLFSSL_FAILURE;
+#endif
+ return ret;
#else
(void)ssl;
(void)peer;
@@ -2156,17 +2114,38 @@ int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz)
#endif
}
-
-#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
-
-int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx)
+int wolfSSL_dtls_get0_peer(WOLFSSL* ssl, const void** peer,
+ unsigned int* peerSz)
{
- WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp");
+#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_RW_THREADED)
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
- if (ctx == NULL)
- return BAD_FUNC_ARG;
+ if (peer == NULL || peerSz == NULL)
+ return WOLFSSL_FAILURE;
- ctx->dtlsSctp = 1;
+ *peer = ssl->buffers.dtlsCtx.peer.sa;
+ *peerSz = ssl->buffers.dtlsCtx.peer.sz;
+ return WOLFSSL_SUCCESS;
+#else
+ (void)ssl;
+ (void)peer;
+ (void)peerSz;
+ return WOLFSSL_NOT_IMPLEMENTED;
+#endif
+}
+
+
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+
+int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp");
+
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ ctx->dtlsSctp = 1;
return WOLFSSL_SUCCESS;
}
@@ -2211,6 +2190,18 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu)
return WOLFSSL_SUCCESS;
}
+#ifdef OPENSSL_EXTRA
+/* Maps to compatibility API SSL_set_mtu and is same as wolfSSL_dtls_set_mtu,
+ * but expects only success or failure returns. */
+int wolfSSL_set_mtu_compat(WOLFSSL* ssl, unsigned short mtu)
+{
+ if (wolfSSL_dtls_set_mtu(ssl, mtu) == WOLFSSL_SUCCESS)
+ return WOLFSSL_SUCCESS;
+ else
+ return WOLFSSL_FAILURE;
+}
+#endif /* OPENSSL_EXTRA */
+
#endif /* WOLFSSL_DTLS && (WOLFSSL_SCTP || WOLFSSL_DTLS_MTU) */
#ifdef WOLFSSL_SRTP
@@ -2218,10 +2209,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 */
@@ -2294,20 +2287,53 @@ static int DtlsSrtpSelProfiles(word16* id, const char* profile_str)
return WOLFSSL_SUCCESS;
}
+/**
+ * @brief Set the SRTP protection profiles for DTLS.
+ *
+ * @param ctx Pointer to the WOLFSSL_CTX structure representing the SSL/TLS
+ * context.
+ * @param profile_str A colon-separated string of SRTP profile names.
+ * @return 0 on success to match OpenSSL
+ * @return 1 on error to match OpenSSL
+ */
int wolfSSL_CTX_set_tlsext_use_srtp(WOLFSSL_CTX* ctx, const char* profile_str)
{
- int ret = WOLFSSL_FAILURE;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
if (ctx != NULL) {
ret = DtlsSrtpSelProfiles(&ctx->dtlsSrtpProfiles, profile_str);
}
+
+ if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+
return ret;
}
+
+/**
+ * @brief Set the SRTP protection profiles for DTLS.
+ *
+ * @param ssl Pointer to the WOLFSSL structure representing the SSL/TLS
+ * session.
+ * @param profile_str A colon-separated string of SRTP profile names.
+ * @return 0 on success to match OpenSSL
+ * @return 1 on error to match OpenSSL
+ */
int wolfSSL_set_tlsext_use_srtp(WOLFSSL* ssl, const char* profile_str)
{
- int ret = WOLFSSL_FAILURE;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
if (ssl != NULL) {
ret = DtlsSrtpSelProfiles(&ssl->dtlsSrtpProfiles, profile_str);
}
+
+ if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+
return ret;
}
@@ -2348,15 +2374,15 @@ int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl,
return EXT_MISSING;
}
if (out == NULL) {
- *olen = profile->kdfBits;
- return LENGTH_ONLY_E;
+ *olen = (size_t)profile->kdfBits;
+ return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
}
if (*olen < (size_t)profile->kdfBits) {
return BUFFER_E;
}
- return wolfSSL_export_keying_material(ssl, out, profile->kdfBits,
+ return wolfSSL_export_keying_material(ssl, out, (size_t)profile->kdfBits,
DTLS_SRTP_KEYING_MATERIAL_LABEL,
XSTR_SIZEOF(DTLS_SRTP_KEYING_MATERIAL_LABEL), NULL, 0, 0);
}
@@ -2398,7 +2424,7 @@ int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id)
WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id");
- if (ctx == NULL || id > 255)
+ if (ctx == NULL || id > WOLFSSL_MAX_8BIT)
ret = BAD_FUNC_ARG;
if (ret == 0) {
@@ -2465,7 +2491,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);
@@ -2532,7 +2559,7 @@ int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int sub)
int i;
WOLFSSL_ENTER("wolfSSL_mcast_peer_add");
- if (ssl == NULL || peerId > 255)
+ if (ssl == NULL || peerId > WOLFSSL_MAX_8BIT)
return BAD_FUNC_ARG;
if (!sub) {
@@ -2557,7 +2584,7 @@ int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int sub)
}
else {
WOLFSSL_MSG("No room in peer list.");
- ret = -1;
+ ret = WOLFSSL_FATAL_ERROR;
}
}
else {
@@ -2588,7 +2615,7 @@ int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId)
WOLFSSL_ENTER("wolfSSL_mcast_peer_known");
- if (ssl == NULL || peerId > 255) {
+ if (ssl == NULL || peerId > WOLFSSL_MAX_8BIT) {
return BAD_FUNC_ARG;
}
@@ -2644,11 +2671,11 @@ int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx)
#endif /* WOLFSSL_LEANPSK */
-
+#ifndef NO_TLS
/* return underlying connect or accept, WOLFSSL_SUCCESS on ok */
int wolfSSL_negotiate(WOLFSSL* ssl)
{
- int err = WOLFSSL_FATAL_ERROR;
+ int err = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
WOLFSSL_ENTER("wolfSSL_negotiate");
@@ -2683,7 +2710,7 @@ int wolfSSL_negotiate(WOLFSSL* ssl)
return err;
}
-
+#endif /* !NO_TLS */
WOLFSSL_ABI
WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl)
@@ -2716,7 +2743,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 +2777,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 +2803,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 +2817,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 +2841,6 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method
}
}
- /* determine what max applies too */
- if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) {
- heap->maxIO = maxSz;
- }
- else { /* general memory used in handshakes */
- heap->maxHa = maxSz;
- }
-
- heap->flag |= flag;
-
- (void)maxSz;
- (void)method;
-
return WOLFSSL_SUCCESS;
}
@@ -2855,6 +2852,7 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats)
}
WOLFSSL_ENTER("wolfSSL_is_static_memory");
+#ifndef WOLFSSL_STATIC_MEMORY_LEAN
/* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */
if (mem_stats != NULL && ssl->heap != NULL) {
WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap));
@@ -2863,7 +2861,9 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats)
XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS));
}
}
+#endif
+ (void)mem_stats;
return (ssl->heap) ? 1 : 0;
}
@@ -2875,6 +2875,7 @@ int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats)
}
WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory");
+#ifndef WOLFSSL_STATIC_MEMORY_LEAN
/* fill out statistics if wanted */
if (mem_stats != NULL && ctx->heap != NULL) {
WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory;
@@ -2882,13 +2883,15 @@ int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats)
return MEMORY_E;
}
}
+#endif
+ (void)mem_stats;
return (ctx->heap) ? 1 : 0;
}
#endif /* WOLFSSL_STATIC_MEMORY */
-
+#ifndef NO_TLS
/* return max record layer size plaintext input size */
int wolfSSL_GetMaxOutputSize(WOLFSSL* ssl)
{
@@ -2922,21 +2925,40 @@ int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz)
if (inSz > maxSize)
return INPUT_SIZE_E;
- return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0, CUR_ORDER);
+ return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0,
+ CUR_ORDER);
}
#ifdef HAVE_ECC
int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz)
{
- if (ctx == NULL || keySz < 0 || keySz % 8 != 0) {
- WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null");
+ short keySzBytes;
+
+ WOLFSSL_ENTER("wolfSSL_CTX_SetMinEccKey_Sz");
+ if (ctx == NULL || keySz < 0) {
+ WOLFSSL_MSG("Key size must be positive value or ctx was null");
return BAD_FUNC_ARG;
}
- ctx->minEccKeySz = keySz / 8;
+ if (keySz % 8 == 0) {
+ keySzBytes = keySz / 8;
+ }
+ else {
+ keySzBytes = (keySz / 8) + 1;
+ }
+
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ if (ctx->minEccKeySz > (keySzBytes)) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
+ ctx->minEccKeySz = keySzBytes;
#ifndef NO_CERTS
- ctx->cm->minEccKeySz = keySz / 8;
+ ctx->cm->minEccKeySz = keySzBytes;
#endif
return WOLFSSL_SUCCESS;
}
@@ -2944,12 +2966,30 @@ int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz)
int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz)
{
- if (ssl == NULL || keySz < 0 || keySz % 8 != 0) {
- WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null");
+ short keySzBytes;
+
+ WOLFSSL_ENTER("wolfSSL_SetMinEccKey_Sz");
+ if (ssl == NULL || keySz < 0) {
+ WOLFSSL_MSG("Key size must be positive value or ctx was null");
return BAD_FUNC_ARG;
}
- ssl->options.minEccKeySz = keySz / 8;
+ if (keySz % 8 == 0) {
+ keySzBytes = keySz / 8;
+ }
+ else {
+ keySzBytes = (keySz / 8) + 1;
+ }
+
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ if (ssl->options.minEccKeySz > (keySzBytes)) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
+ ssl->options.minEccKeySz = keySzBytes;
return WOLFSSL_SUCCESS;
}
@@ -2963,6 +3003,14 @@ int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX* ctx, short keySz)
return BAD_FUNC_ARG;
}
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ if (ctx->minRsaKeySz > (keySz / 8)) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
ctx->minRsaKeySz = keySz / 8;
ctx->cm->minRsaKeySz = keySz / 8;
return WOLFSSL_SUCCESS;
@@ -2976,6 +3024,14 @@ int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz)
return BAD_FUNC_ARG;
}
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ if (ssl->options.minRsaKeySz > (keySz / 8)) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
ssl->options.minRsaKeySz = keySz / 8;
return WOLFSSL_SUCCESS;
}
@@ -2983,138 +3039,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,87 +3059,19 @@ 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)
return BAD_FUNC_ARG;
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ if (ctx->minDhKeySz > (keySz_bits / 8)) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
ctx->minDhKeySz = keySz_bits / 8;
return WOLFSSL_SUCCESS;
}
@@ -3226,6 +3082,14 @@ int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz_bits)
if (ssl == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0)
return BAD_FUNC_ARG;
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ if (ssl->options.minDhKeySz > (keySz_bits / 8)) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
ssl->options.minDhKeySz = keySz_bits / 8;
return WOLFSSL_SUCCESS;
}
@@ -3236,6 +3100,14 @@ int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz_bits)
if (ctx == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0)
return BAD_FUNC_ARG;
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ if (ctx->minDhKeySz > (keySz_bits / 8)) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
ctx->maxDhKeySz = keySz_bits / 8;
return WOLFSSL_SUCCESS;
}
@@ -3246,6 +3118,14 @@ int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz_bits)
if (ssl == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0)
return BAD_FUNC_ARG;
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ if (ssl->options.minDhKeySz > (keySz_bits / 8)) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
ssl->options.maxDhKeySz = keySz_bits / 8;
return WOLFSSL_SUCCESS;
}
@@ -3262,14 +3142,13 @@ int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl)
#endif /* !NO_DH */
-WOLFSSL_ABI
-int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
+static int wolfSSL_write_internal(WOLFSSL* ssl, const void* data, size_t sz)
{
int ret;
WOLFSSL_ENTER("wolfSSL_write");
- if (ssl == NULL || data == NULL || sz < 0)
+ if (ssl == NULL || data == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_QUIC
@@ -3315,8 +3194,8 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
#ifdef OPENSSL_EXTRA
if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_CB_WRITE, WOLFSSL_SUCCESS);
- ssl->cbmode = SSL_CB_WRITE;
+ ssl->CBIS(ssl, WOLFSSL_CB_WRITE, WOLFSSL_SUCCESS);
+ ssl->cbmode = WOLFSSL_CB_WRITE;
}
#endif
ret = SendData(ssl, data, sz);
@@ -3329,47 +3208,132 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
return ret;
}
-static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
+WOLFSSL_ABI
+int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
{
- int ret;
-
- WOLFSSL_ENTER("wolfSSL_read_internal");
+ WOLFSSL_ENTER("wolfSSL_write");
- if (ssl == NULL || data == NULL || sz < 0)
+ if (sz < 0)
return BAD_FUNC_ARG;
-#ifdef WOLFSSL_QUIC
- if (WOLFSSL_IS_QUIC(ssl)) {
- WOLFSSL_MSG("SSL_read() on QUIC not allowed");
+ return wolfSSL_write_internal(ssl, data, (size_t)sz);
+}
+
+int wolfSSL_inject(WOLFSSL* ssl, const void* data, int sz)
+{
+ int maxLength;
+ int usedLength;
+
+ WOLFSSL_ENTER("wolfSSL_inject");
+
+ if (ssl == NULL || data == NULL || sz <= 0)
return BAD_FUNC_ARG;
- }
-#endif
-#if defined(WOLFSSL_ERROR_CODE_OPENSSL) && defined(OPENSSL_EXTRA)
- /* This additional logic is meant to simulate following openSSL behavior:
- * After bidirectional SSL_shutdown complete, SSL_read returns 0 and
- * SSL_get_error_code returns SSL_ERROR_ZERO_RETURN.
- * This behavior is used to know the disconnect of the underlying
- * transport layer.
- *
- * In this logic, CBIORecv is called with a read size of 0 to check the
- * transport layer status. It also returns WOLFSSL_FAILURE so that
- * SSL_read does not return a positive number on failure.
- */
- /* make sure bidirectional TLS shutdown completes */
- if (ssl->error == WOLFSSL_ERROR_SYSCALL || ssl->options.shutdownDone) {
- /* ask the underlying transport the connection is closed */
- if (ssl->CBIORecv(ssl, (char*)data, 0, ssl->IOCB_ReadCtx) ==
- WOLFSSL_CBIO_ERR_CONN_CLOSE) {
- ssl->options.isClosed = 1;
- ssl->error = WOLFSSL_ERROR_ZERO_RETURN;
- }
- return WOLFSSL_FAILURE;
+ usedLength = (int)(ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx);
+ maxLength = (int)(ssl->buffers.inputBuffer.bufferSize -
+ (word32)usedLength);
+
+ if (sz > maxLength) {
+ /* Need to make space */
+ int ret;
+ if (ssl->buffers.clearOutputBuffer.length > 0) {
+ /* clearOutputBuffer points into so reallocating inputBuffer will
+ * invalidate clearOutputBuffer and lose app data */
+ WOLFSSL_MSG("Can't inject while there is application data to read");
+ return APP_DATA_READY;
+ }
+ ret = GrowInputBuffer(ssl, sz, usedLength);
+ if (ret < 0)
+ return ret;
}
-#endif
-#ifdef HAVE_WRITE_DUP
- if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) {
+ XMEMCPY(ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
+ data, sz);
+ ssl->buffers.inputBuffer.length += sz;
+
+ return WOLFSSL_SUCCESS;
+}
+
+
+int wolfSSL_write_ex(WOLFSSL* ssl, const void* data, size_t sz, size_t* wr)
+{
+ int ret;
+
+ if (wr != NULL) {
+ *wr = 0;
+ }
+
+ ret = wolfSSL_write_internal(ssl, data, sz);
+ if (ret >= 0) {
+ if (wr != NULL) {
+ *wr = (size_t)ret;
+ }
+
+ /* handle partial write cases, if not set then a partial write is
+ * considered a failure case, or if set and ret is 0 then is a fail */
+ if (ret == 0 && ssl->options.partialWrite) {
+ ret = 0;
+ }
+ else if ((size_t)ret < sz && !ssl->options.partialWrite) {
+ ret = 0;
+ }
+ else {
+ /* wrote out all application data, or wrote out 1 byte or more with
+ * partial write flag set */
+ ret = 1;
+ }
+ }
+ else {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+
+static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, size_t sz, int peek)
+{
+ int ret;
+
+ WOLFSSL_ENTER("wolfSSL_read_internal");
+
+ if (ssl == NULL || data == NULL)
+ return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_QUIC
+ if (WOLFSSL_IS_QUIC(ssl)) {
+ WOLFSSL_MSG("SSL_read() on QUIC not allowed");
+ return BAD_FUNC_ARG;
+ }
+#endif
+#if defined(WOLFSSL_ERROR_CODE_OPENSSL) && defined(OPENSSL_EXTRA)
+ /* This additional logic is meant to simulate following openSSL behavior:
+ * After bidirectional SSL_shutdown complete, SSL_read returns 0 and
+ * SSL_get_error_code returns SSL_ERROR_ZERO_RETURN.
+ * This behavior is used to know the disconnect of the underlying
+ * transport layer.
+ *
+ * In this logic, CBIORecv is called with a read size of 0 to check the
+ * transport layer status. It also returns WOLFSSL_FAILURE so that
+ * SSL_read does not return a positive number on failure.
+ */
+
+ /* make sure bidirectional TLS shutdown completes */
+ if (ssl->error == WOLFSSL_ERROR_SYSCALL || ssl->options.shutdownDone) {
+ /* ask the underlying transport the connection is closed */
+ if (ssl->CBIORecv(ssl, (char*)data, 0, ssl->IOCB_ReadCtx)
+ == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_CONN_CLOSE))
+ {
+ ssl->options.isClosed = 1;
+ ssl->error = WOLFSSL_ERROR_ZERO_RETURN;
+ }
+ return WOLFSSL_FAILURE;
+ }
+#endif
+
+#ifdef HAVE_WRITE_DUP
+ if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) {
WOLFSSL_MSG("Write dup side cannot read");
return WRITE_DUP_READ_E;
}
@@ -3383,9 +3347,9 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
#ifdef HAVE_WRITE_DUP
if (ssl->dupWrite) {
- if (ssl->error != 0 && ssl->error != WANT_READ
+ if (ssl->error != 0 && ssl->error != WC_NO_ERR_TRACE(WANT_READ)
#ifdef WOLFSSL_ASYNC_CRYPT
- && ssl->error != WC_PENDING_E
+ && ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
) {
int notifyErr;
@@ -3412,7 +3376,10 @@ int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz)
{
WOLFSSL_ENTER("wolfSSL_peek");
- return wolfSSL_read_internal(ssl, data, sz, TRUE);
+ if (sz < 0)
+ return BAD_FUNC_ARG;
+
+ return wolfSSL_read_internal(ssl, data, (size_t)sz, TRUE);
}
@@ -3421,19 +3388,45 @@ int wolfSSL_read(WOLFSSL* ssl, void* data, int sz)
{
WOLFSSL_ENTER("wolfSSL_read");
+ if (sz < 0)
+ return BAD_FUNC_ARG;
+
#ifdef OPENSSL_EXTRA
if (ssl == NULL) {
return BAD_FUNC_ARG;
}
if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_CB_READ, WOLFSSL_SUCCESS);
- ssl->cbmode = SSL_CB_READ;
+ ssl->CBIS(ssl, WOLFSSL_CB_READ, WOLFSSL_SUCCESS);
+ ssl->cbmode = WOLFSSL_CB_READ;
}
#endif
- return wolfSSL_read_internal(ssl, data, sz, FALSE);
+ return wolfSSL_read_internal(ssl, data, (size_t)sz, FALSE);
}
+/* returns 0 on failure and 1 on read */
+int wolfSSL_read_ex(WOLFSSL* ssl, void* data, size_t sz, size_t* rd)
+{
+ int ret;
+
+ #ifdef OPENSSL_EXTRA
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
+ }
+ if (ssl->CBIS != NULL) {
+ ssl->CBIS(ssl, WOLFSSL_CB_READ, WOLFSSL_SUCCESS);
+ ssl->cbmode = WOLFSSL_CB_READ;
+ }
+ #endif
+ ret = wolfSSL_read_internal(ssl, data, sz, FALSE);
+
+ if (ret > 0 && rd != NULL) {
+ *rd = (size_t)ret;
+ }
+
+ return ret > 0 ? 1 : 0;
+}
+
#ifdef WOLFSSL_MULTICAST
int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz)
@@ -3442,17 +3435,17 @@ int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz)
WOLFSSL_ENTER("wolfSSL_mcast_read");
- if (ssl == NULL)
+ if ((ssl == NULL) || (sz < 0))
return BAD_FUNC_ARG;
- ret = wolfSSL_read_internal(ssl, data, sz, FALSE);
+ ret = wolfSSL_read_internal(ssl, data, (size_t)sz, FALSE);
if (ssl->options.dtls && ssl->options.haveMcast && id != NULL)
*id = ssl->keys.curPeerId;
return ret;
}
#endif /* WOLFSSL_MULTICAST */
-
+#endif /* !NO_TLS */
/* helpers to set the device id, WOLFSSL_SUCCESS on ok */
WOLFSSL_ABI
@@ -3499,6 +3492,7 @@ void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl)
}
+#ifndef NO_TLS
#ifdef HAVE_SNI
WOLFSSL_ABI
@@ -3549,7 +3543,7 @@ word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data)
*data = NULL;
if (ssl && ssl->extensions)
- return TLSX_SNI_GetRequest(ssl->extensions, type, data);
+ return TLSX_SNI_GetRequest(ssl->extensions, type, data, 0);
return 0;
}
@@ -3564,7 +3558,7 @@ int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
return BAD_FUNC_ARG;
}
-#endif /* NO_WOLFSSL_SERVER */
+#endif /* !NO_WOLFSSL_SERVER */
#endif /* HAVE_SNI */
@@ -3750,15 +3744,36 @@ static int isValidCurveGroup(word16 name)
case WOLFSSL_FFDHE_6144:
case WOLFSSL_FFDHE_8192:
-#ifdef HAVE_PQC
+#ifdef WOLFSSL_HAVE_MLKEM
+#ifndef WOLFSSL_NO_ML_KEM
+ case WOLFSSL_ML_KEM_512:
+ case WOLFSSL_ML_KEM_768:
+ case WOLFSSL_ML_KEM_1024:
+ #if defined(WOLFSSL_WC_MLKEM) || defined(HAVE_LIBOQS)
+ case WOLFSSL_SECP256R1MLKEM512:
+ case WOLFSSL_SECP384R1MLKEM768:
+ case WOLFSSL_SECP521R1MLKEM1024:
+ case WOLFSSL_SECP384R1MLKEM1024:
+ case WOLFSSL_X25519MLKEM512:
+ case WOLFSSL_X448MLKEM768:
+ case WOLFSSL_X25519MLKEM768:
+ case WOLFSSL_SECP256R1MLKEM768:
+ #endif
+#endif /* !WOLFSSL_NO_ML_KEM */
+#ifdef WOLFSSL_MLKEM_KYBER
case WOLFSSL_KYBER_LEVEL1:
case WOLFSSL_KYBER_LEVEL3:
case WOLFSSL_KYBER_LEVEL5:
- #ifdef HAVE_LIBOQS
+ #if defined(WOLFSSL_WC_MLKEM) || defined(HAVE_LIBOQS)
case WOLFSSL_P256_KYBER_LEVEL1:
case WOLFSSL_P384_KYBER_LEVEL3:
case WOLFSSL_P521_KYBER_LEVEL5:
+ case WOLFSSL_X25519_KYBER_LEVEL1:
+ case WOLFSSL_X448_KYBER_LEVEL3:
+ case WOLFSSL_X25519_KYBER_LEVEL3:
+ case WOLFSSL_P256_KYBER_LEVEL3:
#endif
+#endif /* WOLFSSL_MLKEM_KYBER */
#endif
return 1;
@@ -3794,7 +3809,7 @@ int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name)
#endif /* NO_TLS */
}
-#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13)
+#if defined(OPENSSL_EXTRA)
int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups,
int count)
{
@@ -3812,7 +3827,7 @@ int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups,
#ifdef HAVE_ECC
else {
/* groups may be populated with curve NIDs */
- int oid = nid2oid(groups[i], oidCurveType);
+ int oid = (int)nid2oid(groups[i], oidCurveType);
int name = (int)GetCurveByOID(oid);
if (name == 0) {
WOLFSSL_MSG("Invalid group name");
@@ -3847,7 +3862,7 @@ int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count)
#ifdef HAVE_ECC
else {
/* groups may be populated with curve NIDs */
- int oid = nid2oid(groups[i], oidCurveType);
+ int oid = (int)nid2oid(groups[i], oidCurveType);
int name = (int)GetCurveByOID(oid);
if (name == 0) {
WOLFSSL_MSG("Invalid group name");
@@ -3865,7 +3880,7 @@ int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count)
return wolfSSL_set_groups(ssl, _groups, count) == WOLFSSL_SUCCESS ?
WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
}
-#endif /* OPENSSL_EXTRA && WOLFSSL_TLS13 */
+#endif /* OPENSSL_EXTRA */
#endif /* HAVE_SUPPORTED_CURVES */
/* Application-Layer Protocol Negotiation */
@@ -3875,10 +3890,10 @@ WOLFSSL_ABI
int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list,
word32 protocol_name_listSz, byte options)
{
- char *list, *ptr, **token;
+ char *list, *ptr = NULL, **token;
word16 len;
int idx = 0;
- int ret = WOLFSSL_FAILURE;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
WOLFSSL_ENTER("wolfSSL_UseALPN");
@@ -3906,7 +3921,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");
@@ -3983,7 +3999,7 @@ int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz)
*list = NULL;
return WOLFSSL_FAILURE;
}
- XMEMCPY(p, s + i, len);
+ XMEMCPY(p, s + i, (size_t)len);
}
*p = 0;
@@ -4012,12 +4028,14 @@ int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list)
/* user is forcing ability to use secure renegotiation, we discourage it */
int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl)
{
- int ret = BAD_FUNC_ARG;
+ int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
#if defined(NO_TLS)
(void)ssl;
#else
if (ssl)
ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap);
+ else
+ ret = BAD_FUNC_ARG;
if (ret == WOLFSSL_SUCCESS) {
TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO);
@@ -4103,7 +4121,7 @@ static int _Rehandshake(WOLFSSL* ssl)
ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
-#if !defined(NO_WOLFSSL_SERVER)
+#if !defined(NO_WOLFSSL_SERVER) && !defined(WOLFSSL_NO_TLS12)
if (ssl->options.side == WOLFSSL_SERVER_END) {
ret = SendHelloRequest(ssl);
if (ret != 0) {
@@ -4111,7 +4129,7 @@ static int _Rehandshake(WOLFSSL* ssl)
return WOLFSSL_FATAL_ERROR;
}
}
-#endif /* !NO_WOLFSSL_SERVER */
+#endif /* !NO_WOLFSSL_SERVER && !WOLFSSL_NO_TLS12 */
ret = InitHandshakeHashes(ssl);
if (ret != 0) {
@@ -4309,7 +4327,15 @@ int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx)
int wolfSSL_get_SessionTicket(WOLFSSL* ssl, byte* buf, word32* bufSz)
{
- if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0)
+ if (ssl == NULL || bufSz == NULL)
+ return BAD_FUNC_ARG;
+
+ if (*bufSz == 0 && buf == NULL) {
+ *bufSz = ssl->session->ticketLen;
+ return LENGTH_ONLY_E;
+ }
+
+ if (buf == NULL)
return BAD_FUNC_ARG;
if (ssl->session->ticketLen <= *bufSz) {
@@ -4339,7 +4365,8 @@ int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf,
}
}
else { /* Ticket requires dynamic ticket storage */
- if (ssl->session->ticketLen < bufSz) { /* is dyn buffer big enough */
+ /* is dyn buffer big enough */
+ if (ssl->session->ticketLen < bufSz) {
if (ssl->session->ticketLenAlloc > 0) {
XFREE(ssl->session->ticket, ssl->session->heap,
DYNAMIC_TYPE_SESSION_TICK);
@@ -4452,12 +4479,31 @@ int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags)
}
#endif
+int wolfSSL_SendUserCanceled(WOLFSSL* ssl)
+{
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ WOLFSSL_ENTER("wolfSSL_recv");
+
+ if (ssl != NULL) {
+ ssl->error = SendAlert(ssl, alert_warning, user_canceled);
+ if (ssl->error < 0) {
+ WOLFSSL_ERROR(ssl->error);
+ }
+ else {
+ ret = wolfSSL_shutdown(ssl);
+ }
+ }
+
+ WOLFSSL_LEAVE("wolfSSL_SendUserCanceled", ret);
+
+ return ret;
+}
/* WOLFSSL_SUCCESS on ok */
WOLFSSL_ABI
int wolfSSL_shutdown(WOLFSSL* ssl)
{
- int ret = WOLFSSL_FATAL_ERROR;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
WOLFSSL_ENTER("wolfSSL_shutdown");
if (ssl == NULL)
@@ -4468,15 +4514,53 @@ int wolfSSL_shutdown(WOLFSSL* ssl)
ret = WOLFSSL_SUCCESS;
}
else {
+
+ /* Try to flush the buffer first, it might contain the alert */
+ if (ssl->error == WC_NO_ERR_TRACE(WANT_WRITE) &&
+ ssl->buffers.outputBuffer.length > 0) {
+ ret = SendBuffered(ssl);
+ if (ret != 0) {
+ ssl->error = ret;
+ /* for error tracing */
+ if (ret != WC_NO_ERR_TRACE(WANT_WRITE))
+ WOLFSSL_ERROR(ret);
+ ret = WOLFSSL_FATAL_ERROR;
+ WOLFSSL_LEAVE("wolfSSL_shutdown", ret);
+ return ret;
+ }
+
+ ssl->error = WOLFSSL_ERROR_NONE;
+ /* we succeeded in sending the alert now */
+ if (ssl->options.sentNotify) {
+ /* just after we send the alert, if we didn't receive the alert
+ * from the other peer yet, return WOLFSSL_STHUDOWN_NOT_DONE */
+ if (!ssl->options.closeNotify) {
+ ret = WOLFSSL_SHUTDOWN_NOT_DONE;
+ WOLFSSL_LEAVE("wolfSSL_shutdown", ret);
+ return ret;
+ }
+ else {
+ ssl->options.shutdownDone = 1;
+ ret = WOLFSSL_SUCCESS;
+ }
+ }
+ }
+
/* try to send close notify, not an error if can't */
if (!ssl->options.isClosed && !ssl->options.connReset &&
!ssl->options.sentNotify) {
ssl->error = SendAlert(ssl, alert_warning, close_notify);
+
+ /* the alert is now sent or sitting in the buffer,
+ * where will be sent eventually */
+ if (ssl->error == 0 || ssl->error == WC_NO_ERR_TRACE(WANT_WRITE))
+ ssl->options.sentNotify = 1;
+
if (ssl->error < 0) {
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
- ssl->options.sentNotify = 1; /* don't send close_notify twice */
+
if (ssl->options.closeNotify) {
ret = WOLFSSL_SUCCESS;
ssl->options.shutdownDone = 1;
@@ -4496,20 +4580,28 @@ int wolfSSL_shutdown(WOLFSSL* ssl)
}
#endif
- /* call wolfSSL_shutdown again for bidirectional shutdown */
+ /* wolfSSL_shutdown called again for bidirectional shutdown */
if (ssl->options.sentNotify && !ssl->options.closeNotify) {
ret = ProcessReply(ssl);
- if ((ret == ZERO_RETURN) || (ret == SOCKET_ERROR_E)) {
+ if ((ret == WC_NO_ERR_TRACE(ZERO_RETURN)) ||
+ (ret == WC_NO_ERR_TRACE(SOCKET_ERROR_E))) {
/* simulate OpenSSL behavior */
ssl->options.shutdownDone = 1;
/* Clear error */
ssl->error = WOLFSSL_ERROR_NONE;
ret = WOLFSSL_SUCCESS;
- } else if (ret == MEMORY_E) {
+ }
+ else if (ret == WC_NO_ERR_TRACE(MEMORY_E)) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ else if (ret == WC_NO_ERR_TRACE(WANT_READ)) {
+ ssl->error = ret;
ret = WOLFSSL_FATAL_ERROR;
- } else if (ssl->error == WOLFSSL_ERROR_NONE) {
+ }
+ else if (ssl->error == WOLFSSL_ERROR_NONE) {
ret = WOLFSSL_SHUTDOWN_NOT_DONE;
- } else {
+ }
+ else {
WOLFSSL_ERROR(ssl->error);
ret = WOLFSSL_FATAL_ERROR;
}
@@ -4530,7 +4622,7 @@ int wolfSSL_shutdown(WOLFSSL* ssl)
return ret;
}
-
+#endif /* !NO_TLS */
/* get current error state value */
int wolfSSL_state(WOLFSSL* ssl)
@@ -4556,21 +4648,20 @@ int wolfSSL_get_error(WOLFSSL* ssl, int ret)
WOLFSSL_LEAVE("wolfSSL_get_error", ssl->error);
/* make sure converted types are handled in SetErrorString() too */
- if (ssl->error == WANT_READ)
+ if (ssl->error == WC_NO_ERR_TRACE(WANT_READ))
return WOLFSSL_ERROR_WANT_READ; /* convert to OpenSSL type */
- else if (ssl->error == WANT_WRITE)
+ else if (ssl->error == WC_NO_ERR_TRACE(WANT_WRITE))
return WOLFSSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */
- else if (ssl->error == ZERO_RETURN || ssl->options.shutdownDone)
+ else if (ssl->error == WC_NO_ERR_TRACE(ZERO_RETURN) ||
+ ssl->options.shutdownDone)
return WOLFSSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */
#ifdef OPENSSL_EXTRA
- else if (ssl->error == SOCKET_PEER_CLOSED_E)
+ else if (ssl->error == WC_NO_ERR_TRACE(MATCH_SUITE_ERROR))
+ return WOLFSSL_ERROR_SYSCALL; /* convert to OpenSSL type */
+ else if (ssl->error == WC_NO_ERR_TRACE(SOCKET_PEER_CLOSED_E))
return WOLFSSL_ERROR_SYSCALL; /* convert to OpenSSL type */
#endif
-#if defined(WOLFSSL_HAPROXY)
- return GetX509Error(ssl->error);
-#else
- return (ssl->error);
-#endif
+ return ssl->error;
}
@@ -4587,12 +4678,12 @@ int wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *h)
/* returns SSL_WRITING, SSL_READING or SSL_NOTHING */
int wolfSSL_want(WOLFSSL* ssl)
{
- int rw_state = SSL_NOTHING;
+ int rw_state = WOLFSSL_NOTHING;
if (ssl) {
- if (ssl->error == WANT_READ)
- rw_state = SSL_READING;
- else if (ssl->error == WANT_WRITE)
- rw_state = SSL_WRITING;
+ if (ssl->error == WC_NO_ERR_TRACE(WANT_READ))
+ rw_state = WOLFSSL_READING;
+ else if (ssl->error == WC_NO_ERR_TRACE(WANT_WRITE))
+ rw_state = WOLFSSL_WRITING;
}
return rw_state;
}
@@ -4602,24 +4693,22 @@ int wolfSSL_want(WOLFSSL* ssl)
int wolfSSL_want_read(WOLFSSL* ssl)
{
WOLFSSL_ENTER("wolfSSL_want_read");
- if (ssl->error == WANT_READ)
+ if (ssl->error == WC_NO_ERR_TRACE(WANT_READ))
return 1;
return 0;
}
-
/* return TRUE if current error is want write */
int wolfSSL_want_write(WOLFSSL* ssl)
{
WOLFSSL_ENTER("wolfSSL_want_write");
- if (ssl->error == WANT_WRITE)
+ if (ssl->error == WC_NO_ERR_TRACE(WANT_WRITE))
return 1;
return 0;
}
-
char* wolfSSL_ERR_error_string(unsigned long errNumber, char* data)
{
WOLFSSL_ENTER("wolfSSL_ERR_error_string");
@@ -5012,7 +5101,7 @@ int wolfSSL_GetCipherType(WOLFSSL* ssl)
if (ssl->specs.cipher_type == aead)
return WOLFSSL_AEAD_TYPE;
- return -1;
+ return WOLFSSL_FATAL_ERROR;
}
@@ -5128,7 +5217,7 @@ int wolfSSL_pending(WOLFSSL* ssl)
if (ssl == NULL)
return WOLFSSL_FAILURE;
- return ssl->buffers.clearOutputBuffer.length;
+ return (int)ssl->buffers.clearOutputBuffer.length;
}
int wolfSSL_has_pending(const WOLFSSL* ssl)
@@ -5151,10 +5240,20 @@ int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx)
return WOLFSSL_SUCCESS;
}
+
+int wolfSSL_CTX_clear_group_messages(WOLFSSL_CTX* ctx)
+{
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ ctx->groupMessages = 0;
+
+ return WOLFSSL_SUCCESS;
+}
#endif
-#ifndef NO_WOLFSSL_CLIENT
+#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
/* connect enough to get peer cert chain */
int wolfSSL_connect_cert(WOLFSSL* ssl)
{
@@ -5184,13 +5283,20 @@ int wolfSSL_set_group_messages(WOLFSSL* ssl)
return WOLFSSL_SUCCESS;
}
+int wolfSSL_clear_group_messages(WOLFSSL* ssl)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+
+ ssl->options.groupMessages = 0;
+
+ return WOLFSSL_SUCCESS;
+}
/* make minVersion the internal equivalent SSL version */
static int SetMinVersionHelper(byte* minVersion, int version)
{
-#ifdef NO_TLS
(void)minVersion;
-#endif
switch (version) {
#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
@@ -5257,6 +5363,12 @@ int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version)
return BAD_FUNC_ARG;
}
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
return SetMinVersionHelper(&ctx->minDowngrade, version);
}
@@ -5271,6 +5383,12 @@ int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version)
return BAD_FUNC_ARG;
}
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ if (crypto_policy.enabled) {
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
return SetMinVersionHelper(&ssl->options.minDowngrade, version);
}
@@ -5297,6 +5415,20 @@ int wolfSSL_GetVersion(const WOLFSSL* ssl)
break;
}
}
+#ifdef WOLFSSL_DTLS
+ if (ssl->version.major == DTLS_MAJOR) {
+ switch (ssl->version.minor) {
+ case DTLS_MINOR :
+ return WOLFSSL_DTLSV1;
+ case DTLSv1_2_MINOR :
+ return WOLFSSL_DTLSV1_2;
+ case DTLSv1_3_MINOR :
+ return WOLFSSL_DTLSV1_3;
+ default:
+ break;
+ }
+ }
+#endif /* WOLFSSL_DTLS */
return VERSION_ERROR;
}
@@ -5366,8 +5498,7 @@ int wolfSSL_SetVersion(WOLFSSL* ssl, int version)
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);
+ ssl->options.useAnon, TRUE, TRUE, TRUE, TRUE, ssl->options.side);
return WOLFSSL_SUCCESS;
}
#endif /* !leanpsk */
@@ -5437,8 +5568,13 @@ int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DecodedCert* cert)
return ret;
tp = cm->tpTable[row];
while (tp) {
- if (XMEMCMP(cert->subjectHash, tp->subjectNameHash,
+ if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
+ SIGNER_DIGEST_SIZE) == 0)
+ #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
+ && (XMEMCMP(cert->issuerHash, tp->issuerHash,
SIGNER_DIGEST_SIZE) == 0)
+ #endif
+ )
ret = 1;
#ifndef NO_SKID
if (cert->extSubjKeyIdSet) {
@@ -5478,8 +5614,13 @@ TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert)
tp = cm->tpTable[row];
while (tp) {
- if (XMEMCMP(cert->subjectHash, tp->subjectNameHash,
+ if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
+ SIGNER_DIGEST_SIZE) == 0)
+ #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
+ && (XMEMCMP(cert->issuerHash, tp->issuerHash,
SIGNER_DIGEST_SIZE) == 0)
+ #endif
+ )
ret = tp;
#ifndef NO_SKID
if (cert->extSubjKeyIdSet) {
@@ -5557,6 +5698,42 @@ Signer* GetCA(void* vp, byte* hash)
return ret;
}
+#if defined(HAVE_OCSP)
+Signer* GetCAByKeyHash(void* vp, const byte* keyHash)
+{
+ WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
+ Signer* ret = NULL;
+ Signer* signers;
+ int row;
+
+ if (cm == NULL || keyHash == NULL)
+ return NULL;
+
+ /* try lookup using keyHash as subjKeyID first */
+ ret = GetCA(vp, (byte*)keyHash);
+ if (ret != NULL && XMEMCMP(ret->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
+ return ret;
+ }
+
+ /* if we can't find the cert, we have to scan the full table */
+ if (wc_LockMutex(&cm->caLock) != 0)
+ return NULL;
+
+ /* Unfortunately we need to look through the entire table */
+ for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
+ for (signers = cm->caTable[row]; signers != NULL;
+ signers = signers->next) {
+ if (XMEMCMP(signers->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
+ ret = signers;
+ break;
+ }
+ }
+ }
+
+ wc_UnLockMutex(&cm->caLock);
+ return ret;
+}
+#endif
#ifdef WOLFSSL_AKID_NAME
Signer* GetCAByAKID(void* vp, const byte* issuer, word32 issuerSz,
const byte* serial, word32 serialSz)
@@ -5709,14 +5886,19 @@ 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. */
+ #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
+ XMEMCPY(peerCert->issuerHash, cert->issuerHash,
+ SIGNER_DIGEST_SIZE);
+ #endif
+ /* If Key Usage not set, all uses valid. */
+ peerCert->next = NULL;
cert->subjectCN = 0;
#ifndef IGNORE_NAME_CONSTRAINTS
cert->permittedNames = NULL;
cert->excludedNames = NULL;
#endif
- row = TrustedPeerHashSigner(peerCert->subjectNameHash);
+ row = (int)TrustedPeerHashSigner(peerCert->subjectNameHash);
if (wc_LockMutex(&cm->tpLock) == 0) {
peerCert->next = cm->tpTable[row];
@@ -5745,6 +5927,38 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
}
#endif /* WOLFSSL_TRUST_PEER_CERT */
+int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s)
+{
+ byte* subjectHash;
+ Signer* signers;
+ word32 row;
+
+ if (cm == NULL || s == NULL)
+ return BAD_FUNC_ARG;
+
+#ifndef NO_SKID
+ subjectHash = s->subjectKeyIdHash;
+#else
+ subjectHash = s->subjectNameHash;
+#endif
+
+ if (AlreadySigner(cm, subjectHash)) {
+ FreeSigner(s, cm->heap);
+ return 0;
+ }
+
+ row = HashSigner(subjectHash);
+
+ if (wc_LockMutex(&cm->caLock) != 0)
+ return BAD_MUTEX_E;
+
+ signers = cm->caTable[row];
+ s->next = signers;
+ cm->caTable[row] = s;
+
+ wc_UnLockMutex(&cm->caLock);
+ return 0;
+}
/* owns der, internal now uses too */
/* type flag ids from user or from chain received during verify
@@ -5755,32 +5969,54 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
Signer* signer = NULL;
word32 row;
byte* subjectHash;
-#ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert = NULL;
-#else
- DecodedCert cert[1];
-#endif
+ WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
DerBuffer* der = *pDer;
- WOLFSSL_MSG("Adding a CA");
+ WOLFSSL_MSG_CERT_LOG("Adding a CA");
if (cm == NULL) {
FreeDer(pDer);
return BAD_FUNC_ARG;
}
-#ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_DCERT);
+ #ifdef WOLFSSL_SMALL_STACK
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
if (cert == NULL) {
FreeDer(pDer);
return MEMORY_E;
}
-#endif
+ #endif
InitDecodedCert(cert, der->buffer, der->length, cm->heap);
+
+#ifdef WC_ASN_UNKNOWN_EXT_CB
+ if (cm->unknownExtCallback != NULL) {
+ wc_SetUnknownExtCallback(cert, cm->unknownExtCallback);
+ }
+#endif
+
+ WOLFSSL_MSG_CERT("\tParsing new CA");
ret = ParseCert(cert, CA_TYPE, verify, cm);
- WOLFSSL_MSG("\tParsed new CA");
+
+ WOLFSSL_MSG("\tParsed new CA");
+#ifdef WOLFSSL_DEBUG_CERTS
+ {
+ const char* err_msg;
+ if (ret == 0) {
+ WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "issuer: '%s'",
+ cert->issuer);
+ WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "subject: '%s'",
+ cert->subject);
+ }
+ else {
+ WOLFSSL_MSG_CERT(
+ WOLFSSL_MSG_CERT_INDENT "Failed during parse of new CA");
+ err_msg = wc_GetErrorString(ret);
+ WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "error ret: %d; %s",
+ ret, err_msg);
+ }
+ }
+#endif /* WOLFSSL_DEBUG_CERTS */
#ifndef NO_SKID
subjectHash = cert->extSubjKeyId;
@@ -5789,7 +6025,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
#endif
/* check CA key size */
- if (verify) {
+ if (verify && (ret == 0 )) {
switch (cert->keyOID) {
#ifndef NO_RSA
#ifdef WC_RSA_PSS
@@ -5799,7 +6035,10 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
if (cm->minRsaKeySz < 0 ||
cert->pubKeySize < (word16)cm->minRsaKeySz) {
ret = RSA_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA RSA key size error");
+ WOLFSSL_MSG_CERT_LOG("\tCA RSA key size error");
+ WOLFSSL_MSG_CERT_EX("\tCA RSA pubKeySize = %d; "
+ "minRsaKeySz = %d",
+ cert->pubKeySize, cm->minRsaKeySz);
}
break;
#endif /* !NO_RSA */
@@ -5808,7 +6047,10 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
if (cm->minEccKeySz < 0 ||
cert->pubKeySize < (word16)cm->minEccKeySz) {
ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("\tCA ECC key size error");
+ WOLFSSL_MSG_CERT_LOG("\tCA ECC key size error");
+ WOLFSSL_MSG_CERT_EX("\tCA ECC pubKeySize = %d; "
+ "minEccKeySz = %d",
+ cert->pubKeySize, cm->minEccKeySz);
}
break;
#endif /* HAVE_ECC */
@@ -5830,7 +6072,6 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
}
break;
#endif /* HAVE_ED448 */
- #if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
case FALCON_LEVEL1k:
if (cm->minFalconKeySz < 0 ||
@@ -5848,6 +6089,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
break;
#endif /* HAVE_FALCON */
#if defined(HAVE_DILITHIUM)
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
case DILITHIUM_LEVEL2k:
if (cm->minDilithiumKeySz < 0 ||
DILITHIUM_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
@@ -5869,8 +6111,29 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
WOLFSSL_MSG("\tCA Dilithium level 5 key size error");
}
break;
+ #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
+ case ML_DSA_LEVEL2k:
+ if (cm->minDilithiumKeySz < 0 ||
+ ML_DSA_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
+ ret = DILITHIUM_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Dilithium level 2 key size error");
+ }
+ break;
+ case ML_DSA_LEVEL3k:
+ if (cm->minDilithiumKeySz < 0 ||
+ ML_DSA_LEVEL3_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
+ ret = DILITHIUM_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Dilithium level 3 key size error");
+ }
+ break;
+ case ML_DSA_LEVEL5k:
+ if (cm->minDilithiumKeySz < 0 ||
+ ML_DSA_LEVEL5_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
+ ret = DILITHIUM_KEY_SIZE_E;
+ WOLFSSL_MSG("\tCA Dilithium level 5 key size error");
+ }
+ break;
#endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
default:
WOLFSSL_MSG("\tNo key size check done on CA");
@@ -5878,13 +6141,15 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
}
}
- if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) {
+ if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA &&
+ type != WOLFSSL_TEMP_CA) {
WOLFSSL_MSG("\tCan't add as CA if not actually one");
ret = NOT_CA_ERROR;
}
#ifndef ALLOW_INVALID_CERTSIGN
else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
- !cert->selfSigned && (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
+ type != WOLFSSL_TEMP_CA && !cert->selfSigned &&
+ (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
/* Intermediate CA certs are required to have the keyCertSign
* extension set. User loaded root certs are not. */
WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
@@ -5901,70 +6166,42 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
if (!signer)
ret = MEMORY_ERROR;
}
-#if defined(WOLFSSL_AKID_NAME) || defined(HAVE_CRL)
- if (ret == 0 && signer != NULL)
- ret = CalcHashId(cert->serial, cert->serialSz, signer->serialHash);
-#endif
- if (ret == 0 && signer != NULL) {
- #ifdef WOLFSSL_SIGNER_DER_CERT
- ret = AllocDer(&signer->derCert, der->length, der->type, NULL);
- }
if (ret == 0 && signer != NULL) {
- XMEMCPY(signer->derCert->buffer, der->buffer, der->length);
- #endif
- signer->keyOID = cert->keyOID;
- if (cert->pubKeyStored) {
- signer->publicKey = cert->publicKey;
- signer->pubKeySize = cert->pubKeySize;
- }
-
-#ifdef WOLFSSL_DUAL_ALG_CERTS
- signer->sapkiDer = cert->sapkiDer;
- signer->sapkiLen = cert->sapkiLen;
-#endif /* WOLFSSL_DUAL_ALG_CERTS */
+ ret = FillSigner(signer, cert, type, der);
- if (cert->subjectCNStored) {
- signer->nameLen = cert->subjectCNLen;
- signer->name = cert->subjectCN;
+ if (ret == 0){
+ #ifndef NO_SKID
+ row = HashSigner(signer->subjectKeyIdHash);
+ #else
+ row = HashSigner(signer->subjectNameHash);
+ #endif
}
- signer->maxPathLen = cert->maxPathLen;
- signer->selfSigned = cert->selfSigned;
- #ifndef IGNORE_NAME_CONSTRAINTS
- signer->permittedNames = cert->permittedNames;
- signer->excludedNames = cert->excludedNames;
- #endif
- #ifndef NO_SKID
- XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId,
- SIGNER_DIGEST_SIZE);
- #endif
- XMEMCPY(signer->subjectNameHash, cert->subjectHash,
- SIGNER_DIGEST_SIZE);
- #if defined(HAVE_OCSP) || defined(HAVE_CRL)
- XMEMCPY(signer->issuerNameHash, cert->issuerHash,
- SIGNER_DIGEST_SIZE);
- #endif
- #ifdef HAVE_OCSP
- XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash,
- KEYID_SIZE);
- #endif
- signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
- : 0xFFFF;
- signer->next = NULL; /* If Key Usage not set, all uses valid. */
- cert->publicKey = 0; /* in case lock fails don't free here. */
- cert->subjectCN = 0;
- #ifndef IGNORE_NAME_CONSTRAINTS
- cert->permittedNames = NULL;
- cert->excludedNames = NULL;
- #endif
- signer->type = (byte)type;
- #ifndef NO_SKID
- row = HashSigner(signer->subjectKeyIdHash);
- #else
- row = HashSigner(signer->subjectNameHash);
- #endif
+ #if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS)
+ /* Verify CA by TSIP so that generated tsip key is going to */
+ /* be able to be used for peer's cert verification */
+ /* TSIP is only able to handle USER CA, and only one CA. */
+ /* Therefore, it doesn't need to call TSIP again if there is already */
+ /* verified CA. */
+ if ( ret == 0 && signer != NULL ) {
+ signer->cm_idx = row;
+ if (type == WOLFSSL_USER_CA) {
+ if ((ret = wc_Renesas_cmn_RootCertVerify(cert->source,
+ cert->maxIdx,
+ cert->sigCtx.CertAtt.pubkey_n_start,
+ cert->sigCtx.CertAtt.pubkey_n_len - 1,
+ cert->sigCtx.CertAtt.pubkey_e_start,
+ cert->sigCtx.CertAtt.pubkey_e_len - 1,
+ row/* cm index */))
+ < 0)
+ WOLFSSL_MSG("Renesas_RootCertVerify() failed");
+ else
+ WOLFSSL_MSG("Renesas_RootCertVerify() succeed or skipped");
+ }
+ }
+ #endif /* TSIP or SCE */
- if (wc_LockMutex(&cm->caLock) == 0) {
+ if (ret == 0 && wc_LockMutex(&cm->caLock) == 0) {
signer->next = cm->caTable[row];
cm->caTable[row] = signer; /* takes ownership */
wc_UnLockMutex(&cm->caLock);
@@ -5976,36 +6213,12 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
ret = BAD_MUTEX_E;
}
}
-#if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS)
- /* Verify CA by TSIP so that generated tsip key is going to be able to */
- /* be used for peer's cert verification */
- /* TSIP is only able to handle USER CA, and only one CA. */
- /* Therefore, it doesn't need to call TSIP again if there is already */
- /* verified CA. */
- if ( ret == 0 && signer != NULL ) {
- signer->cm_idx = row;
- if (type == WOLFSSL_USER_CA) {
- if ((ret = wc_Renesas_cmn_RootCertVerify(cert->source, cert->maxIdx,
- cert->sigCtx.CertAtt.pubkey_n_start,
- cert->sigCtx.CertAtt.pubkey_n_len - 1,
- cert->sigCtx.CertAtt.pubkey_e_start,
- cert->sigCtx.CertAtt.pubkey_e_len - 1,
- row/* cm index */))
- < 0)
- WOLFSSL_MSG("Renesas_RootCertVerify() failed");
- else
- WOLFSSL_MSG("Renesas_RootCertVerify() succeed or skipped");
- }
- }
-#endif /* TSIP or SCE */
WOLFSSL_MSG("\tFreeing Parsed CA");
FreeDecodedCert(cert);
if (ret != 0 && signer != NULL)
FreeSigner(signer, cm->heap);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
-#endif
+ WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
WOLFSSL_MSG("\tFreeing der CA");
FreeDer(pDer);
WOLFSSL_MSG("\t\tOK Freeing der CA");
@@ -6015,204 +6228,147 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
return ret == 0 ? WOLFSSL_SUCCESS : ret;
}
-#endif /* !NO_CERTS */
-
-
-#ifndef NO_SESSION_CACHE
-
- /* basic config gives a cache with 33 sessions, adequate for clients and
- embedded servers
-
- TITAN_SESSION_CACHE allows just over 2 million sessions, for servers
- with titanic amounts of memory with long session ID timeouts and high
- levels of traffic.
-
- ENABLE_SESSION_CACHE_ROW_LOCK: Allows row level locking for increased
- performance with large session caches
-
- HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
- allows over 13,000 new sessions per minute or over 200 new sessions per
- second
+/* Removes the CA with the passed in subject hash from the
+ cert manager's CA cert store. */
+int RemoveCA(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
+{
+ Signer* current;
+ Signer** prev;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ word32 row;
- BIG_SESSION_CACHE yields 20,027 sessions
+ WOLFSSL_MSG("Removing a CA");
- MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that
- aren't under heavy load, basically allows 200 new sessions per minute
+ if (cm == NULL || hash == NULL) {
+ return BAD_FUNC_ARG;
+ }
- 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
+ row = HashSigner(hash);
- 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
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ return BAD_MUTEX_E;
+ }
+ current = cm->caTable[row];
+ prev = &cm->caTable[row];
+ while (current) {
+ byte* subjectHash;
- 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
+ #ifndef NO_SKID
+ subjectHash = current->subjectKeyIdHash;
#else
- #define SESSIONS_PER_ROW 3
- #define SESSION_ROWS 11
+ subjectHash = current->subjectNameHash;
#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
+ if ((current->type == type) &&
+ (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0)) {
+ *prev = current->next;
+ FreeSigner(current, cm->heap);
+ ret = WOLFSSL_SUCCESS;
+ break;
+ }
+ prev = ¤t->next;
+ current = current->next;
+ }
+ wc_UnLockMutex(&cm->caLock);
- #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))
+ WOLFSSL_LEAVE("RemoveCA", ret);
- static WOLFSSL_GLOBAL SessionRow SessionCache[SESSION_ROWS];
+ return ret;
+}
- #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
+/* Sets the CA with the passed in subject hash
+ to the provided type. */
+int SetCAType(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
+{
+ Signer* current;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ word32 row;
- #if !defined(NO_SESSION_CACHE_REF) && defined(NO_CLIENT_CACHE)
- #error ClientCache is required when not using NO_SESSION_CACHE_REF
- #endif
+ WOLFSSL_MSG_EX("Setting CA to type %d", type);
- #ifndef NO_CLIENT_CACHE
+ if (cm == NULL || hash == NULL ||
+ type < WOLFSSL_USER_CA || type > WOLFSSL_USER_INTER) {
+ return ret;
+ }
- #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)
+ row = HashSigner(hash);
- #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
+ if (wc_LockMutex(&cm->caLock) != 0) {
+ return ret;
+ }
+ current = cm->caTable[row];
+ while (current) {
+ byte* subjectHash;
- 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
+ #ifndef NO_SKID
+ subjectHash = current->subjectKeyIdHash;
+ #else
+ subjectHash = current->subjectNameHash;
#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;
+ if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
+ current->type = (byte)type;
+ ret = WOLFSSL_SUCCESS;
+ break;
}
-#endif
-#ifdef HAVE_EX_DATA
- session->ownExData = save_ownExData;
-#endif
+ current = current->next;
}
+ wc_UnLockMutex(&cm->caLock);
+
+ WOLFSSL_LEAVE("SetCAType", ret);
+
+ return ret;
+}
+#endif /* !NO_CERTS */
-#endif /* !NO_SESSION_CACHE */
#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB)
static int wolfSSL_RAND_InitMutex(void);
#endif
+/* If we don't have static mutex initializers, but we do have static atomic
+ * initializers, activate WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS to leverage
+ * the latter.
+ *
+ * See further explanation below in wolfSSL_Init().
+ */
+#ifndef WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS
+ #if !defined(WOLFSSL_MUTEX_INITIALIZER) && !defined(SINGLE_THREADED) && \
+ defined(WOLFSSL_ATOMIC_OPS) && defined(WOLFSSL_ATOMIC_INITIALIZER)
+ #define WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS 1
+ #else
+ #define WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS 0
+ #endif
+#elif defined(WOLFSSL_MUTEX_INITIALIZER) || defined(SINGLE_THREADED)
+ #undef WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS
+ #define WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS 0
+#endif
+
+#if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS
+ #ifndef WOLFSSL_ATOMIC_OPS
+ #error WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS requires WOLFSSL_ATOMIC_OPS
+ #endif
+ #ifndef WOLFSSL_ATOMIC_INITIALIZER
+ #error WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS requires WOLFSSL_ATOMIC_INITIALIZER
+ #endif
+ static wolfSSL_Atomic_Int inits_count_mutex_atomic_initing_flag =
+ WOLFSSL_ATOMIC_INITIALIZER(0);
+#endif /* WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS && !WOLFSSL_MUTEX_INITIALIZER */
+
#if defined(OPENSSL_EXTRA) && defined(HAVE_ATEXIT)
static void AtExitCleanup(void)
{
if (initRefCount > 0) {
initRefCount = 1;
(void)wolfSSL_Cleanup();
+#if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS
+ if (inits_count_mutex_valid == 1) {
+ (void)wc_FreeMutex(&inits_count_mutex);
+ inits_count_mutex_valid = 0;
+ inits_count_mutex_atomic_initing_flag = 0;
+ }
+#endif
}
}
#endif
@@ -6227,10 +6383,39 @@ int wolfSSL_Init(void)
WOLFSSL_ENTER("wolfSSL_Init");
+#if defined(LIBWOLFSSL_CMAKE_OUTPUT)
+ WOLFSSL_MSG(LIBWOLFSSL_CMAKE_OUTPUT);
+#else
+ WOLFSSL_MSG("No extra wolfSSL cmake messages found");
+#endif
+
#ifndef WOLFSSL_MUTEX_INITIALIZER
if (inits_count_mutex_valid == 0) {
+ #if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS
+
+ /* Without this mitigation, if two threads enter wolfSSL_Init() at the
+ * same time, and both see zero inits_count_mutex_valid, then both will
+ * run wc_InitMutex(&inits_count_mutex), leading to process corruption
+ * or (best case) a resource leak.
+ *
+ * When WOLFSSL_ATOMIC_INITIALIZER() is available, we can mitigate this
+ * by use an atomic counting int as a mutex.
+ */
+
+ if (wolfSSL_Atomic_Int_FetchAdd(&inits_count_mutex_atomic_initing_flag,
+ 1) != 0)
+ {
+ (void)wolfSSL_Atomic_Int_FetchSub(
+ &inits_count_mutex_atomic_initing_flag, 1);
+ return DEADLOCK_AVERTED_E;
+ }
+ #endif /* WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS */
if (wc_InitMutex(&inits_count_mutex) != 0) {
WOLFSSL_MSG("Bad Init Mutex count");
+ #if WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS
+ (void)wolfSSL_Atomic_Int_FetchSub(
+ &inits_count_mutex_atomic_initing_flag, 1);
+ #endif
return BAD_MUTEX_E;
}
else {
@@ -6244,13 +6429,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 */
@@ -6273,7 +6458,7 @@ int wolfSSL_Init(void)
#endif
#ifdef WC_RNG_SEED_CB
- wc_SetSeed_Cb(wc_GenerateSeed);
+ wc_SetSeed_Cb(WC_GENERATE_SEED_DEFAULT);
#endif
#ifdef OPENSSL_EXTRA
@@ -6337,29692 +6522,19285 @@ int wolfSSL_Init(void)
#endif
}
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ /* System wide crypto policy disabled by default. */
+ XMEMSET(&crypto_policy, 0, sizeof(crypto_policy));
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
+
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 */
}
return ret;
}
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+/* Helper function for wolfSSL_crypto_policy_enable and
+ * wolfSSL_crypto_policy_enable_buffer.
+ *
+ * Parses the crypto policy string, verifies values,
+ * and sets in global crypto policy struct. Not thread
+ * safe. String length has already been verified.
+ *
+ * Returns WOLFSSL_SUCCESS on success.
+ * Returns CRYPTO_POLICY_FORBIDDEN if already enabled.
+ * Returns < 0 on misc error.
+ * */
+static int crypto_policy_parse(void)
+{
+ const char * hdr = WOLFSSL_SECLEVEL_STR;
+ int sec_level = 0;
+ size_t i = 0;
+
+ /* All policies should begin with "@SECLEVEL=" (N={0..5}) followed
+ * by bulk cipher list. */
+ if (XMEMCMP(crypto_policy.str, hdr, strlen(hdr)) != 0) {
+ WOLFSSL_MSG("error: crypto policy: invalid header");
+ return WOLFSSL_BAD_FILE;
+ }
-#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)
-{
- int ret = 0;
- void* heap = wolfSSL_CTX_GetHeap(ctx, ssl);
-
- if ((type == CA_TYPE) && (ctx == NULL)) {
- WOLFSSL_MSG("Need context for CA load");
- return BAD_FUNC_ARG;
+ {
+ /* Extract the security level. */
+ char * policy_mem = crypto_policy.str;
+ policy_mem += strlen(hdr);
+ sec_level = (int) (*policy_mem - '0');
}
- /* 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
+ if (sec_level < MIN_WOLFSSL_SEC_LEVEL ||
+ sec_level > MAX_WOLFSSL_SEC_LEVEL) {
+ WOLFSSL_MSG_EX("error: invalid SECLEVEL: %d", sec_level);
+ return WOLFSSL_BAD_FILE;
+ }
- /* 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;
+ /* Remove trailing '\r' or '\n'. */
+ for (i = 0; i < MAX_WOLFSSL_CRYPTO_POLICY_SIZE; ++i) {
+ if (crypto_policy.str[i] == '\0') {
+ break;
}
- WOLFSSL_MSG("Processing Cert Chain");
- while (consumed < sz) {
- DerBuffer* part = NULL;
- word32 remain = (word32)(sz - consumed);
- info->consumed = 0;
+ if (crypto_policy.str[i] == '\r' || crypto_policy.str[i] == '\n') {
+ crypto_policy.str[i] = '\0';
+ break;
+ }
+ }
- if (format == WOLFSSL_FILETYPE_PEM) {
- #ifdef WOLFSSL_PEM_TO_DER
- ret = PemToDer(buff + consumed, remain, type, &part,
- heap, info, NULL);
- #else
- ret = NOT_COMPILED_IN;
- #endif
- }
- else {
- int length = remain;
- if (format == WOLFSSL_FILETYPE_ASN1) {
- /* get length of der (read sequence) */
- word32 inOutIdx = 0;
- if (GetSequence(buff + consumed, &inOutIdx, &length,
- remain) < 0) {
- ret = ASN_NO_PEM_HEADER;
- }
- length += inOutIdx; /* include leading sequence */
- }
- info->consumed = length;
- if (ret == 0) {
- ret = AllocDer(&part, length, type, heap);
- if (ret == 0) {
- XMEMCPY(part->buffer, buff + consumed, length);
- }
- }
- }
- if (ret == 0) {
- gotOne = 1;
-#ifdef WOLFSSL_TLS13
- cnt++;
-#endif
- if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) {
- WOLFSSL_MSG(" Cert Chain bigger than buffer. "
- "Consider increasing MAX_CHAIN_DEPTH");
- ret = BUFFER_E;
- }
- else {
- c32to24(part->length, &chainBuffer[idx]);
- idx += CERT_HEADER_SZ;
- XMEMCPY(&chainBuffer[idx], part->buffer, part->length);
- idx += part->length;
- consumed += info->consumed;
- if (used)
- *used += info->consumed;
- }
+ #if defined(DEBUG_WOLFSSL_VERBOSE)
+ WOLFSSL_MSG_EX("info: SECLEVEL=%d", sec_level);
+ WOLFSSL_MSG_EX("info: using crypto-policy file: %s, %ld", policy_file, sz);
+ #endif /* DEBUG_WOLFSSL_VERBOSE */
- /* 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 */
- }
- }
+ crypto_policy.secLevel = sec_level;
+ crypto_policy.enabled = 1;
- FreeDer(&part);
+ return WOLFSSL_SUCCESS;
+}
- if (ret == ASN_NO_PEM_HEADER && gotOne) {
- WOLFSSL_MSG("We got one good cert, so stuff at end ok");
- break;
- }
+#ifndef NO_FILESYSTEM
+/* Enables wolfSSL system wide crypto-policy, using the given policy
+ * file arg. If NULL is passed, then the default system crypto-policy
+ * file that was set at configure time will be used instead.
+ *
+ * While enabled:
+ * - TLS methods, min key sizes, and cipher lists are all configured
+ * automatically by the policy.
+ * - Attempting to use lesser strength parameters will fail with
+ * error CRYPTO_POLICY_FORBIDDEN.
+ *
+ * Disable with wolfSSL_crypto_policy_disable.
+ *
+ * Note: the wolfSSL_crypto_policy_X API are not thread safe, and should
+ * only be called at program init time.
+ *
+ * Returns WOLFSSL_SUCCESS on success.
+ * Returns CRYPTO_POLICY_FORBIDDEN if already enabled.
+ * Returns < 0 on misc error.
+ * */
+int wolfSSL_crypto_policy_enable(const char * policy_file)
+{
+ XFILE file;
+ long sz = 0;
+ size_t n_read = 0;
- 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");
+ WOLFSSL_ENTER("wolfSSL_crypto_policy_enable");
- /* only retain actual size used */
- ret = 0;
- if (idx > 0) {
- if (ssl) {
- if (ssl->buffers.weOwnCertChain) {
- FreeDer(&ssl->buffers.certChain);
- }
- ret = AllocDer(&ssl->buffers.certChain, idx, type, heap);
- if (ret == 0) {
- XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer,
- idx);
- ssl->buffers.weOwnCertChain = 1;
- }
- #ifdef WOLFSSL_TLS13
- ssl->buffers.certChainCnt = cnt;
- #endif
- } else if (ctx) {
- FreeDer(&ctx->certChain);
- ret = AllocDer(&ctx->certChain, idx, type, heap);
- if (ret == 0) {
- XMEMCPY(ctx->certChain->buffer, chainBuffer, idx);
- }
- #ifdef WOLFSSL_TLS13
- ctx->certChainCnt = cnt;
- #endif
- }
- }
+ if (wolfSSL_crypto_policy_is_enabled()) {
+ WOLFSSL_MSG_EX("error: crypto policy already enabled: %s",
+ policy_file);
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
- if (dynamicBuffer)
- XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE);
+ if (policy_file == NULL) {
+ /* Use the configure-time default if NULL passed. */
+ policy_file = WC_STRINGIFY(WOLFSSL_CRYPTO_POLICY_FILE);
}
- return ret;
-}
+ if (policy_file == NULL || *policy_file == '\0') {
+ WOLFSSL_MSG("error: crypto policy empty file");
+ 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 ret;
+ XMEMSET(&crypto_policy, 0, sizeof(crypto_policy));
- (void)devId;
+ file = XFOPEN(policy_file, "rb");
- *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 (file == XBADFILE) {
+ WOLFSSL_MSG_EX("error: crypto policy file open failed: %s",
+ policy_file);
+ return WOLFSSL_BAD_FILE;
+ }
- /* 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;
- }
+ if (XFSEEK(file, 0, XSEEK_END) != 0) {
+ WOLFSSL_MSG_EX("error: crypto policy file seek end failed: %s",
+ policy_file);
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
}
-#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
+
+ sz = XFTELL(file);
+
+ if (XFSEEK(file, 0, XSEEK_SET) != 0) {
+ WOLFSSL_MSG_EX("error: crypto policy file seek failed: %s",
+ policy_file);
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
}
- 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");
- }
- if (ssl) {
- ssl->buffers.keyType = rsa_sa_algo;
- ssl->buffers.keySz = *keySz;
- }
- else {
- ctx->privateKeyType = rsa_sa_algo;
- ctx->privateKeySz = *keySz;
- }
+ if (sz <= 0 || sz > MAX_WOLFSSL_CRYPTO_POLICY_SIZE) {
+ WOLFSSL_MSG_EX("error: crypto policy file %s, invalid size: %ld",
+ policy_file, sz);
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
+ }
- *keyFormat = RSAk;
+ n_read = XFREAD(crypto_policy.str, 1, sz, file);
+ XFCLOSE(file);
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- ssl->options.haveStaticECC = 0;
- *resetSuites = 1;
- }
+ if (n_read != (size_t) sz) {
+ WOLFSSL_MSG_EX("error: crypto policy file %s: read %zu, "
+ "expected %ld", policy_file, n_read, sz);
+ return WOLFSSL_BAD_FILE;
}
- return ret;
-}
-#else
-static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
- DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat,
- void* heap, int devId)
-{
- int ret;
+ crypto_policy.str[n_read] = '\0';
- /* make sure RSA key can be used */
-#ifdef WOLFSSL_SMALL_STACK
- RsaKey* key;
-#else
- RsaKey key[1];
-#endif
+ return crypto_policy_parse();
+}
+#endif /* ! NO_FILESYSTEM */
-#ifdef WOLFSSL_SMALL_STACK
- key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
- if (key == NULL)
- return MEMORY_E;
-#endif
+/* Same behavior as wolfSSL_crypto_policy_enable, but loads
+ * via memory buf instead of file.
+ *
+ * Returns WOLFSSL_SUCCESS on success.
+ * Returns CRYPTO_POLICY_FORBIDDEN if already enabled.
+ * Returns < 0 on misc error.
+ * */
+int wolfSSL_crypto_policy_enable_buffer(const char * buf)
+{
+ size_t sz = 0;
- 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");
- }
+ WOLFSSL_ENTER("wolfSSL_crypto_policy_enable_buffer");
- if (ssl) {
- ssl->buffers.keyType = rsa_sa_algo;
- ssl->buffers.keySz = *keySz;
- }
- else {
- ctx->privateKeyType = rsa_sa_algo;
- ctx->privateKeySz = *keySz;
- }
+ if (wolfSSL_crypto_policy_is_enabled()) {
+ WOLFSSL_MSG_EX("error: crypto policy already enabled");
+ return CRYPTO_POLICY_FORBIDDEN;
+ }
- *keyFormat = RSAk;
+ if (buf == NULL || *buf == '\0') {
+ return BAD_FUNC_ARG;
+ }
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- ssl->options.haveStaticECC = 0;
- *resetSuites = 1;
- }
- }
+ sz = XSTRLEN(buf);
- wc_FreeRsaKey(key);
+ if (sz == 0 || sz > MAX_WOLFSSL_CRYPTO_POLICY_SIZE) {
+ return BAD_FUNC_ARG;
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, heap, DYNAMIC_TYPE_RSA);
-#endif
+ XMEMSET(&crypto_policy, 0, sizeof(crypto_policy));
+ XMEMCPY(crypto_policy.str, buf, sz);
- return ret;
+ return crypto_policy_parse();
}
-#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)
+/* Returns whether the system wide crypto-policy is enabled.
+ *
+ * Returns 1 if enabled.
+ * 0 if disabled.
+ * */
+int wolfSSL_crypto_policy_is_enabled(void)
{
- 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_crypto_policy_is_enabled");
-#ifdef WOLFSSL_SMALL_STACK
- key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC);
- if (key == NULL)
- return MEMORY_E;
-#endif
+ return crypto_policy.enabled == 1;
+}
- 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;
- }
+/* Disables the system wide crypto-policy.
+ * note: SSL and CTX structures already instantiated will
+ * keep their security policy parameters. This will only
+ * affect new instantiations.
+ * */
+void wolfSSL_crypto_policy_disable(void)
+{
+ WOLFSSL_ENTER("wolfSSL_crypto_policy_disable");
+ crypto_policy.enabled = 0;
+ XMEMSET(&crypto_policy, 0, sizeof(crypto_policy));
+ return;
+}
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- *resetSuites = 1;
- }
- }
- else if (*keyFormat == 0) {
- ret = 0; /* continue trying other algorithms */
- }
+/* Get the crypto-policy bulk cipher list string.
+ * String is not owned by caller, should not be freed.
+ *
+ * Returns pointer to bulk cipher list string.
+ * Returns NULL if NOT enabled, or on error.
+ * */
+const char * wolfSSL_crypto_policy_get_ciphers(void)
+{
+ WOLFSSL_ENTER("wolfSSL_crypto_policy_get_ciphers");
- wc_ecc_free(key);
+ if (crypto_policy.enabled == 1) {
+ /* The crypto policy config will have
+ * this form:
+ * "@SECLEVEL=2:kEECDH:kRSA..." */
+ return crypto_policy.str;
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, heap, DYNAMIC_TYPE_ECC);
-#endif
- return ret;
+ return NULL;
}
-#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)
+/* Get the configured crypto-policy security level.
+ * A security level of 0 does not impose any additional
+ * restrictions.
+ *
+ * Returns 1 - 5 if enabled.
+ * Returns 0 if NOT enabled.
+ * */
+int wolfSSL_crypto_policy_get_level(void)
{
- int ret;
- /* make sure Ed25519 key can be used */
-#ifdef WOLFSSL_SMALL_STACK
- ed25519_key* key;
-#else
- ed25519_key key[1];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
- key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
- DYNAMIC_TYPE_ED25519);
- if (key == NULL)
- return MEMORY_E;
-#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;
- }
+ if (crypto_policy.enabled == 1) {
+ return crypto_policy.secLevel;
+ }
- *keyFormat = ED25519k;
- if (ssl != NULL) {
-#if !defined(WOLFSSL_NO_CLIENT_AUTH) && !defined(NO_ED25519_CLIENT_AUTH)
- /* ED25519 requires caching enabled for tracking message
- * hash used in EdDSA_Update for signing */
- ssl->options.cacheMessages = 1;
-#endif
- if (ssl->options.side == WOLFSSL_SERVER_END) {
- *resetSuites = 1;
- }
- }
- }
- }
- else if (*keyFormat == 0) {
- ret = 0; /* continue trying other algorithms */
- }
+ return 0;
+}
- wc_ed25519_free(key);
+/* Get security level from ssl structure.
+ * @param ssl a pointer to WOLFSSL structure
+ */
+int wolfSSL_get_security_level(const WOLFSSL * ssl)
+{
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
}
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, heap, DYNAMIC_TYPE_ED25519);
-#endif
- return ret;
+ return ssl->secLevel;
}
-#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_WOLFSSL_STUB
+/*
+ * Set security level (wolfSSL doesn't support setting the security level).
+ *
+ * The security level can only be set through a system wide crypto-policy
+ * with wolfSSL_crypto_policy_enable().
+ *
+ * @param ssl a pointer to WOLFSSL structure
+ * @param level security level
+ */
+void wolfSSL_set_security_level(WOLFSSL * ssl, int level)
{
- 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_set_security_level");
+ (void)ssl;
+ (void)level;
+}
+#endif /* !NO_WOLFSSL_STUB */
-#ifdef WOLFSSL_SMALL_STACK
- key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448);
- if (key == NULL)
- return MEMORY_E;
-#endif
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
- 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);
- }
+#define WOLFSSL_SSL_LOAD_INCLUDED
+#include
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, heap, DYNAMIC_TYPE_ED448);
-#endif
- return ret;
+#ifndef NO_CERTS
+
+#ifdef HAVE_CRL
+
+int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
+ long sz, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer");
+
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type);
}
-#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)
+
+int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff,
+ long sz, int type)
{
- 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_LoadCRLBuffer");
- 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 == NULL || ssl->ctx == NULL)
+ return BAD_FUNC_ARG;
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- *resetSuites = 1;
- }
- }
- else if (*keyFormat == 0) {
- ret = 0; /* continue trying other algorithms */
- }
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type);
+}
+
+#endif /* HAVE_CRL */
- wc_falcon_free(key);
+#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);
}
- XFREE(key, heap, DYNAMIC_TYPE_FALCON);
- return ret;
+ else
+ return BAD_FUNC_ARG;
}
-#endif
-#if defined(HAVE_DILITHIUM)
-static int ProcessBufferTryDecodeDilithium(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
- DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat,
- void* heap, int type)
+int wolfSSL_DisableOCSP(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;
+ WOLFSSL_ENTER("wolfSSL_DisableOCSP");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerDisableOCSP(SSL_CM(ssl));
}
- 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 (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;
- }
- }
+ else
+ return BAD_FUNC_ARG;
+}
- if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
- *resetSuites = 1;
- }
- }
- else if (*keyFormat == 0) {
- ret = 0; /* continue trying other algorithms */
- }
- wc_dilithium_free(key);
+int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl));
}
- XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM);
+ else
+ return BAD_FUNC_ARG;
+}
- return ret;
+int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerDisableOCSPStapling(SSL_CM(ssl));
+ }
+ else
+ return BAD_FUNC_ARG;
}
-#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)
+int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url)
{
- int ret = 0;
+ WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerSetOCSPOverrideURL(SSL_CM(ssl), url);
+ }
+ else
+ return BAD_FUNC_ARG;
+}
- (void)heap;
- (void)devId;
- (void)type;
- if (ctx == NULL && ssl == NULL)
+int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl,
+ CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx)
+{
+ WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */
+ return wolfSSL_CertManagerSetOCSP_Cb(SSL_CM(ssl),
+ ioCb, respFreeCb, NULL);
+ }
+ else
return BAD_FUNC_ARG;
- if (!der || !keySz || !idx || !resetSuites || !keyFormat)
+}
+
+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;
+}
-#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;
- }
-#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;
- }
-#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 /* 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 /* 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 /* 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;
- }
- }
-#endif /* HAVE_DILITHIUM */
-#endif /* HAVE_PQC */
- return ret;
+
+int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP");
+ if (ctx)
+ return wolfSSL_CertManagerDisableOCSP(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
}
-/* 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
-#ifdef WOLFSSL_SMALL_STACK
- EncryptedInfo* info = NULL;
-#else
- EncryptedInfo info[1];
-#endif
- (void)devId;
- (void)idx;
- (void)keySz;
+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 (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;
+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;
+}
- if (ctx == NULL && ssl == NULL)
+#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;
+}
- /* This API does not handle CHAIN_CERT_TYPE */
- if (type == CHAIN_CERT_TYPE)
+int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling");
+ if (ctx)
+ return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm);
+ else
return BAD_FUNC_ARG;
+}
-#ifdef WOLFSSL_SMALL_STACK
- info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
- DYNAMIC_TYPE_ENCRYPTEDINFO);
- if (info == NULL)
- return MEMORY_E;
-#endif
+int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPMustStaple");
+ if (ctx)
+ return wolfSSL_CertManagerEnableOCSPMustStaple(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
- 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;
- }
-#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 (format == WOLFSSL_FILETYPE_PEM) {
- #ifdef WOLFSSL_PEM_TO_DER
- ret = PemToDer(buff, sz, type, &der, heap, info, &keyFormat);
- #else
- ret = NOT_COMPILED_IN;
- #endif
- }
- else {
- /* ASN1 (DER) */
- int length = (int)sz;
- word32 inOutIdx = 0;
- /* get length of der (read sequence or octet string) */
- if (GetSequence(buff, &inOutIdx, &length, (word32)sz) >= 0) {
- length += inOutIdx; /* include leading sequence */
- }
- /* get length using octet string (allowed for private key types) */
- else if (type == PRIVATEKEY_TYPE &&
- GetOctetString(buff, &inOutIdx, &length, (word32)sz) >= 0) {
- length += inOutIdx; /* include leading oct string */
- }
- else {
- ret = ASN_PARSE_E;
- }
+#endif /* HAVE_OCSP */
- info->consumed = length;
+#ifdef HAVE_CRL
- if (ret == 0) {
- ret = AllocDer(&der, (word32)length, type, heap);
- if (ret == 0) {
- XMEMCPY(der->buffer, buff, length);
- }
-
- #ifdef HAVE_PKCS8
- /* if private key try and remove PKCS8 header */
- if (ret == 0 && type == PRIVATEKEY_TYPE) {
- if ((ret = ToTraditional_ex(der->buffer, der->length,
- &algId)) > 0) {
- /* Found PKCS8 header */
- /* ToTraditional_ex moves buff and returns adjusted length */
- der->length = ret;
- keyFormat = algId;
- }
- ret = 0; /* failures should be ignored */
- }
- #endif
- }
+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;
+}
- if (used) {
- *used = info->consumed;
- }
- /* 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;
- }
- }
+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;
+}
- /* info is only used for private key with DER or PEM, so free now */
- if (ret < 0 || type != PRIVATEKEY_TYPE) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
+#ifndef NO_FILESYSTEM
+int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor)
+{
+ WOLFSSL_ENTER("wolfSSL_LoadCRL");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor);
}
+ else
+ return BAD_FUNC_ARG;
+}
- /* check for error */
- if (ret < 0) {
- FreeDer(&der);
- done = 1;
+int wolfSSL_LoadCRLFile(WOLFSSL* ssl, const char* file, int type)
+{
+ WOLFSSL_ENTER("wolfSSL_LoadCRLFile");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerLoadCRLFile(SSL_CM(ssl), file, type);
}
+ else
+ return BAD_FUNC_ARG;
+}
+#endif
- if (done == 1) {
- /* No operation, just skip the next section */
- }
- /* Handle DER owner */
- else if (type == CA_TYPE) {
- if (ctx == NULL) {
- WOLFSSL_MSG("Need context for CA load");
- FreeDer(&der);
- return BAD_FUNC_ARG;
- }
- /* verify CA unless user set to no verify */
- ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify);
- done = 1;
+int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb)
+{
+ WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerSetCRL_Cb(SSL_CM(ssl), cb);
}
-#ifdef WOLFSSL_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;
+ else
+ return BAD_FUNC_ARG;
+}
+
+int wolfSSL_SetCRL_ErrorCb(WOLFSSL* ssl, crlErrorCb cb, void* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_SetCRL_Cb");
+ if (ssl) {
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerSetCRL_ErrorCb(SSL_CM(ssl), cb, ctx);
}
-#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;
- }
+ 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);
}
- 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);
+ else
+ return BAD_FUNC_ARG;
+}
#endif
- }
- }
-#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);
+
+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;
+}
+
+
+int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL");
+ if (ctx)
+ return wolfSSL_CertManagerDisableCRL(ctx->cm);
+ else
+ return BAD_FUNC_ARG;
+}
+
+
+#ifndef NO_FILESYSTEM
+int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path,
+ int type, int monitor)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
+ if (ctx)
+ return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor);
+ else
+ return BAD_FUNC_ARG;
+}
+
+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
- 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);
+
+
+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;
+}
+
+int wolfSSL_CTX_SetCRL_ErrorCb(WOLFSSL_CTX* ctx, crlErrorCb cb, void* cbCtx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_ErrorCb");
+ if (ctx)
+ return wolfSSL_CertManagerSetCRL_ErrorCb(ctx->cm, cb, cbCtx);
+ else
+ return BAD_FUNC_ARG;
+}
+
+#ifdef HAVE_CRL_IO
+int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb");
+ if (ctx)
+ return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb);
+ else
+ return BAD_FUNC_ARG;
+}
#endif
- }
+
+
+#endif /* HAVE_CRL */
+
+
+/* Sets the max chain depth when verifying a certificate chain. Default depth
+ * is set to MAX_CHAIN_DEPTH.
+ *
+ * ctx WOLFSSL_CTX structure to set depth in
+ * depth max depth
+ */
+void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) {
+ WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
+
+ if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) {
+ WOLFSSL_MSG("Bad depth argument, too large or less than 0");
+ return;
}
-#endif /* WOLFSSL_DUAL_ALG_CERTS */
- else {
- FreeDer(&der);
- return WOLFSSL_BAD_CERTTYPE;
+
+ ctx->verifyDepth = (byte)depth;
+}
+
+
+/* get cert chaining depth using ssl struct */
+long wolfSSL_get_verify_depth(WOLFSSL* ssl)
+{
+ if(ssl == NULL) {
+ return BAD_FUNC_ARG;
}
+#ifndef OPENSSL_EXTRA
+ return MAX_CHAIN_DEPTH;
+#else
+ return ssl->options.verifyDepth;
+#endif
+}
+
- if (done == 1) {
- /* No operation, just skip the next section */
+/* get cert chaining depth using ctx struct */
+long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
+{
+ if (ctx == NULL) {
+ return BAD_FUNC_ARG;
}
- 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
+#ifndef OPENSSL_EXTRA
+ return MAX_CHAIN_DEPTH;
+#else
+ return ctx->verifyDepth;
+#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 */
+#ifndef NO_CHECK_PRIVATE_KEY
- ForceZero(password, passwordSz);
- }
+#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;
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(password, heap, DYNAMIC_TYPE_STRING);
- #elif defined(WOLFSSL_CHECK_MEM_ZERO)
- wc_MemZero_Check(password, NAME_SZ);
+ if (privKey == NULL) {
+ return MISSING_KEY;
+ }
+
+#ifndef NO_RSA
+ if (keyOID == RSAk) {
+ type = DYNAMIC_TYPE_RSA;
+ }
+#ifdef WC_RSA_PSS
+ if (keyOID == RSAPSSk) {
+ type = DYNAMIC_TYPE_RSA;
+ }
+#endif
+#endif
+#ifdef HAVE_ECC
+ if (keyOID == ECDSAk) {
+ type = DYNAMIC_TYPE_ECC;
+ }
+#endif
+#if defined(HAVE_DILITHIUM)
+ if ((keyOID == ML_DSA_LEVEL2k) ||
+ (keyOID == ML_DSA_LEVEL3k) ||
+ (keyOID == ML_DSA_LEVEL5k)
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ || (keyOID == DILITHIUM_LEVEL2k)
+ || (keyOID == DILITHIUM_LEVEL3k)
+ || (keyOID == DILITHIUM_LEVEL5k)
+ #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
+ ) {
+ type = DYNAMIC_TYPE_DILITHIUM;
+ }
+#endif
+#if defined(HAVE_FALCON)
+ if ((keyOID == FALCON_LEVEL1k) ||
+ (keyOID == FALCON_LEVEL5k)) {
+ type = DYNAMIC_TYPE_FALCON;
+ }
+#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 = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx,
- &resetSuites, &keyFormat, heap, devId, type);
+ ) {
+ ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, pubKey, pubSz);
}
- #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
-
- if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
#endif
- return ret;
+ #ifdef HAVE_ECC
+ if (keyOID == ECDSAk) {
+ ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, pubKey, pubSz);
}
- 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);
-#endif
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
#endif
- WOLFSSL_ERROR(WOLFSSL_BAD_FILE);
- return WOLFSSL_BAD_FILE;
+ #if defined(HAVE_DILITHIUM)
+ if ((keyOID == ML_DSA_LEVEL2k) ||
+ (keyOID == ML_DSA_LEVEL3k) ||
+ (keyOID == ML_DSA_LEVEL5k)
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ || (keyOID == DILITHIUM_LEVEL2k)
+ || (keyOID == DILITHIUM_LEVEL3k)
+ || (keyOID == DILITHIUM_LEVEL5k)
+ #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
+ ) {
+ ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey,
+ WC_PQC_SIG_TYPE_DILITHIUM,
+ pubKey, pubSz);
}
-
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
-
- (void)devId;
+ #endif
+ #if defined(HAVE_FALCON)
+ if ((keyOID == FALCON_LEVEL1k) ||
+ (keyOID == FALCON_LEVEL5k)) {
+ ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey,
+ WC_PQC_SIG_TYPE_FALCON,
+ pubKey, pubSz);
+ }
+ #endif
}
- else if (type == CERT_TYPE) {
- #ifdef WOLFSSL_SMALL_STACK
- DecodedCert* cert;
#else
- DecodedCert cert[1];
+ /* devId was set, don't check, for now */
+ /* TODO: Add callback for private key check? */
+ (void) pubKey;
+ (void) pubSz;
#endif
- #ifdef WOLF_PRIVATE_KEY_ID
- int keyType = 0;
+ if (pkey != NULL) {
+ #ifndef NO_RSA
+ if (keyOID == RSAk
+ #ifdef WC_RSA_PSS
+ || keyOID == RSAPSSk
+ #endif
+ ) {
+ wc_FreeRsaKey((RsaKey*)pkey);
+ }
#endif
-
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_E;
+ #ifdef HAVE_ECC
+ if (keyOID == ECDSAk) {
+ wc_ecc_free((ecc_key*)pkey);
+ }
#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 */
-
- 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 */
- }
-
- switch (cert->signatureOID) {
- case CTC_SHAwECDSA:
- case CTC_SHA256wECDSA:
- case CTC_SHA384wECDSA:
- case CTC_SHA512wECDSA:
- case CTC_ED25519:
- case CTC_ED448:
- #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
- case CTC_SM3wSM2:
- #endif
- WOLFSSL_MSG("ECDSA/ED25519/ED448 cert signature");
- if (ssl)
- ssl->options.haveECDSAsig = 1;
- else if (ctx)
- ctx->haveECDSAsig = 1;
- break;
- case CTC_FALCON_LEVEL1:
- case CTC_FALCON_LEVEL5:
- WOLFSSL_MSG("Falcon cert signature");
- if (ssl)
- ssl->options.haveFalconSig = 1;
- else if (ctx)
- ctx->haveFalconSig = 1;
- break;
- case CTC_DILITHIUM_LEVEL2:
- case CTC_DILITHIUM_LEVEL3:
- case CTC_DILITHIUM_LEVEL5:
- WOLFSSL_MSG("Dilithium cert signature");
- if (ssl)
- ssl->options.haveDilithiumSig = 1;
- else if (ctx)
- ctx->haveDilithiumSig = 1;
- break;
- default:
- WOLFSSL_MSG("Not ECDSA cert signature");
- break;
- }
-
- #if 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
+ #if defined(HAVE_DILITHIUM)
+ if ((keyOID == ML_DSA_LEVEL2k) ||
+ (keyOID == ML_DSA_LEVEL3k) ||
+ (keyOID == ML_DSA_LEVEL5k)
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ || (keyOID == DILITHIUM_LEVEL2k)
+ || (keyOID == DILITHIUM_LEVEL3k)
+ || (keyOID == DILITHIUM_LEVEL5k)
+ #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
+ ) {
+ wc_dilithium_free((dilithium_key*)pkey);
}
#endif
-
- /* check key size of cert unless specified not to */
- switch (cert->keyOID) {
- #ifndef NO_RSA
- #ifdef WC_RSA_PSS
- case RSAPSSk:
- #endif
- case RSAk:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = rsa_sa_algo;
- #endif
- /* Determine RSA key size by parsing public key */
- idx = 0;
- ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx,
- cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL);
- if (ret < 0)
- break;
-
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minRsaKeySz < 0 ||
- keySz < (int)ssl->options.minRsaKeySz ||
- keySz > (RSA_MAX_SIZE / 8)) {
- ret = RSA_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate RSA key size too small");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minRsaKeySz < 0 ||
- keySz < (int)ctx->minRsaKeySz ||
- keySz > (RSA_MAX_SIZE / 8)) {
- ret = RSA_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate RSA key size too small");
- }
- }
- break;
- #endif /* !NO_RSA */
- #ifdef HAVE_ECC
- case ECDSAk:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = ecc_dsa_sa_algo;
- #endif
- /* Determine ECC key size based on curve */
- #ifdef WOLFSSL_CUSTOM_CURVES
- if (cert->pkCurveOID == 0 && cert->pkCurveSize != 0) {
- keySz = cert->pkCurveSize * 8;
- }
- else
- #endif
- {
- keySz = wc_ecc_get_curve_size_from_id(
- wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL));
- }
-
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minEccKeySz < 0 ||
- keySz < (int)ssl->options.minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate ECC key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minEccKeySz < 0 ||
- keySz < (int)ctx->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate ECC key size error");
- }
- }
- break;
- #endif /* HAVE_ECC */
- #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
- case SM2k:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = sm2_sa_algo;
- #endif
- /* Determine ECC key size based on curve */
- keySz = wc_ecc_get_curve_size_from_id(
- wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL));
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minEccKeySz < 0 ||
- keySz < (int)ssl->options.minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Ed key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minEccKeySz < 0 ||
- keySz < (int)ctx->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate ECC key size error");
- }
- }
- break;
- #endif /* HAVE_ED25519 */
- #ifdef HAVE_ED25519
- case ED25519k:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = ed25519_sa_algo;
- #endif
- /* ED25519 is fixed key size */
- keySz = ED25519_KEY_SIZE;
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minEccKeySz < 0 ||
- keySz < (int)ssl->options.minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Ed key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minEccKeySz < 0 ||
- keySz < (int)ctx->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate ECC key size error");
- }
- }
- break;
- #endif /* HAVE_ED25519 */
- #ifdef HAVE_ED448
- case ED448k:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = ed448_sa_algo;
- #endif
- /* ED448 is fixed key size */
- keySz = ED448_KEY_SIZE;
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minEccKeySz < 0 ||
- keySz < (int)ssl->options.minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Ed key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minEccKeySz < 0 ||
- keySz < (int)ctx->minEccKeySz) {
- ret = ECC_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate ECC key size error");
- }
- }
- break;
- #endif /* HAVE_ED448 */
- #if defined(HAVE_PQC)
- #if defined(HAVE_FALCON)
- case FALCON_LEVEL1k:
- case FALCON_LEVEL5k:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = falcon_level5_sa_algo;
- #endif
- /* Falcon is fixed key size */
- keySz = FALCON_MAX_KEY_SIZE;
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minFalconKeySz < 0 ||
- keySz < (int)ssl->options.minFalconKeySz) {
- ret = FALCON_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Falcon key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minFalconKeySz < 0 ||
- keySz < (int)ctx->minFalconKeySz) {
- ret = FALCON_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Falcon key size error");
- }
- }
- break;
- #endif /* HAVE_FALCON */
- #if defined(HAVE_DILITHIUM)
- case DILITHIUM_LEVEL2k:
- case DILITHIUM_LEVEL3k:
- case DILITHIUM_LEVEL5k:
- #ifdef WOLF_PRIVATE_KEY_ID
- keyType = dilithium_level5_sa_algo;
- #endif
- /* Dilithium is fixed key size */
- keySz = DILITHIUM_MAX_KEY_SIZE;
- if (ssl && !ssl->options.verifyNone) {
- if (ssl->options.minDilithiumKeySz < 0 ||
- keySz < (int)ssl->options.minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Dilithium key size error");
- }
- }
- else if (ctx && !ctx->verifyNone) {
- if (ctx->minDilithiumKeySz < 0 ||
- keySz < (int)ctx->minDilithiumKeySz) {
- ret = DILITHIUM_KEY_SIZE_E;
- WOLFSSL_MSG("Certificate Dilithium key size error");
- }
- }
- break;
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
-
- default:
- WOLFSSL_MSG("No key size check done on certificate");
- break; /* do no check if not a case for the key */
- }
-
- #ifdef WOLF_PRIVATE_KEY_ID
- if (ssl != NULL) {
- ssl->buffers.keyType = (byte)keyType;
- ssl->buffers.keySz = keySz;
- }
- else if (ctx != NULL) {
- ctx->privateKeyType = (byte)keyType;
- ctx->privateKeySz = keySz;
+ #if defined(HAVE_FALCON)
+ if ((keyOID == FALCON_LEVEL1k) ||
+ (keyOID == FALCON_LEVEL5k)) {
+ wc_falcon_free((falcon_key*)pkey);
}
#endif
-
- FreeDecodedCert(cert);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
- #endif
-
- if (ret != 0) {
- done = 1;
- }
+ XFREE(pkey, heap, type);
}
- if (done == 1) {
- #if !defined(NO_WOLFSSL_CM_VERIFY) && (!defined(NO_WOLFSSL_CLIENT) || \
- !defined(WOLFSSL_NO_CLIENT_AUTH))
- if ((type == CA_TYPE) || (type == CERT_TYPE)) {
- /* Call to over-ride status */
- if ((ctx != NULL) && (ctx->cm != NULL) &&
- (ctx->cm->verifyCallback != NULL)) {
- ret = CM_VerifyBuffer_ex(ctx->cm, buff,
- sz, format, (ret == WOLFSSL_SUCCESS ? 0 : ret));
- }
- }
- #endif /* NO_WOLFSSL_CM_VERIFY */
+ return ret;
+}
+#endif /* WOLF_PRIVATE_KEY_ID */
- return ret;
- }
+/* Check private against public in certificate for match
+ *
+ * Returns WOLFSSL_SUCCESS on good private key
+ * WOLFSSL_FAILURE if mismatched */
+static int check_cert_key(const DerBuffer* cert, const DerBuffer* key,
+ const DerBuffer* altKey, void* heap, int devId, int isKeyLabel, int isKeyId,
+ int altDevId, int isAltKeyLabel, int isAltKeyId)
+{
+ WC_DECLARE_VAR(der, DecodedCert, 1, 0);
+ word32 size;
+ byte* buff;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ WOLFSSL_ENTER("check_cert_key");
- if (ssl && resetSuites) {
- word16 havePSK = 0;
- word16 haveRSA = 0;
+ if (cert == NULL || key == NULL) {
+ return WOLFSSL_FAILURE;
+ }
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (ssl->options.havePSK) {
- havePSK = 1;
- }
- #endif
- #ifndef NO_RSA
- haveRSA = 1;
- #endif
- keySz = ssl->buffers.keySz;
+ WC_ALLOC_VAR_EX(der, DecodedCert, 1, heap, DYNAMIC_TYPE_DCERT,
+ return MEMORY_E);
- 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);
+ size = cert->length;
+ buff = cert->buffer;
+ InitDecodedCert_ex(der, buff, size, heap, devId);
+ if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL, NULL) != 0) {
+ FreeDecodedCert(der);
+ WC_FREE_VAR_EX(der, heap, DYNAMIC_TYPE_DCERT);
+ return WOLFSSL_FAILURE;
}
- else if (ctx && resetSuites) {
- word16 havePSK = 0;
- word16 haveRSA = 0;
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (ctx->havePSK) {
- havePSK = 1;
+ size = key->length;
+ buff = key->buffer;
+#ifdef WOLF_PRIVATE_KEY_ID
+ if (devId != INVALID_DEVID) {
+ ret = check_cert_key_dev(der->keyOID, buff, size, der->publicKey,
+ der->pubKeySize, isKeyLabel, isKeyId, heap,
+ devId);
+ if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
+ ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
}
- #endif
- #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);
+ }
+ else {
+ /* fall through if unavailable */
+ ret = CRYPTOCB_UNAVAILABLE;
}
- return WOLFSSL_SUCCESS;
-}
-
-
-/* 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)
-{
- long used = 0;
- int ret = 0;
- int gotOne = 0;
-
- WOLFSSL_MSG("Processing CA PEM file");
- while (used < sz) {
- long consumed = 0;
-
- ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl,
- &consumed, 0, verify);
+ if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
+#endif /* WOLF_PRIVATE_KEY_ID */
+ {
+ ret = wc_CheckPrivateKeyCert(buff, size, der, 0, heap);
+ ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
+ }
- if (ret == MEMORY_E) {
- return ret;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ if (ret == WOLFSSL_SUCCESS && der->extSapkiSet && der->sapkiDer != NULL) {
+ /* Certificate contains an alternative public key. Hence, we also
+ * need an alternative private key. */
+ if (altKey == NULL) {
+ ret = MISSING_KEY;
+ buff = NULL;
+ size = 0;
}
- else 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;
+ else {
+ size = altKey->length;
+ buff = altKey->buffer;
+ }
+#ifdef WOLF_PRIVATE_KEY_ID
+ if (ret == WOLFSSL_SUCCESS && altDevId != INVALID_DEVID) {
+ /* We have to decode the public key first */
+ /* Default to max pub key size. */
+ word32 pubKeyLen = MAX_PUBLIC_KEY_SZ;
+ byte* decodedPubKey = (byte*)XMALLOC(pubKeyLen, heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (decodedPubKey == NULL) {
+ ret = MEMORY_E;
}
-#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");
+ 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 {
+ #if defined(WC_ENABLE_ASYM_KEY_IMPORT)
+ word32 idx = 0;
+ ret = DecodeAsymKeyPublic(der->sapkiDer, &idx,
+ der->sapkiLen, decodedPubKey,
+ &pubKeyLen, der->sapkiOID);
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif /* WC_ENABLE_ASYM_KEY_IMPORT */
+ }
}
- else {
- WOLFSSL_MSG("CA Parse failed, no progress in file.");
- WOLFSSL_MSG("Do not continue search for other certs in file");
- break;
+ if (ret == 0) {
+ ret = check_cert_key_dev(der->sapkiOID, buff, size,
+ decodedPubKey, pubKeyLen,
+ isAltKeyLabel, isAltKeyId,
+ heap, altDevId);
+ }
+ XFREE(decodedPubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
+ ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
}
}
else {
- WOLFSSL_MSG(" Processed a CA");
- gotOne = 1;
+ /* fall through if unavailable */
+ ret = CRYPTOCB_UNAVAILABLE;
}
- used += consumed;
- }
- if (gotOne) {
- WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK");
- return WOLFSSL_SUCCESS;
+ if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
+#endif /* WOLF_PRIVATE_KEY_ID */
+ {
+ ret = wc_CheckPrivateKeyCert(buff, size, der, 1, heap);
+ ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
+ }
}
- return ret;
-}
+#endif /* WOLFSSL_DUAL_ALG_CERTS */
+ FreeDecodedCert(der);
+ WC_FREE_VAR_EX(der, heap, DYNAMIC_TYPE_DCERT);
+ (void)devId;
+ (void)isKeyLabel;
+ (void)isKeyId;
+ (void)altKey;
+ (void)altDevId;
+ (void)isAltKeyLabel;
+ (void)isAltKeyId;
-#ifdef HAVE_CRL
+ return ret;
+}
-int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
- long sz, int type)
+/* 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)
{
- WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer");
+ int res = WOLFSSL_SUCCESS;
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ DerBuffer *privateKey;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ DerBuffer *altPrivateKey;
+#endif
+#else
+ const DerBuffer *privateKey;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ const DerBuffer *altPrivateKey;
+#endif
+#endif
- if (ctx == NULL)
- return BAD_FUNC_ARG;
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
+ }
- return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type);
-}
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ privateKey = wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask);
+ altPrivateKey = wolfssl_priv_der_unblind(ctx->altPrivateKey,
+ ctx->altPrivateKeyMask);
+ if ((privateKey == NULL) || (altPrivateKey == NULL)) {
+ res = WOLFSSL_FAILURE;
+ }
+#else
+ privateKey = ctx->privateKey;
+ altPrivateKey = ctx->altPrivateKey;
+#endif
+ if (res == WOLFSSL_SUCCESS) {
+ res = check_cert_key(ctx->certificate, privateKey, altPrivateKey,
+ ctx->heap, ctx->privateKeyDevId, ctx->privateKeyLabel,
+ ctx->privateKeyId, ctx->altPrivateKeyDevId,
+ ctx->altPrivateKeyLabel, ctx->altPrivateKeyId) != 0;
+ }
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_unblind_free(privateKey);
+ wolfssl_priv_der_unblind_free(altPrivateKey);
+#endif
+#else
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ privateKey = wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask);
+ if (privateKey == NULL) {
+ res = WOLFSSL_FAILURE;
+ }
+#else
+ privateKey = ctx->privateKey;
+#endif
+ if (res == WOLFSSL_SUCCESS) {
+ res = check_cert_key(ctx->certificate, privateKey, NULL, ctx->heap,
+ ctx->privateKeyDevId, ctx->privateKeyLabel,
+ ctx->privateKeyId, INVALID_DEVID, 0, 0);
+ }
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_unblind_free(privateKey);
+#endif
+#endif
+ /* placing error into error queue for Python port */
+ if (res != WOLFSSL_SUCCESS) {
+ WOLFSSL_ERROR(WC_KEY_MISMATCH_E);
+ }
-int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff,
- long sz, int type)
+ return res;
+}
+#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.
+ *
+ * Note, even though the supplied ctx pointer is designated const, on success
+ * ctx->privateKeyPKey is changed by this call. The change is done safely using
+ * a hardware-synchronized store.
+ */
+WOLFSSL_EVP_PKEY* wolfSSL_CTX_get0_privatekey(const WOLFSSL_CTX* ctx)
{
- WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer");
+ WOLFSSL_EVP_PKEY* res;
+ const unsigned char *key;
+ int type;
- if (ssl == NULL || ssl->ctx == NULL)
- return BAD_FUNC_ARG;
+ WOLFSSL_ENTER("wolfSSL_CTX_get0_privatekey");
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type);
-}
+ if (ctx == NULL || ctx->privateKey == NULL ||
+ ctx->privateKey->buffer == NULL) {
+ WOLFSSL_MSG("Bad parameter or key not set");
+ return NULL;
+ }
-#endif /* HAVE_CRL */
+ switch (ctx->privateKeyType) {
+#ifndef NO_RSA
+ case rsa_sa_algo:
+ type = WC_EVP_PKEY_RSA;
+ break;
+#endif
+#ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ type = WC_EVP_PKEY_EC;
+ break;
+#endif
+#ifdef WOLFSSL_SM2
+ case sm2_sa_algo:
+ type = WC_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;
+ }
-#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 (ctx->privateKeyPKey != NULL) {
+ res = ctx->privateKeyPKey;
}
- else
- return BAD_FUNC_ARG;
+ else {
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ DerBuffer *unblinded_privateKey =
+ wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask);
+ if (unblinded_privateKey == NULL)
+ return NULL;
+ key = unblinded_privateKey->buffer;
+ #else
+ key = ctx->privateKey->buffer;
+ #endif
+ res = wolfSSL_d2i_PrivateKey(type, NULL, &key,
+ (long)ctx->privateKey->length);
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_unblind_free(unblinded_privateKey);
+ #endif
+ if (res) {
+#ifdef WOLFSSL_ATOMIC_OPS
+ WOLFSSL_EVP_PKEY *current_pkey = NULL;
+ if (! wolfSSL_Atomic_Ptr_CompareExchange(
+ (void **)&ctx->privateKeyPKey,
+ (void **)¤t_pkey, res))
+ {
+ wolfSSL_EVP_PKEY_free(res);
+ res = current_pkey;
+ }
+#else
+ ((WOLFSSL_CTX *)ctx)->privateKeyPKey = res;
+#endif
+ }
+ }
+
+ return res;
}
+#endif
-int wolfSSL_DisableOCSP(WOLFSSL* ssl)
+#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_ENTER("wolfSSL_DisableOCSP");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerDisableOCSP(SSL_CM(ssl));
+ 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) {
+ WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA);
+ return 0;
}
- else
- return BAD_FUNC_ARG;
-}
+ /* 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);
+ WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA);
+ if (!isRsaKey) {
+ return WOLFSSL_FATAL_ERROR;
+ }
-int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl)
-{
- WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl));
+ if (*out != NULL) {
+ pkey = *out;
+ }
+ else {
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey == NULL) {
+ WOLFSSL_MSG("RSA wolfSSL_EVP_PKEY_new error");
+ return 0;
+ }
}
- else
- return BAD_FUNC_ARG;
-}
-int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl)
-{
- WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerDisableOCSPStapling(SSL_CM(ssl));
+ pkey->pkey_sz = (int)keyIdx;
+ pkey->pkey.ptr = (char*)XMALLOC((size_t)memSz, NULL,
+ priv ? DYNAMIC_TYPE_PRIVATE_KEY :
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkey->pkey.ptr == NULL) {
+ ret = 0;
}
- else
- return BAD_FUNC_ARG;
-}
+ if (ret == 1) {
+ XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+ pkey->type = WC_EVP_PKEY_RSA;
-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);
+ 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
- return BAD_FUNC_ARG;
-}
+ if (ret == 1) {
+ *out = pkey;
+ }
-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 ((ret == 0) && (*out == NULL)) {
+ wolfSSL_EVP_PKEY_free(pkey);
}
- else
- return BAD_FUNC_ARG;
+ return ret;
}
+#endif /* !NO_RSA */
-
-int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options)
+#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
+static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
{
- WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP");
- if (ctx)
- return wolfSSL_CertManagerEnableOCSP(ctx->cm, options);
- else
- return BAD_FUNC_ARG;
-}
+ 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));
-int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP");
- if (ctx)
- return wolfSSL_CertManagerDisableOCSP(ctx->cm);
- else
- return BAD_FUNC_ARG;
-}
+ if (wc_ecc_init(ecc) != 0) {
+ WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC);
+ return 0;
+ }
+ if (priv) {
+ isEccKey =
+ (wc_EccPrivateKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0);
+ }
+ else {
+ isEccKey =
+ (wc_EccPublicKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0);
+ }
+ wc_ecc_free(ecc);
+ WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC);
-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 (!isEccKey) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ if (*out != NULL) {
+ pkey = *out;
+ }
+ else {
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey == NULL) {
+ WOLFSSL_MSG("ECC wolfSSL_EVP_PKEY_new error");
+ return 0;
+ }
+ }
-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;
-}
+ pkey->pkey_sz = (int)keyIdx;
+ pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL,
+ priv ? DYNAMIC_TYPE_PRIVATE_KEY :
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkey->pkey.ptr == NULL) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ XMEMCPY(pkey->pkey.ptr, mem, keyIdx);
+ pkey->type = WC_EVP_PKEY_EC;
-#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;
+ pkey->ownEcc = 1;
+ pkey->ecc = wolfSSL_EC_KEY_new();
+ if (pkey->ecc == NULL) {
+ ret = 0;
+ }
+ }
+ if ((ret == 1) && (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc,
+ (const unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE
+ : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ *out = pkey;
+ }
+
+ if ((ret == 0) && (*out == NULL)) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ }
+ return ret;
}
+#endif /* HAVE_ECC && OPENSSL_EXTRA */
-int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx)
+#if !defined(NO_DSA)
+static int d2iTryDsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
{
- WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling");
- if (ctx)
- return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm);
- else
- return BAD_FUNC_ARG;
-}
-
-int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPMustStaple");
- if (ctx)
- return wolfSSL_CertManagerEnableOCSPMustStaple(ctx->cm);
- else
- return BAD_FUNC_ARG;
-}
-
-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 */
-
-#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
-
-/* process a file with name fname into ctx of format and type
- userChain specifies a user certificate chain to pass during handshake */
-int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
- WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl, int verify)
-{
-#ifdef WOLFSSL_SMALL_STACK
- byte staticBuffer[1]; /* force heap usage */
+ WOLFSSL_EVP_PKEY* pkey;
+ word32 keyIdx = 0;
+ int isDsaKey;
+ int ret = 1;
+#ifndef WOLFSSL_SMALL_STACK
+ DsaKey dsa[1];
#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;
+ DsaKey *dsa = (DsaKey*)XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA);
+ if (dsa == NULL)
+ return 0;
#endif
- (void)crl;
- (void)heapHint;
+ XMEMSET(dsa, 0, sizeof(DsaKey));
- if (fname == NULL) return WOLFSSL_BAD_FILE;
+ if (wc_InitDsaKey(dsa) != 0) {
+ WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA);
+ return 0;
+ }
- file = XFOPEN(fname, "rb");
- if (file == XBADFILE) return WOLFSSL_BAD_FILE;
- if (XFSEEK(file, 0, XSEEK_END) != 0) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
+ if (priv) {
+ isDsaKey =
+ (wc_DsaPrivateKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0);
}
- sz = XFTELL(file);
- if (XFSEEK(file, 0, XSEEK_SET) != 0) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
+ else {
+ isDsaKey =
+ (wc_DsaPublicKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0);
}
+ wc_FreeDsaKey(dsa);
+ WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA);
- if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
- WOLFSSL_MSG("ProcessFile file size error");
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
+ /* test if DSA key */
+ if (!isDsaKey) {
+ return WOLFSSL_FATAL_ERROR;
}
- if (sz > (long)sizeof(staticBuffer)) {
- WOLFSSL_MSG("Getting dynamic buffer");
- myBuffer = (byte*)XMALLOC(sz, heapHint, DYNAMIC_TYPE_FILE);
- if (myBuffer == NULL) {
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
- dynamic = 1;
+ if (*out != NULL) {
+ pkey = *out;
}
-
- 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;
- }
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey == NULL) {
+ WOLFSSL_MSG("DSA wolfSSL_EVP_PKEY_new error");
+ return 0;
}
- if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE)
- && format == WOLFSSL_FILETYPE_PEM) {
- ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl,
- verify);
+ }
+
+ pkey->pkey_sz = (int)keyIdx;
+ pkey->pkey.ptr = (char*)XMALLOC((size_t)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 = WC_EVP_PKEY_DSA;
+
+ pkey->ownDsa = 1;
+ pkey->dsa = wolfSSL_DSA_new();
+ if (pkey->dsa == NULL) {
+ ret = 0;
}
-#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);
+ if ((ret == 1) && (wolfSSL_DSA_LoadDer_ex(pkey->dsa,
+ (const unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE
+ : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ *out = pkey;
+ }
+ if ((ret == 0) && (*out == NULL)) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ }
return ret;
}
+#endif /* NO_DSA */
-/* 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)
+#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)
{
- int ret = WOLFSSL_SUCCESS;
-#ifndef NO_WOLFSSL_DIR
- int successCount = 0;
+ 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
- int verify;
- WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex");
+ XMEMSET(dh, 0, sizeof(DhKey));
- if (ctx == NULL || (file == NULL && path == NULL)) {
- return WOLFSSL_FAILURE;
+ if (wc_InitDhKey(dh) != 0) {
+ WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
+ return 0;
}
- verify = GET_VERIFY_SETTING_CTX(ctx);
- if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)
- verify = VERIFY_SKIP_DATE;
+ isDhKey = (wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz) == 0);
+ wc_FreeDhKey(dh);
+ WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
- 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
+ /* test if DH key */
+ if (!isDhKey) {
+ return WOLFSSL_FATAL_ERROR;
}
- 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);
+ if (*out != NULL) {
+ pkey = *out;
+ }
+ else {
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey == NULL) {
+ WOLFSSL_MSG("DH wolfSSL_EVP_PKEY_new error");
+ return 0;
}
- 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;
+ pkey->pkey_sz = (int)memSz;
+ pkey->pkey.ptr = (char*)XMALLOC((size_t)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, (size_t)memSz);
+ pkey->type = WC_EVP_PKEY_DH;
+
+ pkey->ownDh = 1;
+ pkey->dh = wolfSSL_DH_new();
+ if (pkey->dh == NULL) {
+ ret = 0;
}
+ }
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
- #endif
-#else
- ret = NOT_COMPILED_IN;
- (void)flags;
-#endif
+ if ((ret == 1) && (wolfSSL_DH_LoadDer(pkey->dh,
+ (const unsigned char*)pkey->pkey.ptr,
+ pkey->pkey_sz) != WOLFSSL_SUCCESS)) {
+ ret = 0;
+ }
+ if (ret == 1) {
+ *out = pkey;
}
+ if ((ret == 0) && (*out == NULL)) {
+ wolfSSL_EVP_PKEY_free(pkey);
+ }
return ret;
}
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
-WOLFSSL_ABI
-int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
- const char* path)
+#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)
{
- int ret = wolfSSL_CTX_load_verify_locations_ex(ctx, file, path,
- WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
-
- return WS_RETURN_CODE(ret,WOLFSSL_FAILURE);
-}
-
-#ifdef WOLFSSL_SYS_CA_CERTS
+ 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));
-#ifdef USE_WINDOWS_API
+ /* test if DH-public key */
+ if (wc_InitDhKey(dh) != 0) {
+ WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
+ return 0;
+ }
-static int LoadSystemCaCertsWindows(WOLFSSL_CTX* ctx, byte* loaded)
-{
- int ret = WOLFSSL_SUCCESS;
- word32 i;
- HANDLE handle = NULL;
- PCCERT_CONTEXT certCtx = NULL;
- LPCSTR storeNames[2] = {"ROOT", "CA"};
- HCRYPTPROV_LEGACY hProv = (HCRYPTPROV_LEGACY)NULL;
+ ret = wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz);
+ wc_FreeDhKey(dh);
+ WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH);
- if (ctx == NULL || loaded == NULL) {
- ret = WOLFSSL_FAILURE;
+ if (ret != 0) {
+ return WOLFSSL_FATAL_ERROR;
}
- 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 (*out != NULL) {
+ pkey = *out;
+ }
+ else {
+ pkey = wolfSSL_EVP_PKEY_new();
+ if (pkey == NULL) {
+ return 0;
}
+ }
- if (handle != NULL && !CertCloseStore(handle, 0)) {
- WOLFSSL_MSG_EX("Failed to close cert store %s.", storeNames[i]);
- ret = WOLFSSL_FAILURE;
+ ret = 1;
+ pkey->type = WC_EVP_PKEY_DH;
+ pkey->pkey_sz = (int)memSz;
+ pkey->pkey.ptr = (char*)XMALLOC((size_t)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, (size_t)memSz);
+ pkey->ownDh = 1;
+ pkey->dh = wolfSSL_DH_new();
+ if (pkey->dh == NULL) {
+ ret = 0;
}
}
- return ret;
-}
-
-#elif defined(__APPLE__)
-
-#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) \
- && !defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION)
-/*
- * Manually obtains certificates from the system trust store and loads them
- * directly into wolfSSL "the old way".
- *
- * As of MacOS 14.0 we are still able to use this method to access system
- * certificates. Accessibility of this API is indicated by the presence of the
- * Security/SecTrustSettings.h header. In the likely event that Apple removes
- * access to this API on Macs, this function should be removed and the
- * DoAppleNativeCertValidation() routine should be used for all devices.
- */
-static int LoadSystemCaCertsMac(WOLFSSL_CTX* ctx, byte* loaded)
-{
- int ret = WOLFSSL_SUCCESS;
- word32 i;
- const unsigned int trustDomains[] = {
- kSecTrustSettingsDomainUser,
- kSecTrustSettingsDomainAdmin,
- kSecTrustSettingsDomainSystem
- };
- CFArrayRef certs;
- OSStatus stat;
- CFIndex numCerts;
- CFDataRef der;
- CFIndex j;
+ if (ret == 1) {
+ key = (DhKey*)pkey->dh->internal;
- if (ctx == NULL || loaded == NULL) {
- ret = WOLFSSL_FAILURE;
+ keyIdx = 0;
+ if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) {
+ ret = 0;
+ }
}
- 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;
- }
-
- CFRelease(der);
- }
- }
-
- CFRelease(certs);
- }
- else if (stat == errSecNoTrustSettings) {
- WOLFSSL_MSG_EX("No trust settings for domain %d, moving to next "
- "domain.", trustDomains[i]);
+ if (ret == 1) {
+ elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB;
+ if (priv) {
+ elements |= ELEMENT_PRV;
}
- else {
- WOLFSSL_MSG_EX("SecTrustSettingsCopyCertificates failed with"
- " status %d.", stat);
- ret = WOLFSSL_FAILURE;
- break;
+ 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 /* defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) */
-
-#else
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */
-/* Potential system CA certs directories on Linux/Unix distros. */
-static const char* systemCaDirs[] = {
-#if defined(__ANDROID__) || defined(ANDROID)
- "/system/etc/security/cacerts" /* Android */
+#ifdef HAVE_FALCON
+static int d2iTryFalconKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, int priv)
+{
+ WOLFSSL_EVP_PKEY* pkey;
+ int isFalcon = 0;
+#ifndef WOLFSSL_SMALL_STACK
+ falcon_key falcon[1];
#else
- "/etc/ssl/certs", /* Debian, Ubuntu, Gentoo, others */
- "/etc/pki/ca-trust/source/anchors", /* Fedora, RHEL */
- "/etc/pki/tls/certs" /* Older RHEL */
+ falcon_key *falcon = (falcon_key *)XMALLOC(sizeof(falcon_key), NULL,
+ DYNAMIC_TYPE_FALCON);
+ if (falcon == NULL) {
+ return 0;
+ }
#endif
-};
-const char** wolfSSL_get_system_CA_dirs(word32* num)
-{
- const char** ret;
+ if (wc_falcon_init(falcon) != 0) {
+ WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON);
+ return 0;
+ }
- if (num == NULL) {
- ret = NULL;
+ /* 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 {
- ret = systemCaDirs;
- *num = sizeof(systemCaDirs)/sizeof(*systemCaDirs);
- }
-
- return ret;
-}
+ /* Try level 1 */
+ isFalcon = ((wc_falcon_set_level(falcon, 1) == 0) &&
+ (wc_falcon_import_public(mem, (word32)memSz, falcon) == 0));
-static int LoadSystemCaCertsNix(WOLFSSL_CTX* ctx, byte* loaded) {
- int ret = WOLFSSL_SUCCESS;
- word32 i;
+ 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);
+ WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON);
- if (ctx == NULL || loaded == NULL) {
- ret = WOLFSSL_FAILURE;
+ if (!isFalcon) {
+ return WOLFSSL_FATAL_ERROR;
}
- 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]);
- }
- else {
- WOLFSSL_MSG_EX("Loaded CA certs from %s.",
- systemCaDirs[i]);
- *loaded = 1;
- /* Stop searching after we've loaded one directory. */
- break;
+ if (*out != NULL) {
+ pkey = *out;
+ }
+ 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 = WC_EVP_PKEY_FALCON;
+ pkey->pkey.ptr = NULL;
+ pkey->pkey_sz = 0;
- return ret;
-}
+ *out = pkey;
+ return 1;
-#endif
+}
+#endif /* HAVE_FALCON */
-int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx)
+#ifdef HAVE_DILITHIUM
+static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem,
+ long memSz, 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) */
-
+ WOLFSSL_EVP_PKEY* pkey;
+ int isDilithium = 0;
+#ifndef WOLFSSL_SMALL_STACK
+ dilithium_key dilithium[1];
#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"
+ dilithium_key *dilithium = (dilithium_key *)
+ XMALLOC(sizeof(dilithium_key), NULL, DYNAMIC_TYPE_DILITHIUM);
+ if (dilithium == NULL) {
+ return 0;
+ }
#endif
-#else
-
- ret = LoadSystemCaCertsNix(ctx, &loaded);
+ if (wc_dilithium_init(dilithium) != 0) {
+ WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
+ return 0;
+ }
-#endif
-
- if (ret == WOLFSSL_SUCCESS && !loaded) {
- ret = WOLFSSL_BAD_PATH;
+ /* Test if Dilithium key. Try all levels. */
+ if (priv) {
+ isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_44) == 0) &&
+ (wc_dilithium_import_private(mem,
+ (word32)memSz, dilithium) == 0));
+ if (!isDilithium) {
+ isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_65) == 0) &&
+ (wc_dilithium_import_private(mem,
+ (word32)memSz, dilithium) == 0));
+ }
+ if (!isDilithium) {
+ isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_87) == 0) &&
+ (wc_dilithium_import_private(mem,
+ (word32)memSz, dilithium) == 0));
+ }
}
+ else {
+ isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_44) == 0) &&
+ (wc_dilithium_import_public(mem, (word32)memSz,
+ dilithium) == 0));
+ if (!isDilithium) {
+ isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_65) == 0) &&
+ (wc_dilithium_import_public(mem, (word32)memSz,
+ dilithium) == 0));
+ }
+ if (!isDilithium) {
+ isDilithium = ((wc_dilithium_set_level(dilithium, WC_ML_DSA_87) == 0) &&
+ (wc_dilithium_import_public(mem, (word32)memSz,
+ dilithium) == 0));
+ }
+ }
+ wc_dilithium_free(dilithium);
+ WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
- WOLFSSL_LEAVE("wolfSSL_CTX_load_system_CA_certs", ret);
-
- return ret;
-}
-
-#endif /* WOLFSSL_SYS_CA_CERTS */
-
-#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");
+ if (!isDilithium) {
+ return WOLFSSL_FATAL_ERROR;
+ }
- if (ctx == NULL || file == NULL) {
- return WOLFSSL_FAILURE;
+ 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 = WC_EVP_PKEY_DILITHIUM;
+ pkey->pkey.ptr = NULL;
+ pkey->pkey_sz = 0;
- return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL,
- GET_VERIFY_SETTING_CTX(ctx));
+ *out = pkey;
+ return 1;
}
+#endif /* HAVE_DILITHIUM */
-int wolfSSL_trust_peer_cert(WOLFSSL* ssl, const char* file, int type)
+static WOLFSSL_EVP_PKEY* d2iGenericKey(WOLFSSL_EVP_PKEY** out,
+ const unsigned char** in, long inSz, int priv)
{
- WOLFSSL_ENTER("wolfSSL_trust_peer_cert");
-
- if (ssl == NULL || file == NULL) {
- return WOLFSSL_FAILURE;
- }
+ WOLFSSL_EVP_PKEY* pkey = NULL;
- return ProcessFile(NULL, file, type, TRUSTED_PEER_TYPE, ssl, 0, NULL,
- GET_VERIFY_SETTING_SSL(ssl));
-}
-#endif /* WOLFSSL_TRUST_PEER_CERT */
+ WOLFSSL_ENTER("d2iGenericKey");
-#endif /* NO_FILESYSTEM */
+ if (in == NULL || *in == NULL || inSz < 0) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
-#ifdef HAVE_CRL
+ if ((out != NULL) && (*out != NULL)) {
+ pkey = *out;
+ }
-int wolfSSL_EnableCRL(WOLFSSL* ssl, int options)
-{
- WOLFSSL_ENTER("wolfSSL_EnableCRL");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerEnableCRL(SSL_CM(ssl), options);
+#if !defined(NO_RSA)
+ if (d2iTryRsaKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
}
else
- return BAD_FUNC_ARG;
-}
-
-
-int wolfSSL_DisableCRL(WOLFSSL* ssl)
-{
- WOLFSSL_ENTER("wolfSSL_DisableCRL");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerDisableCRL(SSL_CM(ssl));
+#endif /* NO_RSA */
+#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
+ if (d2iTryEccKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
}
else
- return BAD_FUNC_ARG;
-}
-
-#ifndef NO_FILESYSTEM
-int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor)
-{
- WOLFSSL_ENTER("wolfSSL_LoadCRL");
- if (ssl) {
- SSL_CM_WARNING(ssl);
- return wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor);
+#endif /* HAVE_ECC && OPENSSL_EXTRA */
+#if !defined(NO_DSA)
+ if (d2iTryDsaKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
}
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);
+#endif /* NO_DSA */
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
+ (HAVE_FIPS_VERSION > 2))
+ if (d2iTryDhKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
}
else
- return BAD_FUNC_ARG;
-}
-#endif
-
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
-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);
+#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 */
-#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);
+#ifdef HAVE_FALCON
+ if (d2iTryFalconKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
}
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);
+#endif /* HAVE_FALCON */
+#ifdef HAVE_DILITHIUM
+ if (d2iTryDilithiumKey(&pkey, *in, inSz, priv) >= 0) {
+ ;
+ }
else
- return BAD_FUNC_ARG;
-}
-
+#endif /* HAVE_DILITHIUM */
+ {
+ WOLFSSL_MSG("wolfSSL_d2i_PUBKEY couldn't determine key type");
+ }
-int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL");
- if (ctx)
- return wolfSSL_CertManagerDisableCRL(ctx->cm);
- else
- return BAD_FUNC_ARG;
+ if ((pkey != NULL) && (out != NULL)) {
+ *out = pkey;
+ }
+ return pkey;
}
+#endif /* OPENSSL_EXTRA || WPA_SMALL */
+#ifdef OPENSSL_EXTRA
-#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;
-}
-
-int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* file,
- int type)
+WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY(
+ WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf,
+ long keyLen)
{
- WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL");
- if (ctx)
- return wolfSSL_CertManagerLoadCRLFile(ctx->cm, file, type);
- else
- return BAD_FUNC_ARG;
-}
-#endif
-
+ WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
+#ifdef WOLFSSL_PEM_TO_DER
+ int ret;
+ DerBuffer* pkcs8Der = NULL;
+ DerBuffer rawDer;
+ EncryptedInfo info;
+ int advanceLen = 0;
-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;
-}
+ XMEMSET(&info, 0, sizeof(info));
+ XMEMSET(&rawDer, 0, sizeof(rawDer));
-#ifdef HAVE_CRL_IO
-int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb");
- if (ctx)
- return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb);
- else
- return BAD_FUNC_ARG;
-}
-#endif
+ if (keyBuf == NULL || *keyBuf == NULL || keyLen <= 0) {
+ WOLFSSL_MSG("Bad key PEM/DER args");
+ return NULL;
+ }
+ ret = PemToDer(*keyBuf, keyLen, PRIVATEKEY_TYPE, &pkcs8Der, NULL, &info,
+ NULL);
+ if (ret < 0) {
+ WOLFSSL_MSG("Not PEM format");
+ ret = AllocDer(&pkcs8Der, (word32)keyLen, PRIVATEKEY_TYPE, NULL);
+ if (ret == 0) {
+ XMEMCPY(pkcs8Der->buffer, *keyBuf, keyLen);
+ }
+ }
+ else {
+ advanceLen = (int)info.consumed;
+ }
-#endif /* HAVE_CRL */
+ if (ret == 0) {
+ /* Verify this is PKCS8 Key */
+ word32 inOutIdx = 0;
+ word32 algId;
+ ret = ToTraditionalInline_ex(pkcs8Der->buffer, &inOutIdx,
+ pkcs8Der->length, &algId);
+ if (ret >= 0) {
+ if (advanceLen == 0) /* Set only if not PEM */
+ advanceLen = (int)inOutIdx + ret;
+ if (algId == DHk) {
+ /* Special case for DH as we expect the DER buffer to be always
+ * be in PKCS8 format */
+ rawDer.buffer = pkcs8Der->buffer;
+ rawDer.length = inOutIdx + (word32)ret;
+ }
+ else {
+ rawDer.buffer = pkcs8Der->buffer + inOutIdx;
+ rawDer.length = (word32)ret;
+ }
+ ret = 0; /* good DER */
+ }
+ }
+ if (ret == 0) {
+ pkcs8 = wolfSSL_EVP_PKEY_new();
+ if (pkcs8 == NULL)
+ ret = MEMORY_E;
+ }
+ if (ret == 0) {
+ pkcs8->pkey.ptr = (char*)XMALLOC(rawDer.length, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pkcs8->pkey.ptr == NULL)
+ ret = MEMORY_E;
+ }
+ if (ret == 0) {
+ XMEMCPY(pkcs8->pkey.ptr, rawDer.buffer, rawDer.length);
+ pkcs8->pkey_sz = (int)rawDer.length;
+ }
-#ifndef NO_FILESYSTEM
+ FreeDer(&pkcs8Der);
+ if (ret != 0) {
+ wolfSSL_EVP_PKEY_free(pkcs8);
+ pkcs8 = NULL;
+ }
+ else {
+ *keyBuf += advanceLen;
+ }
+ if (pkey != NULL) {
+ *pkey = pkcs8;
+ }
+#else
+ (void)bio;
+ (void)pkey;
+#endif /* WOLFSSL_PEM_TO_DER */
-#ifdef WOLFSSL_DER_LOAD
+ return pkcs8;
+}
-/* 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)
+#ifdef OPENSSL_ALL
+int wolfSSL_i2d_PKCS8_PKEY(WOLFSSL_PKCS8_PRIV_KEY_INFO* key, unsigned char** pp)
{
- 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) {
- return WOLFSSL_SUCCESS;
- }
+ word32 keySz = 0;
+ unsigned char* out;
+ int len;
- return WOLFSSL_FAILURE;
-}
+ WOLFSSL_ENTER("wolfSSL_i2d_PKCS8_PKEY");
-#endif /* WOLFSSL_DER_LOAD */
+ if (key == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ if (pkcs8_encode(key, NULL, &keySz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E))
+ return WOLFSSL_FATAL_ERROR;
+ len = (int)keySz;
+ if ((pp == NULL) || (len == 0))
+ return len;
-WOLFSSL_ABI
-int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
- int format)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
+ if (*pp == NULL) {
+ out = (unsigned char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1);
+ if (out == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ }
+ else {
+ out = *pp;
+ }
- if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
+ if (pkcs8_encode(key, out, &keySz) != len) {
+ if (*pp == NULL)
+ XFREE(out, NULL, DYNAMIC_TYPE_ASN1);
+ return WOLFSSL_FATAL_ERROR;
}
- return WOLFSSL_FAILURE;
+ if (*pp == NULL)
+ *pp = out;
+ else
+ *pp += len;
+
+ return len;
}
+#endif
+#ifndef NO_BIO
+/* put SSL type in extra for now, not very common */
-WOLFSSL_ABI
-int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
- int format)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
-
- if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
- }
+/* 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;
- return WOLFSSL_FAILURE;
-}
+ WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio");
-#ifdef WOLFSSL_DUAL_ALG_CERTS
-int wolfSSL_CTX_use_AltPrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
- int format)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_file");
+ if (bio == NULL) {
+ return NULL;
+ }
- if (ProcessFile(ctx, file, format, ALT_PRIVATEKEY_TYPE, NULL, 0, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
+ if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) {
+ return NULL;
}
- return WOLFSSL_FAILURE;
+ pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz);
+#else
+ (void)bio;
+ (void)pkey;
+#endif /* WOLFSSL_PEM_TO_DER */
+
+ return pkcs8;
}
-#endif /* WOLFSSL_DUAL_ALG_CERTS */
-#endif /* NO_FILESYSTEM */
-/* Sets the max chain depth when verifying a certificate chain. Default depth
- * is set to MAX_CHAIN_DEPTH.
+/* expecting DER format public key
*
- * ctx WOLFSSL_CTX structure to set depth in
- * depth max depth
+ * 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.
*/
-void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) {
- WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
-
- if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) {
- WOLFSSL_MSG("Bad depth argument, too large or less than 0");
- return;
- }
-
- ctx->verifyDepth = (byte)depth;
-}
-
-
-/* get cert chaining depth using ssl struct */
-long wolfSSL_get_verify_depth(WOLFSSL* ssl)
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
+ WOLFSSL_EVP_PKEY** out)
{
- if(ssl == NULL) {
- return BAD_FUNC_ARG;
- }
-#ifndef OPENSSL_EXTRA
- return MAX_CHAIN_DEPTH;
-#else
- return ssl->options.verifyDepth;
-#endif
-}
+ unsigned char* mem;
+ long memSz;
+ WOLFSSL_EVP_PKEY* pkey = NULL;
+ WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio");
-/* get cert chaining depth using ctx struct */
-long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
-{
- if (ctx == NULL) {
- return BAD_FUNC_ARG;
+ if (bio == NULL) {
+ return NULL;
}
-#ifndef OPENSSL_EXTRA
- return MAX_CHAIN_DEPTH;
-#else
- return ctx->verifyDepth;
-#endif
-}
-
-
-#ifndef NO_FILESYSTEM
-
-
-WOLFSSL_ABI
-int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
-{
- /* process up to MAX_CHAIN_DEPTH plus subject cert */
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
+ (void)out;
- if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
+ memSz = wolfSSL_BIO_get_len(bio);
+ if (memSz <= 0) {
+ return NULL;
}
- return WOLFSSL_FAILURE;
-}
-
-
-int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx,
- const char* file, int format)
-{
- /* process up to MAX_CHAIN_DEPTH plus subject cert */
- WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format");
+ mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (mem == NULL) {
+ return NULL;
+ }
- if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL,
- GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
+ 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 WOLFSSL_FAILURE;
+ XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return pkey;
}
+#endif /* !NO_BIO */
-#ifndef NO_DH
-/* server Diffie-Hellman parameters */
-static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
- const char* fname, int format)
+/* 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)
{
-#ifdef WOLFSSL_SMALL_STACK
- byte staticBuffer[1]; /* force heap usage */
-#else
- byte staticBuffer[FILE_BUFFER_SIZE];
-#endif
- byte* myBuffer = staticBuffer;
- int dynamic = 0;
- int ret;
- long sz = 0;
- XFILE file;
+ WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY");
+ return d2iGenericKey(out, in, inSz, 0);
+}
- if (ctx == NULL || fname == NULL)
- return BAD_FUNC_ARG;
+#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN) && \
+ !defined(NO_PWDBASED)
- 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;
- }
+/* 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 (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
- WOLFSSL_MSG("SetTmpDH file size error");
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
+ if (!key || !key->pkey_sz)
+ return WOLFSSL_FATAL_ERROR;
- 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;
+ /* 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, (size_t)sz);
+ *der += sz;
+ }
+ else {
+ *der = (unsigned char*)XMALLOC((size_t)sz, NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (*der == NULL) {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ XMEMCPY(*der, pt + pkcs8HeaderSz, (size_t)sz);
}
- 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);
}
-
- XFCLOSE(file);
- if (dynamic)
- XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
-
- return ret;
+ return sz;
}
-/* server Diffie-Hellman parameters */
-int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format)
+int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der)
{
- if (ssl == NULL)
- return BAD_FUNC_ARG;
-
- return wolfSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format);
+ return wolfSSL_i2d_PublicKey(key, der);
}
+#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_ASN && !NO_PWDBASED */
-/* server Diffie-Hellman parameters */
-int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format)
+static WOLFSSL_EVP_PKEY* _d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out,
+ const unsigned char **in, long inSz, int priv)
{
- return wolfSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format);
-}
+ int ret = 0;
+ word32 idx = 0, algId;
+ word16 pkcs8HeaderSz = 0;
+ WOLFSSL_EVP_PKEY* local;
+ int opt = 0;
-#endif /* NO_DH */
+ (void)opt;
-#endif /* NO_FILESYSTEM */
+ if (in == NULL || inSz < 0) {
+ WOLFSSL_MSG("Bad argument");
+ return NULL;
+ }
-#ifndef NO_CHECK_PRIVATE_KEY
-/* Check private against public in certificate for match
- *
- * Returns WOLFSSL_SUCCESS on good private key
- * WOLFSSL_FAILURE if mismatched */
-static int check_cert_key(DerBuffer* cert, DerBuffer* key, void* heap,
- int devId, int isKeyLabel, int isKeyId)
-{
-#ifdef WOLFSSL_SMALL_STACK
- DecodedCert* der = NULL;
-#else
- DecodedCert der[1];
-#endif
- word32 size;
- byte* buff;
- int ret = WOLFSSL_FAILURE;
+ 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;
- WOLFSSL_ENTER("check_cert_key");
+ if ((type == WC_EVP_PKEY_RSA && algId != RSAk
+ #ifdef WC_RSA_PSS
+ && algId != RSAPSSk
+ #endif
+ ) ||
+ (type == WC_EVP_PKEY_EC && algId != ECDSAk) ||
+ (type == WC_EVP_PKEY_DSA && algId != DSAk) ||
+ (type == WC_EVP_PKEY_DH && algId != DHk)) {
+ WOLFSSL_MSG("PKCS8 does not match EVP key type");
+ return NULL;
+ }
- if (cert == NULL || key == NULL) {
- return WOLFSSL_FAILURE;
+ (void)idx; /* not used */
+ }
+ else {
+ if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) {
+ WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 "
+ "header");
+ return NULL;
+ }
+ }
}
-#ifdef WOLFSSL_SMALL_STACK
- der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
- if (der == NULL)
- return MEMORY_E;
-#endif
+ if (out != NULL && *out != NULL) {
+ wolfSSL_EVP_PKEY_free(*out);
+ *out = NULL;
+ }
+ local = wolfSSL_EVP_PKEY_new();
+ if (local == NULL) {
+ return NULL;
+ }
- 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;
+ local->type = type;
+ local->pkey_sz = (int)inSz;
+ local->pkcs8HeaderSz = pkcs8HeaderSz;
+ local->pkey.ptr = (char*)XMALLOC((size_t)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, (size_t)inSz);
}
- size = key->length;
- buff = key->buffer;
-#ifdef WOLF_PRIVATE_KEY_ID
- if (devId != INVALID_DEVID) {
- int type = 0;
- void *pkey = NULL;
-
- #ifndef NO_RSA
- if (der->keyOID == RSAk) {
- type = DYNAMIC_TYPE_RSA;
- }
- #ifdef WC_RSA_PSS
- if (der->keyOID == RSAPSSk) {
- type = DYNAMIC_TYPE_RSA;
- }
- #endif
- #endif
- #ifdef HAVE_ECC
- if (der->keyOID == ECDSAk) {
- type = DYNAMIC_TYPE_ECC;
- }
- #endif
- #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
- if ((der->keyOID == DILITHIUM_LEVEL2k) ||
- (der->keyOID == DILITHIUM_LEVEL3k) ||
- (der->keyOID == DILITHIUM_LEVEL5k)) {
- type = DYNAMIC_TYPE_DILITHIUM;
- }
- #endif
- #if defined(HAVE_PQC) && defined(HAVE_FALCON)
- if ((der->keyOID == FALCON_LEVEL1k) ||
- (der->keyOID == FALCON_LEVEL5k)) {
- type = DYNAMIC_TYPE_FALCON;
- }
- #endif
-
- ret = CreateDevPrivateKey(&pkey, buff, size, type,
- isKeyLabel, isKeyId, heap, devId);
- #ifdef WOLF_CRYPTO_CB
- if (ret == 0) {
- #ifndef NO_RSA
- if (der->keyOID == RSAk
- #ifdef WC_RSA_PSS
- || der->keyOID == RSAPSSk
- #endif
- ) {
- ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey,
- der->publicKey, der->pubKeySize);
- }
- #endif
- #ifdef HAVE_ECC
- if (der->keyOID == ECDSAk) {
- ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey,
- der->publicKey, der->pubKeySize);
+ switch (type) {
+#ifndef NO_RSA
+ case WC_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;
}
- #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);
+ break;
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+ case WC_EVP_PKEY_EC:
+ local->ownEcc = 1;
+ local->ecc = wolfSSL_EC_KEY_new();
+ if (local->ecc == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
}
- #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);
+ 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;
}
- #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);
+ break;
+#endif /* HAVE_ECC */
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)
+#ifndef NO_DSA
+ case WC_EVP_PKEY_DSA:
+ local->ownDsa = 1;
+ local->dsa = wolfSSL_DSA_new();
+ if (local->dsa == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
}
- #endif
- #ifdef HAVE_ECC
- if (der->keyOID == ECDSAk) {
- wc_ecc_free((ecc_key*)pkey);
+ 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;
}
- #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);
+ break;
+#endif /* NO_DSA */
+#ifndef NO_DH
+#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))
+ case WC_EVP_PKEY_DH:
+ local->ownDh = 1;
+ local->dh = wolfSSL_DH_new();
+ if (local->dh == NULL) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
}
- #endif
- #if defined(HAVE_PQC) && defined(HAVE_FALCON)
- if ((der->keyOID == FALCON_LEVEL1k) ||
- (der->keyOID == FALCON_LEVEL5k)) {
- wc_falcon_free((falcon_key*)pkey);
+ if (wolfSSL_DH_LoadDer(local->dh,
+ (const unsigned char*)local->pkey.ptr, local->pkey_sz)
+ != WOLFSSL_SUCCESS) {
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
}
- #endif
- XFREE(pkey, heap, type);
+ break;
+#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* HAVE_DH */
+#endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */
+ default:
+ WOLFSSL_MSG("Unsupported key type");
+ wolfSSL_EVP_PKEY_free(local);
+ return NULL;
+ }
+
+ /* advance pointer with success */
+ if (local != NULL) {
+ if (local->pkey_sz <= (int)inSz) {
+ *in += local->pkey_sz;
}
- if (ret != CRYPTOCB_UNAVAILABLE) {
- ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE;
+
+ if (out != NULL) {
+ *out = local;
}
}
- 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
+ return local;
+}
- (void)devId;
- (void)isKeyLabel;
- (void)isKeyId;
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out,
+ const unsigned char **in, long inSz)
+{
+ WOLFSSL_ENTER("wolfSSL_d2i_PublicKey");
- return ret;
+ return _d2i_PublicKey(type, out, in, inSz, 0);
}
-
-/* Check private against public in certificate for match
+/* Reads in a DER format key. If PKCS8 headers are found they are stripped off.
*
- * ctx WOLFSSL_CTX structure to check private key in
+ * type type of key
+ * out newly created WOLFSSL_EVP_PKEY structure
+ * in pointer to input key DER
+ * inSz size of in buffer
*
- * Returns WOLFSSL_SUCCESS on good private key
- * WOLFSSL_FAILURE if mismatched. */
-int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx)
+ * 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)
{
- 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_d2i_PrivateKey");
+
+ return _d2i_PublicKey(type, out, in, inSz, 1);
}
-#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)
+#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)
{
- const unsigned char *key;
- int type;
+ WOLFSSL_EVP_PKEY* local;
- WOLFSSL_ENTER("wolfSSL_CTX_get0_privatekey");
+ if (out != NULL && *out != NULL) {
+ wolfSSL_EVP_PKEY_free(*out);
+ *out = NULL;
+ }
- if (ctx == NULL || ctx->privateKey == NULL ||
- ctx->privateKey->buffer == NULL) {
- WOLFSSL_MSG("Bad parameter or key not set");
+ local = wolfSSL_EVP_PKEY_new_ex(heap);
+ if (local == NULL) {
return NULL;
}
- switch (ctx->privateKeyType) {
+ local->type = type;
+ local->pkey_sz = 0;
+ local->pkcs8HeaderSz = 0;
+
+ switch (type) {
#ifndef NO_RSA
- case rsa_sa_algo:
- type = EVP_PKEY_RSA;
+ case WC_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
+ }
+#endif /* !NO_RSA */
#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;
+ case WC_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
+ }
+#endif /* HAVE_ECC */
default:
- /* Other key types not supported either as ssl private keys
- * or in the EVP layer */
- WOLFSSL_MSG("Unsupported key type");
+ WOLFSSL_MSG("Unsupported private key id type");
+ wolfSSL_EVP_PKEY_free(local);
return NULL;
}
- key = ctx->privateKey->buffer;
+ if (local != NULL && out != NULL) {
+ *out = local;
+ }
- if (ctx->privateKeyPKey != NULL)
- return ctx->privateKeyPKey;
- else
- return wolfSSL_d2i_PrivateKey(type,
- (WOLFSSL_EVP_PKEY**)&ctx->privateKeyPKey, &key,
- (long)ctx->privateKey->length);
+ return local;
}
-#endif
+#endif /* WOLF_PRIVATE_KEY_ID */
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+#ifndef NO_CERTS /* // NOLINT(readability-redundant-preprocessor) */
-static WOLFSSL_EVP_PKEY* d2iGenericKey(WOLFSSL_EVP_PKEY** out,
- const unsigned char** in, long inSz, int priv)
+#ifndef NO_CHECK_PRIVATE_KEY
+/* Check private against public in certificate for match
+ *
+ * ssl WOLFSSL structure to check private key in
+ *
+ * Returns WOLFSSL_SUCCESS on good private key
+ * WOLFSSL_FAILURE if mismatched. */
+int wolfSSL_check_private_key(const WOLFSSL* ssl)
{
+ int res = WOLFSSL_SUCCESS;
- 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;
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
}
- mem = *in;
-
- #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));
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask);
+ wolfssl_priv_der_unblind(ssl->buffers.altKey, ssl->buffers.altKeyMask);
+#endif
+ res = check_cert_key(ssl->buffers.certificate, ssl->buffers.key,
+ ssl->buffers.altKey, ssl->heap, ssl->buffers.keyDevId,
+ ssl->buffers.keyLabel, ssl->buffers.keyId, ssl->buffers.altKeyDevId,
+ ssl->buffers.altKeyLabel, ssl->buffers.altKeyId);
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ if (res == WOLFSSL_SUCCESS) {
+ int ret;
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key,
+ (DerBuffer**)&ssl->buffers.keyMask);
+ if (ret == 0) {
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey,
+ (DerBuffer**)&ssl->buffers.altKeyMask);
+ }
+ if (ret != 0) {
+ res = WOLFSSL_FAILURE;
+ }
+ }
+#endif
+#else
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key, ssl->buffers.keyMask);
+#endif
+ res = check_cert_key(ssl->buffers.certificate, ssl->buffers.key, NULL,
+ ssl->heap, ssl->buffers.keyDevId, ssl->buffers.keyLabel,
+ ssl->buffers.keyId, INVALID_DEVID, 0, 0);
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ if (res == WOLFSSL_SUCCESS) {
+ int ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key,
+ (DerBuffer**)&ssl->buffers.keyMask);
+ if (ret != 0) {
+ res = WOLFSSL_FAILURE;
+ }
+ }
+#endif
+#endif
- /* 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
+ return res;
+}
+#endif /* !NO_CHECK_PRIVATE_KEY */
- 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;
- }
+#endif /* !NO_CERTS */
- 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;
- }
+#endif /* OPENSSL_EXTRA */
- return pkey;
- }
- else {
- WOLFSSL_MSG("RSA wolfSSL_EVP_PKEY_new error");
+#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)
+{
+ 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;
}
}
}
- #endif /* NO_RSA */
-
- #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
- {
- word32 keyIdx = 0;
- int isEccKey;
- #ifdef WOLFSSL_SMALL_STACK
- ecc_key *ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC);
- if (ecc == NULL)
- return NULL;
- #else
- ecc_key ecc[1];
- #endif
- XMEMSET(ecc, 0, sizeof(ecc_key));
+ return 1;
+}
- 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
+/* Set user preference for the {client,server}_cert_type extension.
+ * Takes byte array containing cert types the caller can provide to its peer.
+ * Cert types are in preferred order in the array.
+ */
+static int set_cert_type(RpkConfig* cfg,
+ int client, const char* buf, int bufLen)
+{
+ int i;
+ byte* certTypeCnt;
+ byte* certTypes;
- 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;
- }
+ if (cfg == NULL || bufLen > (client ? MAX_CLIENT_CERT_TYPE_CNT :
+ MAX_SERVER_CERT_TYPE_CNT)) {
+ return BAD_FUNC_ARG;
+ }
- pkey->ownEcc = 1;
- pkey->ecc = wolfSSL_EC_KEY_new();
- if (pkey->ecc == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
+ if (client) {
+ certTypeCnt = &cfg->preferred_ClientCertTypeCnt;
+ certTypes = cfg->preferred_ClientCertTypes;
+ }
+ else {
+ certTypeCnt = &cfg->preferred_ServerCertTypeCnt;
+ certTypes = cfg->preferred_ServerCertTypes;
+ }
+ /* if buf is set to NULL or bufLen is zero, it defaults the setting*/
+ if (buf == NULL || bufLen == 0) {
+ *certTypeCnt = 1;
+ for (i = 0; i < 2; i++)
+ certTypes[i] = WOLFSSL_CERT_TYPE_X509;
+ return WOLFSSL_SUCCESS;
+ }
- 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;
- }
+ if (!isArrayUnique(buf, (size_t)bufLen))
+ return BAD_FUNC_ARG;
- return pkey;
- }
- else {
- WOLFSSL_MSG("ECC wolfSSL_EVP_PKEY_new error");
- }
- }
+ for (i = 0; i < bufLen; i++) {
+ if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509)
+ return BAD_FUNC_ARG;
+ certTypes[i] = (byte)buf[i];
}
- #endif /* HAVE_ECC && OPENSSL_EXTRA */
+ *certTypeCnt = bufLen;
- #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));
+ return WOLFSSL_SUCCESS;
+}
+int wolfSSL_set_client_cert_type(WOLFSSL* ssl, const char* buf, int buflen)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+ return set_cert_type(&ssl->options.rpkConfig, 1, buf, buflen);
+}
+int wolfSSL_set_server_cert_type(WOLFSSL* ssl, const char* buf, int buflen)
+{
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
+ return set_cert_type(&ssl->options.rpkConfig, 0, buf, buflen);
+}
+int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx,
+ const char* buf, int buflen)
+{
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+ return set_cert_type(&ctx->rpkConfig, 1, buf, buflen);
+}
+int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx,
+ const char* buf, int buflen)
+{
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+ return set_cert_type(&ctx->rpkConfig, 0, buf, buflen);
+}
- 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
+/* 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.
+ */
+int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp)
+{
+ int ret = WOLFSSL_SUCCESS;
- /* 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;
- }
+ if (ssl == NULL || tp == NULL)
+ return BAD_FUNC_ARG;
- pkey->ownDsa = 1;
- pkey->dsa = wolfSSL_DSA_new();
- if (pkey->dsa == NULL) {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
+ 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;
+}
- 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;
- }
+/* 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.
+ */
+int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp)
+{
+ int ret = WOLFSSL_SUCCESS;
- return pkey;
- }
- else {
- WOLFSSL_MSG("DSA wolfSSL_EVP_PKEY_new error");
- }
- }
+ if (ssl == NULL || tp == NULL)
+ return BAD_FUNC_ARG;
+
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ if (ssl->options.rpkState.received_ServerCertTypeCnt == 1)
+ *tp = ssl->options.rpkState.received_ServerCertTypes[0];
+ else
+ *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
}
- #endif /* NO_DSA */
+ else {
+ if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1)
+ *tp = ssl->options.rpkState.sending_ServerCertTypes[0];
+ else
+ *tp = WOLFSSL_CERT_TYPE_UNKNOWN;
+ }
+ return ret;
+}
- #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));
+#endif /* HAVE_RPK */
- 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
+#ifdef HAVE_ECC
- /* 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;
- }
+/* 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)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_SetTmpEC_DHE_Sz");
- 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;
- }
+ /* 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;
- return pkey;
- }
- else {
- WOLFSSL_MSG("DH wolfSSL_EVP_PKEY_new error");
- }
+ if (ctx->privateKeySz == 0) {
+ WOLFSSL_MSG("Must set private key/cert first");
+ return BAD_FUNC_ARG;
}
+
+ sz = (word16)ctx->privateKeySz;
}
- #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
- #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
- #if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA)
- #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
- (HAVE_FIPS_VERSION > 2))
- {
- 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));
+ /* 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;
- /* test if DH-public key */
- if (wc_InitDhKey(dh) != 0)
- return NULL;
+ ctx->eccTempKeySz = sz;
- ret = wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz);
- wc_FreeDhKey(dh);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dh, NULL, DYNAMIC_TYPE_DH);
- #endif
+ return WOLFSSL_SUCCESS;
+}
- 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;
- }
- key = (DhKey*)pkey->dh->internal;
-
- keyIdx = 0;
- if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) == 0)
- {
- int elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q |
- ELEMENT_PUB;
- if (priv)
- elements |= ELEMENT_PRV;
- if(SetDhExternal_ex(pkey->dh, elements)
- == WOLFSSL_SUCCESS ) {
- return pkey;
- }
- }
- else {
- wolfSSL_EVP_PKEY_free(pkey);
- return NULL;
- }
- }
- }
- }
- #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
- #endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */
+/* Set Temp SSL EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */
+int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz)
+{
+ WOLFSSL_ENTER("wolfSSL_SetTmpEC_DHE_Sz");
- #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
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
- 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);
- }
+ /* 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;
- #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->eccTempKeySz = sz;
- }
- #endif /* HAVE_FALCON */
- #ifdef HAVE_DILITHIUM
- {
- int isDilithium = 0;
- #ifdef WOLFSSL_SMALL_STACK
- dilithium_key *dilithium = (dilithium_key *)
- XMALLOC(sizeof(dilithium_key), NULL, DYNAMIC_TYPE_DILITHIUM);
- if (dilithium == NULL) {
- return NULL;
- }
- #else
- dilithium_key dilithium[1];
- #endif
+ 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);
- }
+#endif /* HAVE_ECC */
- #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;
- }
- }
- #endif /* HAVE_DILITHIUM */
- #endif /* HAVE_PQC */
+typedef struct {
+ byte verifyPeer:1;
+ byte verifyNone:1;
+ byte failNoCert:1;
+ byte failNoCertxPSK:1;
+ byte verifyPostHandshake:1;
+} SetVerifyOptions;
- if (pkey == NULL) {
- WOLFSSL_MSG("wolfSSL_d2i_PUBKEY couldn't determine key type");
- }
+static SetVerifyOptions ModeToVerifyOptions(int mode)
+{
+ SetVerifyOptions opts;
+ XMEMSET(&opts, 0, sizeof(SetVerifyOptions));
- return pkey;
+ 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
+ }
+ }
+ return opts;
}
-#endif /* OPENSSL_EXTRA || WPA_SMALL */
-#ifdef OPENSSL_EXTRA
-
-WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY(
- WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf, long keyLen)
+WOLFSSL_ABI
+void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback verify_callback)
{
- WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
-#ifdef WOLFSSL_PEM_TO_DER
- int ret;
- DerBuffer* der = NULL;
-
- if (keyBuf == NULL || *keyBuf == NULL || keyLen <= 0) {
- WOLFSSL_MSG("Bad key PEM/DER args");
- return NULL;
- }
+ SetVerifyOptions opts;
- 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);
- }
- }
+ WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
+ if (ctx == NULL)
+ return;
- 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 */
- }
- }
+ opts = ModeToVerifyOptions(mode);
- 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;
- }
+ 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
- FreeDer(&der);
- if (ret != 0) {
- wolfSSL_EVP_PKEY_free(pkcs8);
- pkcs8 = NULL;
- }
- if (pkey != NULL) {
- *pkey = pkcs8;
- }
+ ctx->verifyCallback = verify_callback;
+}
-#else
- (void)bio;
- (void)pkey;
-#endif /* WOLFSSL_PEM_TO_DER */
+#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;
- return pkcs8;
+ ctx->verifyCertCb = cb;
+ ctx->verifyCertCbArg = arg;
}
+#endif
-#ifndef NO_BIO
-/* put SSL type in extra for now, not very common */
-
-/* Converts a DER format key read from "bio" to a PKCS8 structure.
- *
- * bio input bio to read DER from
- * pkey If not NULL then this pointer will be overwritten with a new PKCS8
- * structure.
- *
- * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail
- * case.
- */
-WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio,
- WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey)
+void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback verify_callback)
{
- WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL;
-#ifdef WOLFSSL_PEM_TO_DER
- unsigned char* mem = NULL;
- int memSz;
-
- WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio");
+ SetVerifyOptions opts;
- if (bio == NULL) {
- return NULL;
- }
+ WOLFSSL_ENTER("wolfSSL_set_verify");
+ if (ssl == NULL)
+ return;
- if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) {
- return NULL;
- }
+ opts = ModeToVerifyOptions(mode);
- pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz);
-#else
- (void)bio;
- (void)pkey;
-#endif /* WOLFSSL_PEM_TO_DER */
+ 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
- return pkcs8;
+ ssl->verifyCallback = verify_callback;
}
-
-/* expecting DER format public key
- *
- * bio input bio to read DER from
- * out If not NULL then this pointer will be overwritten with a new
- * WOLFSSL_EVP_PKEY pointer
- *
- * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case.
- */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio,
- WOLFSSL_EVP_PKEY** out)
+void wolfSSL_set_verify_result(WOLFSSL *ssl, long v)
{
- unsigned char* mem;
- long memSz;
- WOLFSSL_EVP_PKEY* pkey = NULL;
-
- WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio");
+ WOLFSSL_ENTER("wolfSSL_set_verify_result");
- if (bio == NULL) {
- return NULL;
- }
- (void)out;
+ if (ssl == NULL)
+ return;
- memSz = wolfSSL_BIO_get_len(bio);
- if (memSz <= 0) {
- return NULL;
- }
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+ defined(OPENSSL_ALL)
+ ssl->peerVerifyRet = (unsigned long)v;
+#else
+ (void)v;
+ WOLFSSL_STUB("wolfSSL_set_verify_result");
+#endif
+}
- mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (mem == NULL) {
- return NULL;
- }
+#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);
- 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 {
+ WOLFSSL_ERROR(ret); /* log the error in the error queue */
}
}
+ return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
- XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER);
- return pkey;
+int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX* ctx, int val)
+{
+ int ret = wolfSSL_CTX_allow_post_handshake_auth(ctx);
+ if (ret == 0) {
+ ctx->postHandshakeAuth = (val != 0);
+ }
+ return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+}
+int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val)
+{
+ int ret = wolfSSL_allow_post_handshake_auth(ssl);
+ if (ret == 0) {
+ ssl->options.postHandshakeAuth = (val != 0);
+ }
+ return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
}
+#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_TLS13 &&
+ * WOLFSSL_POST_HANDSHAKE_AUTH */
-#endif /* !NO_BIO */
+/* store user ctx for verify callback */
+void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_SetCertCbCtx");
+ if (ssl)
+ ssl->verifyCbCtx = ctx;
+}
-/* 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)
+/* store user ctx for verify callback */
+void wolfSSL_CTX_SetCertCbCtx(WOLFSSL_CTX* ctx, void* userCtx)
{
- WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY");
- return d2iGenericKey(out, in, inSz, 0);
+ WOLFSSL_ENTER("wolfSSL_CTX_SetCertCbCtx");
+ if (ctx)
+ ctx->verifyCbCtx = userCtx;
}
-#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN) && \
- !defined(NO_PWDBASED)
-/* 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)
+/* store context CA Cache addition callback */
+void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb)
{
- int sz;
- word16 pkcs8HeaderSz;
+ if (ctx && ctx->cm)
+ ctx->cm->caCacheCallback = cb;
+}
- 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 {
- *der = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL);
- if (*der == NULL) {
- return WOLFSSL_FATAL_ERROR;
- }
- XMEMCPY(*der, pt + pkcs8HeaderSz, sz);
- }
- }
- return sz;
+#if defined(PERSIST_CERT_CACHE)
+
+#if !defined(NO_FILESYSTEM)
+
+/* Persist cert cache to file */
+int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache");
+
+ if (ctx == NULL || fname == NULL)
+ return BAD_FUNC_ARG;
+
+ return CM_SaveCertCache(ctx->cm, fname);
}
-int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der)
+
+/* Persist cert cache from file */
+int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
{
- return wolfSSL_i2d_PublicKey(key, der);
+ WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache");
+
+ if (ctx == NULL || fname == NULL)
+ return BAD_FUNC_ARG;
+
+ return CM_RestoreCertCache(ctx->cm, fname);
}
-#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_ASN && !NO_PWDBASED */
+#endif /* NO_FILESYSTEM */
-static WOLFSSL_EVP_PKEY* _d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out,
- const unsigned char **in, long inSz, int priv)
+/* Persist cert cache to memory */
+int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem,
+ int sz, int* used)
{
- int ret = 0;
- word32 idx = 0, algId;
- word16 pkcs8HeaderSz = 0;
- WOLFSSL_EVP_PKEY* local;
- int opt = 0;
+ WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache");
- (void)opt;
+ if (ctx == NULL || mem == NULL || used == NULL || sz <= 0)
+ return BAD_FUNC_ARG;
- if (in == NULL || inSz < 0) {
- WOLFSSL_MSG("Bad argument");
- return NULL;
+ return CM_MemSaveCertCache(ctx->cm, mem, sz, used);
+}
+
+
+/* Restore cert cache from memory */
+int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache");
+
+ if (ctx == NULL || mem == NULL || sz <= 0)
+ return BAD_FUNC_ARG;
+
+ return CM_MemRestoreCertCache(ctx->cm, mem, sz);
+}
+
+
+/* get how big the the cert cache save buffer needs to be */
+int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize");
+
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
+
+ return CM_GetCertCacheMemSize(ctx->cm);
+}
+
+#endif /* PERSIST_CERT_CACHE */
+#endif /* !NO_CERTS */
+
+
+void wolfSSL_load_error_strings(void)
+{
+ /* compatibility only */
+}
+
+
+int wolfSSL_library_init(void)
+{
+ WOLFSSL_ENTER("wolfSSL_library_init");
+ if (wolfSSL_Init() == WOLFSSL_SUCCESS)
+ return WOLFSSL_SUCCESS;
+ else
+ return WOLFSSL_FATAL_ERROR;
+}
+
+
+#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_FAILURE;
+
+ ssl->sessionSecretCb = cb;
+ ssl->sessionSecretCtx = ctx;
+ if (cb != NULL) {
+ /* If using a pre-set key, assume session resumption. */
+ ssl->session->sessionIDSz = 0;
+ ssl->options.resuming = 1;
}
- if (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;
+ return WOLFSSL_SUCCESS;
+}
- 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;
- }
+int wolfSSL_set_session_ticket_ext_cb(WOLFSSL* ssl, TicketParseCb cb,
+ void *ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_set_session_ticket_ext_cb");
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
- (void)idx; /* not used */
- }
- else {
- if (ret != ASN_PARSE_E) {
- WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 "
- "header");
- return NULL;
- }
- }
+ ssl->ticketParseCb = cb;
+ ssl->ticketParseCtx = ctx;
+
+ return WOLFSSL_SUCCESS;
+}
+
+int wolfSSL_set_secret_cb(WOLFSSL* ssl, TlsSecretCb cb, void* ctx)
+{
+ WOLFSSL_ENTER("wolfSSL_set_secret_cb");
+ if (ssl == NULL)
+ return WOLFSSL_FATAL_ERROR;
+
+ ssl->tlsSecretCb = cb;
+ ssl->tlsSecretCtx = ctx;
+
+ return WOLFSSL_SUCCESS;
+}
+
+#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;
+
+ (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;
}
- if (out != NULL && *out != NULL) {
- wolfSSL_EVP_PKEY_free(*out);
- *out = NULL;
+ XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%s ",
+ CLIENT_RANDOM_LABEL);
+ pmsPos += XSTRLEN(CLIENT_RANDOM_LABEL) + 1;
+ for (i = 0; i < clientRandomSz; i++) {
+ XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x",
+ clientRandom[i]);
+ pmsPos += 2;
}
- local = wolfSSL_EVP_PKEY_new();
- if (local == NULL) {
- return NULL;
+ 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;
- 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);
- }
-
- switch (type) {
-#ifndef NO_RSA
- case EVP_PKEY_RSA:
- opt = priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC;
- local->ownRsa = 1;
- local->rsa = wolfssl_rsa_d2i(NULL,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz, opt);
- if (local->rsa == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
-#endif /* NO_RSA */
-#ifdef HAVE_ECC
- case EVP_PKEY_EC:
- local->ownEcc = 1;
- local->ecc = wolfSSL_EC_KEY_new();
- if (local->ecc == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- opt = priv ? WOLFSSL_EC_KEY_LOAD_PRIVATE :
- WOLFSSL_EC_KEY_LOAD_PUBLIC;
- if (wolfSSL_EC_KEY_LoadDer_ex(local->ecc,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz,
- opt)
- != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
-#endif /* HAVE_ECC */
-#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)
-#ifndef NO_DSA
- case EVP_PKEY_DSA:
- local->ownDsa = 1;
- local->dsa = wolfSSL_DSA_new();
- if (local->dsa == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- opt = priv ? WOLFSSL_DSA_LOAD_PRIVATE : WOLFSSL_DSA_LOAD_PUBLIC;
- if (wolfSSL_DSA_LoadDer_ex(local->dsa,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz,
- opt)
- != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
-#endif /* NO_DSA */
-#ifndef NO_DH
-#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))
- case EVP_PKEY_DH:
- local->ownDh = 1;
- local->dh = wolfSSL_DH_new();
- if (local->dh == NULL) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- if (wolfSSL_DH_LoadDer(local->dh,
- (const unsigned char*)local->pkey.ptr, local->pkey_sz)
- != WOLFSSL_SUCCESS) {
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- break;
-#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
-#endif /* HAVE_DH */
-#endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */
- default:
- WOLFSSL_MSG("Unsupported key type");
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
-
- /* advance pointer with success */
- if (local != NULL) {
- if (local->pkey_sz <= (int)inSz) {
- *in += local->pkey_sz;
- }
+ /* print master secret */
+ puts(pmsBuf);
- if (out != NULL) {
- *out = local;
+ #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE)
+ {
+ FILE* f = XFOPEN(WOLFSSL_SSLKEYLOGFILE_OUTPUT, "a");
+ if (f != XBADFILE) {
+ XFWRITE(pmsBuf, 1, pmsPos, f);
+ XFCLOSE(f);
}
}
-
- return local;
+ #endif
+ return 0;
}
+#endif /* SHOW_SECRETS */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out,
- const unsigned char **in, long inSz)
-{
- WOLFSSL_ENTER("wolfSSL_d2i_PublicKey");
+#endif
- 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.
+
+#ifdef OPENSSL_EXTRA
+
+/*
+ * check if the list has TLS13 and pre-TLS13 suites
+ * @param list cipher suite list that user want to set
+ * (caller required to check for NULL)
+ * @return mixed: 0, only pre-TLS13: 1, only TLS13: 2
*/
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out,
- const unsigned char **in, long inSz)
+static int CheckcipherList(const char* list)
{
- WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey");
+ int ret;
+ int findTLSv13Suites = 0;
+ int findbeforeSuites = 0;
+ byte cipherSuite0;
+ byte cipherSuite1;
+ int flags;
+ char* next = (char*)list;
- return _d2i_PublicKey(type, out, in, inSz, 1);
-}
+ do {
+ char* current = next;
+ char name[MAX_SUITE_NAME + 1];
+ word32 length = MAX_SUITE_NAME;
+ word32 current_length;
+ byte major = INVALID_BYTE;
+ byte minor = INVALID_BYTE;
-#ifdef WOLF_PRIVATE_KEY_ID
-/* Create an EVP structure for use with crypto callbacks */
-WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_id(int type, WOLFSSL_EVP_PKEY** out,
- void* heap, int devId)
-{
- WOLFSSL_EVP_PKEY* local;
+ next = XSTRSTR(next, ":");
- if (out != NULL && *out != NULL) {
- wolfSSL_EVP_PKEY_free(*out);
- *out = NULL;
- }
+ if (next) {
+ current_length = (word32)(next - current);
+ ++next; /* increment to skip ':' */
+ }
+ else {
+ current_length = (word32)XSTRLEN(current);
+ }
- local = wolfSSL_EVP_PKEY_new_ex(heap);
- if (local == NULL) {
- return NULL;
- }
+ if (current_length == 0) {
+ break;
+ }
- local->type = type;
- local->pkey_sz = 0;
- local->pkcs8HeaderSz = 0;
+ if (current_length < length) {
+ length = current_length;
+ }
+ XMEMCPY(name, current, length);
+ name[length] = 0;
- switch (type) {
-#ifndef NO_RSA
- case EVP_PKEY_RSA:
+ if (XSTRCMP(name, "ALL") == 0 ||
+ XSTRCMP(name, "DEFAULT") == 0 ||
+ XSTRCMP(name, "HIGH") == 0)
{
- 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;
+ findTLSv13Suites = 1;
+ findbeforeSuites = 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;
+ ret = GetCipherSuiteFromName(name, &cipherSuite0,
+ &cipherSuite1, &major, &minor, &flags);
+ if (ret == 0) {
+ if (cipherSuite0 == TLS13_BYTE || minor == TLSv1_3_MINOR) {
+ /* TLSv13 suite */
+ findTLSv13Suites = 1;
+ }
+ else {
+ findbeforeSuites = 1;
+ }
}
-#endif /* HAVE_ECC */
- default:
- WOLFSSL_MSG("Unsupported private key id type");
- wolfSSL_EVP_PKEY_free(local);
- return NULL;
- }
- if (local != NULL && out != NULL) {
- *out = local;
- }
+ #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;
- return local;
-}
-#endif /* WOLF_PRIVATE_KEY_ID */
+ do {
+ subStrNext = XSTRSTR(subStr, "+");
-#ifndef NO_CERTS /* // NOLINT(readability-redundant-preprocessor) */
+ if ((XSTRCMP(subStr, "ECDHE") == 0) ||
+ (XSTRCMP(subStr, "RSA") == 0)) {
+ return 0;
+ }
-#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) {
- 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 */
+ if (subStrNext && (XSTRLEN(subStrNext) > 0)) {
+ subStr = subStrNext + 1; /* +1 to skip past '+' */
+ }
+ } while (subStrNext != NULL);
+ }
+ #endif
-#endif /* !NO_CERTS */
+ if (findTLSv13Suites == 1 && findbeforeSuites == 1) {
+ /* list has mixed suites */
+ return 0;
+ }
+ } while (next);
-int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey)
-{
- WOLFSSL_ENTER("wolfSSL_use_PrivateKey");
- if (ssl == NULL || pkey == NULL ) {
- return WOLFSSL_FAILURE;
+ if (findTLSv13Suites == 0 && findbeforeSuites == 1) {
+ ret = 1;/* only before TLSv13 suites */
}
-
- return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr,
- pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1);
+ else if (findTLSv13Suites == 1 && findbeforeSuites == 0) {
+ ret = 2;/* only TLSv13 suties */
+ }
+ else {
+ ret = 0;/* handle as mixed */
+ }
+ return ret;
}
-
-int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der,
- long derSz)
+/* 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)
{
- WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1");
- if (ssl == NULL || der == NULL ) {
+ int ret = 0;
+ int listattribute = 0;
+ int tls13Only = 0;
+ WC_DECLARE_VAR(suitesCpy, byte, WOLFSSL_MAX_SUITE_SZ, 0);
+ word16 suitesCpySz = 0;
+ word16 i = 0;
+ word16 j = 0;
+
+ if (suites == NULL || list == NULL) {
+ WOLFSSL_MSG("NULL argument");
return WOLFSSL_FAILURE;
}
- (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
-*/
+ listattribute = CheckcipherList(list);
-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 (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;
+ }
}
- (void)pri; /* type of private key */
- return wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1);
-}
-
+ /* list contains ciphers either only for TLS 1.3 or <= TLS 1.2 */
+#ifdef WOLFSSL_SMALL_STACK
+ if (suites->suiteSz > 0) {
+ suitesCpy = (byte*)XMALLOC(suites->suiteSz, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (suitesCpy == NULL) {
+ return WOLFSSL_FAILURE;
+ }
-#ifndef NO_RSA
-int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz)
-{
- WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1");
- if (ssl == NULL || der == NULL ) {
- return WOLFSSL_FAILURE;
+ XMEMSET(suitesCpy, 0, suites->suiteSz);
}
-
- return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1);
-}
+#else
+ XMEMSET(suitesCpy, 0, sizeof(suitesCpy));
#endif
-int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509)
-{
- long idx = 0;
+ if (suites->suiteSz > 0)
+ XMEMCPY(suitesCpy, suites->suites, suites->suiteSz);
+ suitesCpySz = suites->suiteSz;
- 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;
- }
+ ret = SetCipherList_ex(ctx, ssl, suites, list);
+ if (ret != 1) {
+ WC_FREE_VAR_EX(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
}
- (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.
- */
-static int isArrayUnique(const char* buf, size_t len)
-{
- 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;
+ /* The idea in this section is that OpenSSL has two API to set ciphersuites.
+ * - SSL_CTX_set_cipher_list for setting TLS <= 1.2 suites
+ * - SSL_CTX_set_ciphersuites for setting TLS 1.3 suites
+ * Since we direct both API here we attempt to provide API compatibility. If
+ * we only get suites from <= 1.2 or == 1.3 then we will only update those
+ * suites and keep the suites from the other group. */
+ 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;
+ }
}
}
}
- return 1;
-}
-/* Set user preference for the client_cert_type exetnsion.
- * Takes byte array containing cert types the caller can provide to its peer.
- * Cert types are in preferred order in the array.
- */
-WOLFSSL_API int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx,
- const char* buf, int bufLen)
-{
- int i;
+ WC_FREE_VAR_EX(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
- if (ctx == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) {
- return BAD_FUNC_ARG;
- }
+#endif
- /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/
- if (buf == NULL || bufLen == 0) {
- ctx->rpkConfig.preferred_ClientCertTypeCnt = 1;
- ctx->rpkConfig.preferred_ClientCertTypes[0]= WOLFSSL_CERT_TYPE_X509;
- ctx->rpkConfig.preferred_ClientCertTypes[1]= WOLFSSL_CERT_TYPE_X509;
- return WOLFSSL_SUCCESS;
- }
- if (!isArrayUnique(buf, bufLen))
- return BAD_FUNC_ARG;
+int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list");
- 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)
+ return WOLFSSL_FAILURE;
- ctx->rpkConfig.preferred_ClientCertTypes[i] = buf[i];
- }
- ctx->rpkConfig.preferred_ClientCertTypeCnt = bufLen;
+ if (AllocateCtxSuites(ctx) != 0)
+ return WOLFSSL_FAILURE;
- return WOLFSSL_SUCCESS;
+#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
}
-/* 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)
+#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)
{
- int i;
-
- if (ctx == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) {
- return BAD_FUNC_ARG;
- }
-
- /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/
- if (buf == NULL || bufLen == 0) {
- ctx->rpkConfig.preferred_ServerCertTypeCnt = 1;
- ctx->rpkConfig.preferred_ServerCertTypes[0]= WOLFSSL_CERT_TYPE_X509;
- ctx->rpkConfig.preferred_ServerCertTypes[1]= WOLFSSL_CERT_TYPE_X509;
- return WOLFSSL_SUCCESS;
- }
-
- if (!isArrayUnique(buf, bufLen))
- return BAD_FUNC_ARG;
+ WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list_bytes");
- 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)
+ return WOLFSSL_FAILURE;
- ctx->rpkConfig.preferred_ServerCertTypes[i] = buf[i];
- }
- ctx->rpkConfig.preferred_ServerCertTypeCnt = bufLen;
+ if (AllocateCtxSuites(ctx) != 0)
+ return WOLFSSL_FAILURE;
- return WOLFSSL_SUCCESS;
+ return (SetCipherListFromBytes(ctx, ctx->suites, list, listSz)) ?
+ WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
}
+#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */
-/* 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_set_cipher_list(WOLFSSL* ssl, const char* list)
{
- int i;
-
- if (ssl == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) {
- return BAD_FUNC_ARG;
- }
+ WOLFSSL_ENTER("wolfSSL_set_cipher_list");
- /* 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;
+ if (ssl == NULL || ssl->ctx == NULL) {
+ return WOLFSSL_FAILURE;
}
- 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];
- }
- ssl->options.rpkConfig.preferred_ClientCertTypeCnt = bufLen;
+ if (AllocateSuites(ssl) != 0)
+ return WOLFSSL_FAILURE;
- return WOLFSSL_SUCCESS;
+#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
}
-/* 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 defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES)
+int wolfSSL_set_cipher_list_bytes(WOLFSSL* ssl, const byte* list,
+ const int listSz)
{
- int i;
-
- if (ssl == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) {
- return BAD_FUNC_ARG;
- }
+ WOLFSSL_ENTER("wolfSSL_set_cipher_list_bytes");
- /* 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 == NULL || ssl->ctx == NULL) {
+ return WOLFSSL_FAILURE;
}
- if (!isArrayUnique(buf, bufLen))
- return BAD_FUNC_ARG;
+ if (AllocateSuites(ssl) != 0)
+ return WOLFSSL_FAILURE;
- for (i = 0; i < bufLen; i++){
- if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509)
- return BAD_FUNC_ARG;
+ return (SetCipherListFromBytes(ssl->ctx, ssl->suites, list, listSz))
+ ? WOLFSSL_SUCCESS
+ : WOLFSSL_FAILURE;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */
- ssl->options.rpkConfig.preferred_ServerCertTypes[i] = buf[i];
- }
- ssl->options.rpkConfig.preferred_ServerCertTypeCnt = bufLen;
- return WOLFSSL_SUCCESS;
-}
+#ifdef HAVE_KEYING_MATERIAL
-/* 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)
-{
- int ret = WOLFSSL_SUCCESS;
-
- if (ssl == NULL || tp == NULL)
- return BAD_FUNC_ARG;
+#define TLS_PRF_LABEL_CLIENT_FINISHED "client finished"
+#define TLS_PRF_LABEL_SERVER_FINISHED "server finished"
+#define TLS_PRF_LABEL_MASTER_SECRET "master secret"
+#define TLS_PRF_LABEL_EXT_MASTER_SECRET "extended master secret"
+#define TLS_PRF_LABEL_KEY_EXPANSION "key expansion"
- if (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;
-}
+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},
+};
-/* 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.
+/**
+ * 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
*/
-WOLFSSL_API int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp)
+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)
{
- int ret = WOLFSSL_SUCCESS;
+ byte* seed = NULL;
+ word32 seedLen;
+ const struct ForbiddenLabels* fl;
- if (ssl == NULL || tp == NULL)
- return BAD_FUNC_ARG;
+ WOLFSSL_ENTER("wolfSSL_export_keying_material");
- 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;
+ if (ssl == NULL || out == NULL || label == NULL ||
+ (use_context && contextLen && context == NULL)) {
+ WOLFSSL_MSG("Bad argument");
+ return WOLFSSL_FAILURE;
}
- return ret;
-}
-#endif /* HAVE_RPK */
+ /* clientRandom + serverRandom
+ * OR
+ * clientRandom + serverRandom + ctx len encoding + ctx */
+ seedLen = !use_context ? (word32)SEED_LEN :
+ (word32)SEED_LEN + 2 + (word32)contextLen;
-int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der,
- int derSz)
-{
- long idx = 0;
+ 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;
+ }
- 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;
+ /* 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)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;
- }
+#ifdef WOLFSSL_TLS13
+ if (IsAtLeastTLSv1_3(ssl->version)) {
+ /* Path for TLS 1.3 */
+ if (!use_context) {
+ contextLen = 0;
+ context = (byte*)""; /* Give valid pointer for 0 length memcpy */
+ }
- if (ProcessFile(ssl->ctx, file, format, CERT_TYPE,
- ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
+ if (Tls13_Exporter(ssl, out, (word32)outLen, label, labelLen,
+ context, contextLen) != 0) {
+ WOLFSSL_MSG("Tls13_Exporter error");
+ return WOLFSSL_FAILURE;
+ }
return WOLFSSL_SUCCESS;
}
+#endif
- return WOLFSSL_FAILURE;
-}
-
-
-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;
- }
-
- if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE,
- ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
+ /* Path for <=TLS 1.2 */
+ seed = (byte*)XMALLOC(seedLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (seed == NULL) {
+ WOLFSSL_MSG("malloc error");
+ return WOLFSSL_FAILURE;
}
- return WOLFSSL_FAILURE;
-}
-
-
-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");
+ XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN);
+ XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN);
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
+ if (use_context) {
+ /* Encode len in big endian */
+ seed[SEED_LEN ] = (contextLen >> 8) & 0xFF;
+ seed[SEED_LEN + 1] = (contextLen) & 0xFF;
+ if (contextLen) {
+ /* 0 length context is allowed */
+ XMEMCPY(seed + SEED_LEN + 2, context, contextLen);
+ }
}
- if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE,
- ssl, 1, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
+ PRIVATE_KEY_UNLOCK();
+ if (wc_PRF_TLS(out, (word32)outLen, ssl->arrays->masterSecret, SECRET_LEN,
+ (byte*)label, (word32)labelLen, seed, seedLen,
+ IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, ssl->heap,
+ ssl->devId) != 0) {
+ WOLFSSL_MSG("wc_PRF_TLS error");
+ PRIVATE_KEY_LOCK();
+ XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_FAILURE;
}
+ PRIVATE_KEY_LOCK();
- return WOLFSSL_FAILURE;
+ XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_SUCCESS;
}
+#endif /* HAVE_KEYING_MATERIAL */
-int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file,
- int format)
+int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl)
{
- /* process up to MAX_CHAIN_DEPTH plus subject cert */
- WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format");
+ int useNb = 0;
- if (ssl == NULL) {
- return BAD_FUNC_ARG;
- }
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
- if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1,
- NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) {
- return WOLFSSL_SUCCESS;
+ WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock");
+ if (ssl->options.dtls) {
+#ifdef WOLFSSL_DTLS
+ useNb = ssl->options.dtlsUseNonblock;
+#endif
}
- return WOLFSSL_FAILURE;
+ else {
+ WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is "
+ "DEPRECATED for non-DTLS use.");
+ }
+ return useNb;
}
-#endif /* !NO_FILESYSTEM */
-#ifdef HAVE_ECC
+#ifndef WOLFSSL_LEANPSK
-/* 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)
+void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock)
{
- if (ctx == NULL)
- return BAD_FUNC_ARG;
+ (void)nonblock;
- /* 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;
+ WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock");
- if (ctx->privateKeySz == 0) {
- WOLFSSL_MSG("Must set private key/cert first");
- return BAD_FUNC_ARG;
- }
+ if (ssl == NULL)
+ return;
- sz = (word16)ctx->privateKeySz;
+ 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.");
}
+}
- /* 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;
+#ifdef WOLFSSL_DTLS
- return WOLFSSL_SUCCESS;
+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
-/* Set Temp SSL EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */
-int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz)
+/*
+ * 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)
{
- if (ssl == NULL)
- return BAD_FUNC_ARG;
+ return ssl->dtls13FastTimeout;
+}
- /* 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;
+/*
+ * When this is set, a DTLS 1.3 connection will send acks immediately when a
+ * disruption is detected to shortcut timeouts. This results in potentially
+ * more traffic but may make the handshake quicker.
+ */
+void wolfSSL_dtls13_set_send_more_acks(WOLFSSL* ssl, int value)
+{
+ if (ssl != NULL)
+ ssl->options.dtls13SendMoreAcks = !!value;
+}
+#endif /* WOLFSSL_DTLS13 */
- ssl->eccTempKeySz = sz;
+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;
+}
- 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
-#endif /* HAVE_ECC */
+#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
+/* 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;
-#ifdef OPENSSL_EXTRA
+ if (timeout > ssl->dtls_timeout_max) {
+ WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout "
+ "max");
+ return BAD_FUNC_ARG;
+ }
-#ifndef NO_FILESYSTEM
-int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file,
- int format)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey_file");
+ ssl->dtls_timeout_init = timeout;
+ ssl->dtls_timeout = timeout;
- return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format);
+ return WOLFSSL_SUCCESS;
}
-int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format)
+/* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */
+int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout)
{
- WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file");
+ if (ssl == NULL || timeout < 0)
+ return BAD_FUNC_ARG;
+
+ if (timeout < ssl->dtls_timeout_init) {
+ WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init");
+ return BAD_FUNC_ARG;
+ }
+
+ ssl->dtls_timeout_max = timeout;
- return wolfSSL_use_PrivateKey_file(ssl, file, format);
+ return WOLFSSL_SUCCESS;
}
-#endif /* NO_FILESYSTEM */
-/* 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 wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
{
- int size;
+ int result = WOLFSSL_SUCCESS;
+ WOLFSSL_ENTER("wolfSSL_dtls_got_timeout");
- ses = ClientSessionToSession(ses);
+ if (ssl == NULL || !ssl->options.dtls)
+ return WOLFSSL_FATAL_ERROR;
- if (outSz == 0) {
- return SECRET_LEN;
- }
+#ifdef WOLFSSL_DTLS13
+ if (IsAtLeastTLSv1_3(ssl->version)) {
+ result = Dtls13RtxTimeout(ssl);
+ if (result < 0) {
+ if (result == WC_NO_ERR_TRACE(WANT_WRITE))
+ ssl->dtls13SendingAckOrRtx = 1;
+ ssl->error = result;
+ WOLFSSL_ERROR(result);
+ return WOLFSSL_FATAL_ERROR;
+ }
- if (ses == NULL || out == NULL || outSz < 0) {
- return 0;
+ return WOLFSSL_SUCCESS;
}
+#endif /* WOLFSSL_DTLS13 */
- if (outSz > SECRET_LEN) {
- size = SECRET_LEN;
- }
- else {
- size = outSz;
+ /* Do we have any 1.2 messages stored? */
+ if (ssl->dtls_tx_msg_list != NULL || ssl->dtls_tx_msg != NULL) {
+ 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;
+ }
}
- XMEMCPY(out, ses->masterSecret, size);
- return size;
+ WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout", result);
+ return result;
}
-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)
+/* retransmit all the saves messages, WOLFSSL_SUCCESS on ok */
+int wolfSSL_dtls_retransmit(WOLFSSL* ssl)
{
- 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;
+ WOLFSSL_ENTER("wolfSSL_dtls_retransmit");
-static SetVerifyOptions ModeToVerifyOptions(int mode)
-{
- SetVerifyOptions opts;
- XMEMSET(&opts, 0, sizeof(SetVerifyOptions));
+ if (ssl == NULL)
+ return WOLFSSL_FATAL_ERROR;
- 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;
+ if (!ssl->options.handShakeDone) {
+ int result;
+#ifdef WOLFSSL_DTLS13
+ if (IsAtLeastTLSv1_3(ssl->version))
+ result = Dtls13DoScheduledWork(ssl);
+ else
#endif
+ result = DtlsMsgPoolSend(ssl, 0);
+ if (result < 0) {
+ ssl->error = result;
+ WOLFSSL_ERROR(result);
+ return WOLFSSL_FATAL_ERROR;
}
}
- return opts;
+ return WOLFSSL_SUCCESS;
}
-WOLFSSL_ABI
-void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc)
-{
- SetVerifyOptions opts;
+#endif /* DTLS */
+#endif /* LEANPSK */
- WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
- if (ctx == NULL)
- return;
- opts = ModeToVerifyOptions(mode);
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
- 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
+/* 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;
- ctx->verifyCallback = vc;
-}
+ WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret");
-#ifdef OPENSSL_ALL
-void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx,
- CertVerifyCallback cb, void* arg)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_set_cert_verify_callback");
- if (ctx == NULL)
- return;
+ if (ssl == NULL) {
+ WOLFSSL_MSG("need a SSL object");
+ return BAD_FUNC_ARG;
+ }
- ctx->verifyCertCb = cb;
- ctx->verifyCertCbArg = arg;
-}
-#endif
+ if (secret != NULL && secretSz == 0) {
+ WOLFSSL_MSG("can't have a new secret without a size");
+ return BAD_FUNC_ARG;
+ }
+ /* If secretSz is 0, use the default size. */
+ if (secretSz == 0)
+ secretSz = COOKIE_SECRET_SZ;
-void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc)
-{
- SetVerifyOptions opts;
+ if (secretSz != ssl->buffers.dtlsCookieSecret.length) {
+ byte* newSecret;
- WOLFSSL_ENTER("wolfSSL_set_verify");
- if (ssl == NULL)
- return;
+ 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);
+ }
- opts = ModeToVerifyOptions(mode);
+ 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
+ }
- ssl->options.verifyNone = opts.verifyNone;
- ssl->options.verifyPeer = opts.verifyPeer;
- ssl->options.failNoCert = opts.failNoCert;
- ssl->options.failNoCertxPSK = opts.failNoCertxPSK;
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- ssl->options.verifyPostHandshake = opts.verifyPostHandshake;
-#endif
+ /* If 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);
- ssl->verifyCallback = vc;
+ WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0);
+ return ret;
}
-void wolfSSL_set_verify_result(WOLFSSL *ssl, long v)
-{
- WOLFSSL_ENTER("wolfSSL_set_verify_result");
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
- 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
-}
-
-#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
- defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-/* For TLS v1.3 send handshake messages after handshake completes. */
-/* Returns 1=WOLFSSL_SUCCESS or 0=WOLFSSL_FAILURE */
-int wolfSSL_verify_client_post_handshake(WOLFSSL* ssl)
-{
- int ret = wolfSSL_request_certificate(ssl);
- if (ret != WOLFSSL_SUCCESS) {
- if (!IsAtLeastTLSv1_3(ssl->version)) {
- /* specific error of wrong version expected */
- WOLFSSL_ERROR(UNSUPPORTED_PROTO_VERSION);
-
- }
- else {
- WOLFSSL_ERROR(ret); /* log the error in the error queue */
- }
+/* EITHER SIDE METHODS */
+#if !defined(NO_TLS) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE))
+ WOLFSSL_METHOD* wolfSSLv23_method(void)
+ {
+ return wolfSSLv23_method_ex(NULL);
}
- return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
-}
+ 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;
+ }
-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 m;
}
- 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;
-}
+ #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 /* !NO_TLS && (OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE) */
-/* 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;
-}
+/* client only parts */
+#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
+ #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS)
+ WOLFSSL_METHOD* wolfSSLv2_client_method(void)
+ {
+ WOLFSSL_STUB("wolfSSLv2_client_method");
+ return NULL;
+ }
+ #endif
-/* 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(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 */
-#if defined(PERSIST_CERT_CACHE)
+ WOLFSSL_METHOD* wolfSSLv23_client_method(void)
+ {
+ return wolfSSLv23_client_method_ex(NULL);
+ }
+ WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap)
+ {
+ WOLFSSL_METHOD* method =
+ (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
+ heap, DYNAMIC_TYPE_METHOD);
+ (void)heap;
+ WOLFSSL_ENTER("wolfSSLv23_client_method_ex");
+ if (method) {
+ #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || \
+ defined(WOLFSSL_SHA512)
+ #if defined(WOLFSSL_TLS13)
+ InitSSL_Method(method, MakeTLSv1_3());
+ #elif !defined(WOLFSSL_NO_TLS12)
+ InitSSL_Method(method, MakeTLSv1_2());
+ #elif !defined(NO_OLD_TLS)
+ InitSSL_Method(method, MakeTLSv1_1());
+ #endif
+ #else
+ #ifndef NO_OLD_TLS
+ InitSSL_Method(method, MakeTLSv1_1());
+ #endif
+ #endif
+ #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13)
+ method->downgrade = 1;
+ #endif
+ }
+ return method;
+ }
-#if !defined(NO_FILESYSTEM)
+ /* 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;
-/* 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;
+ #ifdef HAVE_ERRNO_H
+ errno = 0;
+ #endif
- return CM_SaveCertCache(ctx->cm, fname);
-}
+ 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 */
+ }
-/* Persist cert cache from file */
-int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache");
+ #ifdef OPENSSL_EXTRA
+ if (ssl->CBIS != NULL) {
+ ssl->CBIS(ssl, WOLFSSL_ST_CONNECT, WOLFSSL_SUCCESS);
+ ssl->cbmode = WOLFSSL_CB_WRITE;
+ }
+ #endif
+ #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
- if (ctx == NULL || fname == NULL)
- return BAD_FUNC_ARG;
+ #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
- return CM_RestoreCertCache(ctx->cm, fname);
-}
+ WOLFSSL_MSG("TLS 1.2 or lower");
+ WOLFSSL_ENTER("wolfSSL_connect");
-#endif /* NO_FILESYSTEM */
+ /* 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;
+ }
-/* 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 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 */
- if (ctx == NULL || mem == NULL || used == NULL || sz <= 0)
- return BAD_FUNC_ARG;
+ if (ssl->options.side != WOLFSSL_CLIENT_END) {
+ ssl->error = SIDE_ERROR;
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
- return CM_MemSaveCertCache(ctx->cm, mem, sz, used);
-}
+ #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));
-/* Restore cert cache from memory */
-int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache");
-
- if (ctx == NULL || mem == NULL || sz <= 0)
- return BAD_FUNC_ARG;
-
- return CM_MemRestoreCertCache(ctx->cm, mem, sz);
-}
-
-
-/* get how big the the cert cache save buffer needs to be */
-int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize");
-
- if (ctx == NULL)
- return BAD_FUNC_ARG;
-
- return CM_GetCertCacheMemSize(ctx->cm);
-}
-
-#endif /* PERSIST_CERT_CACHE */
-#endif /* !NO_CERTS */
-
-
-#ifndef NO_SESSION_CACHE
+#ifdef WOLFSSL_DTLS13
+ if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version))
+ advanceState = advanceState && !ssl->dtls13SendingAckOrRtx;
+#endif /* WOLFSSL_DTLS13 */
-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_NO_ERR_TRACE(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
+ }
}
- 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("connect 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.connectState) {
- 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;
- }
+ 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;
- 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);
+ 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
- WOLFSSL_MSG("wolfSSL_SetSession failed");
- session = NULL;
+ /* 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 == WC_NO_ERR_TRACE(WANT_WRITE))
+ ssl->dtls13SendingAckOrRtx = 1;
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+#endif /* WOLFSSL_DTLS13 */
}
- }
- }
- if (session == NULL) {
- WOLFSSL_MSG("Valid ServerID not cached already");
+ ssl->options.connectState = HELLO_AGAIN;
+ WOLFSSL_MSG("connect state: HELLO_AGAIN");
+ FALL_THROUGH;
- ssl->session->idLen = (word16)len;
- XMEMCPY(ssl->session->serverID, id, len);
- }
-#ifdef HAVE_EXT_CACHE
- else {
- wolfSSL_FreeSession(ssl->ctx, session);
- }
-#endif
+ case HELLO_AGAIN :
- return WOLFSSL_SUCCESS;
-}
+ #ifdef WOLFSSL_TLS13
+ if (ssl->options.tls1_3)
+ return wolfSSL_connect_TLSv13(ssl);
+ #endif
-#endif /* !NO_CLIENT_CACHE */
+ #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
-/* 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)
+ ssl->options.connectState = HELLO_AGAIN_REPLY;
+ WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
+ FALL_THROUGH;
-/* 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
+ case HELLO_AGAIN_REPLY :
+ #ifdef WOLFSSL_DTLS
+ if (IsDtlsNotSctpMode(ssl)) {
+ neededState = ssl->options.resuming ?
+ SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE;
-/* 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;
+ /* 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
-/* current persistence layout is:
+ ssl->options.connectState = FIRST_REPLY_DONE;
+ WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
+ FALL_THROUGH;
- 1) cache_header_t
- 2) SessionCache
- 3) ClientCache
+ 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");
+ }
- update WOLFSSL_CACHE_VERSION if change layout for the following
- PERSISTENT_SESSION_CACHE functions
-*/
+ #endif
+ ssl->options.connectState = FIRST_REPLY_FIRST;
+ WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
+ 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));
+ 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 == WC_NO_ERR_TRACE(NO_PEER_KEY) ||
+ ssl->error == WC_NO_ERR_TRACE(PSK_KEY_ERROR)) {
+ SendAlert(ssl, alert_fatal, handshake_failure);
+ }
#endif
- return sz;
-}
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ WOLFSSL_MSG("sent: client key exchange");
+ }
+ ssl->options.connectState = FIRST_REPLY_SECOND;
+ WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
+ FALL_THROUGH;
-/* Persist 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));
+ #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
+ case FIRST_REPLY_SECOND :
+ /* CLIENT: Fail-safe for Server Authentication. */
+ if (!ssl->options.peerAuthGood) {
+ WOLFSSL_MSG("Server authentication did not happen");
+ ssl->error = NO_PEER_VERIFY;
+ return WOLFSSL_FATAL_ERROR;
+ }
- WOLFSSL_ENTER("wolfSSL_memsave_session_cache");
+ #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH)
+ if (ssl->options.sendVerify) {
+ if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
+ #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
+ ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
+ #endif
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ WOLFSSL_MSG("sent: certificate verify");
+ }
+ #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */
+ ssl->options.connectState = FIRST_REPLY_THIRD;
+ WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD");
+ FALL_THROUGH;
- if (sz < wolfSSL_get_session_cache_memsize()) {
- WOLFSSL_MSG("Memory buffer too small");
- return BUFFER_E;
- }
+ 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;
- 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));
+ 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;
-#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
+#ifdef WOLFSSL_DTLS13
+ case WAIT_FINISHED_ACK:
+ ssl->options.connectState = FINISHED_DONE;
+ FALL_THROUGH;
+#endif /* WOLFSSL_DTLS13 */
- 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
+ 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;
+ }
-#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
+ ssl->options.connectState = SECOND_REPLY_DONE;
+ WOLFSSL_MSG("connect state: SECOND_REPLY_DONE");
+ FALL_THROUGH;
- WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS);
+ 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 */
- return WOLFSSL_SUCCESS;
-}
+ if (!ssl->options.dtls) {
+ if (!ssl->options.keepResources) {
+ FreeHandshakeResources(ssl);
+ }
+ }
+ #ifdef WOLFSSL_DTLS
+ else {
+ ssl->options.dtlsHsRetain = 1;
+ }
+ #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;
+ }
+ #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
-/* 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));
+ ssl->error = 0; /* clear the error */
- WOLFSSL_ENTER("wolfSSL_memrestore_session_cache");
+ WOLFSSL_LEAVE("wolfSSL_connect", WOLFSSL_SUCCESS);
+ return WOLFSSL_SUCCESS;
+ #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */
- if (sz < wolfSSL_get_session_cache_memsize()) {
- WOLFSSL_MSG("Memory buffer too small");
- return BUFFER_E;
+ default:
+ WOLFSSL_MSG("Unknown connect state ERROR");
+ return WOLFSSL_FATAL_ERROR; /* unknown connect state */
+ }
+ #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS || !WOLFSSL_TLS13 */
}
- 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)) {
+#endif /* !NO_WOLFSSL_CLIENT && !NO_TLS */
+/* end client only parts */
- WOLFSSL_MSG("Session cache header match failed");
- return CACHE_MATCH_ERROR;
- }
+/* server only parts */
+#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
-#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;
+ #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS)
+ WOLFSSL_METHOD* wolfSSLv2_server_method(void)
+ {
+ WOLFSSL_STUB("wolfSSLv2_server_method");
+ return 0;
}
-#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;
+ #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
+ WOLFSSL_METHOD* wolfSSLv3_server_method(void)
+ {
+ return wolfSSLv3_server_method_ex(NULL);
}
- 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;
+ 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;
}
- cache_header.version = WOLFSSL_CACHE_VERSION;
- cache_header.rows = SESSION_ROWS;
- cache_header.columns = SESSIONS_PER_ROW;
- cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
+ #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
- /* 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;
+ WOLFSSL_METHOD* wolfSSLv23_server_method(void)
+ {
+ return wolfSSLv23_server_method_ex(NULL);
}
-#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;
- }
+ 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
-
- ret = (int)XFWRITE(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file);
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- SESSION_ROW_UNLOCK(&SessionCache[i]);
+ #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13)
+ method->downgrade = 1;
#endif
- if (ret != 1) {
- WOLFSSL_MSG("Session cache member file write failed");
- rc = FWRITE_ERROR;
- break;
+ method->side = WOLFSSL_SERVER_END;
}
+ return method;
}
-#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);
+ WOLFSSL_ABI
+ int wolfSSL_accept(WOLFSSL* ssl)
+ {
+#if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && \
+ defined(WOLFSSL_TLS13))
+ word16 havePSK = 0;
+ word16 haveAnon = 0;
+ word16 haveMcast = 0;
+#endif
+ int ret = 0;
- return rc;
-}
+ (void)ret;
+ if (ssl == NULL)
+ return WOLFSSL_FATAL_ERROR;
-/* 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;
+ #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
+ #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
- ret = (int)XFREAD(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file);
- #ifdef ENABLE_SESSION_CACHE_ROW_LOCK
- SESSION_ROW_UNLOCK(&SessionCache[i]);
+#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
- 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 */
-#endif /* NO_SESSION_CACHE */
+ WOLFSSL_ENTER("wolfSSL_accept");
+ /* make sure this wolfSSL object has arrays and rng setup. Protects
+ * case where the WOLFSSL object is reused via wolfSSL_clear() */
+ if ((ret = ReinitSSL(ssl, ssl->ctx, 0)) != 0) {
+ return ret;
+ }
-void wolfSSL_load_error_strings(void)
-{
- /* compatibility only */
-}
+#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 */
+ #ifdef HAVE_ERRNO_H
+ errno = 0;
+ #endif
-int wolfSSL_library_init(void)
-{
- WOLFSSL_ENTER("wolfSSL_library_init");
- if (wolfSSL_Init() == WOLFSSL_SUCCESS)
- return WOLFSSL_SUCCESS;
- else
- return WOLFSSL_FATAL_ERROR;
-}
+ #ifndef NO_PSK
+ havePSK = ssl->options.havePSK;
+ #endif
+ (void)havePSK;
+ #ifdef HAVE_ANON
+ haveAnon = ssl->options.useAnon;
+ #endif
+ (void)haveAnon;
-#ifdef HAVE_SECRET_CALLBACK
+ #ifdef WOLFSSL_MULTICAST
+ haveMcast = ssl->options.haveMcast;
+ #endif
+ (void)haveMcast;
-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 (ssl->options.side != WOLFSSL_SERVER_END) {
+ ssl->error = SIDE_ERROR;
+ WOLFSSL_ERROR(ssl->error);
+ 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;
- }
+ #ifndef NO_CERTS
+ /* in case used set_accept_state after init */
+ if (!havePSK && !haveAnon && !haveMcast) {
+ #ifdef WOLFSSL_CERT_SETUP_CB
+ 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) {
- return WOLFSSL_SUCCESS;
-}
+ WOLFSSL_MSG("accept error: server cert required");
+ ssl->error = NO_PRIVATE_KEY;
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
-#endif
+ 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
+ #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) || IsSCR(ssl))
+ ssl->options.dtlsStateful = 1;
+ }
+ #endif
-#ifndef NO_SESSION_CACHE
+ 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_NO_ERR_TRACE(WC_PENDING_E)
+ #endif
+ ) {
+ ret = SendBuffered(ssl);
+ if (ret == 0) {
+ /* fragOffset is non-zero when sending fragments. On the last
+ * fragment, fragOffset is zero again, and the state can be
+ * advanced. */
+ if (ssl->fragOffset == 0 && !ssl->options.buildingMsg) {
+ if (ssl->options.acceptState == ACCEPT_FIRST_REPLY_DONE ||
+ ssl->options.acceptState == SERVER_HELLO_SENT ||
+ ssl->options.acceptState == CERT_SENT ||
+ ssl->options.acceptState == CERT_STATUS_SENT ||
+ ssl->options.acceptState == KEY_EXCHANGE_SENT ||
+ ssl->options.acceptState == CERT_REQ_SENT ||
+ ssl->options.acceptState == ACCEPT_SECOND_REPLY_DONE ||
+ ssl->options.acceptState == TICKET_SENT ||
+ ssl->options.acceptState == CHANGE_CIPHER_SENT) {
+ ssl->options.acceptState++;
+ WOLFSSL_MSG("accept state: Advanced from last "
+ "buffered fragment send");
+ #ifdef WOLFSSL_ASYNC_IO
+ /* Cleanup async */
+ FreeAsyncCtx(ssl, 0);
+ #endif
+ }
+ }
+ else {
+ WOLFSSL_MSG("accept state: "
+ "Not advanced, more fragments to send");
+ }
+ }
+ else {
+ ssl->error = ret;
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+#ifdef WOLFSSL_DTLS13
+ if (ssl->options.dtls)
+ ssl->dtls13SendingAckOrRtx = 0;
+#endif /* WOLFSSL_DTLS13 */
+ }
-/* 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");
+ ret = RetrySendAlert(ssl);
+ if (ret != 0) {
+ ssl->error = ret;
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
- if (ctx == NULL)
- return WOLFSSL_FAILURE;
+ switch (ssl->options.acceptState) {
- if (mode == WOLFSSL_SESS_CACHE_OFF) {
- ctx->sessionCacheOff = 1;
-#ifdef HAVE_EXT_CACHE
- ctx->internalCacheOff = 1;
- ctx->internalCacheLookupOff = 1;
+ case ACCEPT_BEGIN :
+#ifdef HAVE_SECURE_RENEGOTIATION
+ case ACCEPT_BEGIN_RENEG:
#endif
- }
-
- if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0)
- ctx->sessionCacheFlushOff = 1;
+ /* 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;
-#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;
+ case ACCEPT_CLIENT_HELLO_DONE :
+ if (ssl->options.tls1_3) {
+ return wolfSSL_accept_TLSv13(ssl);
+ }
#endif
- return WOLFSSL_SUCCESS;
-}
+ ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
+ WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+ FALL_THROUGH;
-#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;
+ case ACCEPT_FIRST_REPLY_DONE :
+ if (ssl->options.returnOnGoodCh) {
+ /* Higher level in stack wants us to return. Simulate a
+ * WANT_WRITE to accomplish this. */
+ ssl->error = WANT_WRITE;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ 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;
- WOLFSSL_ENTER("wolfSSL_CTX_get_session_cache_mode");
+ 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;
- if (ctx == NULL) {
- return m;
- }
+ 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;
- if (ctx->sessionCacheOff != 1) {
- m |= WOLFSSL_SESS_CACHE_SERVER;
- }
+ 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;
- if (ctx->sessionCacheFlushOff == 1) {
- m |= WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR;
- }
+ 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;
-#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
+ case CERT_REQ_SENT :
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendServerHelloDone(ssl)) != 0) {
+ #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
+ ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
+ #endif
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = SERVER_HELLO_DONE;
+ WOLFSSL_MSG("accept state SERVER_HELLO_DONE");
+ FALL_THROUGH;
- return m;
-}
-#endif /* OPENSSL_EXTRA */
+ case SERVER_HELLO_DONE :
+ if (!ssl->options.resuming) {
+ while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ WOLFSSL_ERROR(ssl->error);
+ return WOLFSSL_FATAL_ERROR;
+ }
+ }
+ ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE;
+ WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
+ FALL_THROUGH;
-#endif /* NO_SESSION_CACHE */
+ case ACCEPT_SECOND_REPLY_DONE :
+ #ifndef NO_CERTS
+ /* SERVER: When not resuming and verifying peer but no certificate
+ * received and not failing when not received then peer auth good.
+ */
+ if (!ssl->options.resuming && ssl->options.verifyPeer &&
+ !ssl->options.havePeerCert && !ssl->options.failNoCert) {
+ ssl->options.peerAuthGood = 1;
+ }
+ #endif /* !NO_CERTS */
+ #ifdef WOLFSSL_NO_CLIENT_AUTH
+ if (!ssl->options.resuming) {
+ ssl->options.peerAuthGood = 1;
+ }
+ #endif
-#ifdef OPENSSL_EXTRA
+#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;
-/*
- * 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;
+ case TICKET_SENT:
+ /* SERVER: Fail-safe for CLient Authentication. */
+ if (!ssl->options.peerAuthGood) {
+ WOLFSSL_MSG("Client authentication did not happen");
+ return WOLFSSL_FATAL_ERROR;
+ }
- do {
- char* current = next;
- char name[MAX_SUITE_NAME + 1];
- word32 length = MAX_SUITE_NAME;
- word32 current_length;
+ 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;
- next = XSTRSTR(next, ":");
+ 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;
+ }
- current_length = (!next) ? (word32)XSTRLEN(current)
- : (word32)(next - current);
+ ssl->options.acceptState = ACCEPT_FINISHED_DONE;
+ WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
+ FALL_THROUGH;
- if (current_length < length) {
- length = current_length;
- }
- XMEMCPY(name, current, length);
- name[length] = 0;
+ 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;
- if (XSTRCMP(name, "ALL") == 0 || XSTRCMP(name, "DEFAULT") == 0 ||
- XSTRCMP(name, "HIGH") == 0) {
- findTLSv13Suites = 1;
- findbeforeSuites = 1;
- break;
- }
+ 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 */
- ret = wolfSSL_get_cipher_suite_from_name(name, &cipherSuite0,
- &cipherSuite1, &flags);
- if (ret == 0) {
- if (cipherSuite0 == TLS13_BYTE) {
- /* TLSv13 suite */
- findTLSv13Suites = 1;
+ if (!ssl->options.dtls) {
+ if (!ssl->options.keepResources) {
+ FreeHandshakeResources(ssl);
+ }
}
+#ifdef WOLFSSL_DTLS
else {
- findbeforeSuites = 1;
+ ssl->options.dtlsHsRetain = 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;
+#endif /* WOLFSSL_DTLS */
- do {
- subStrNext = XSTRSTR(subStr, "+");
+#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 ((XSTRCMP(subStr, "ECDHE") == 0) ||
- (XSTRCMP(subStr, "RSA") == 0)) {
- return 0;
+#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 */
- if (subStrNext && (XSTRLEN(subStrNext) > 0)) {
- subStr = subStrNext + 1; /* +1 to skip past '+' */
- }
- } while (subStrNext != NULL);
- }
- #endif
+ WOLFSSL_LEAVE("wolfSSL_accept", WOLFSSL_SUCCESS);
+ return WOLFSSL_SUCCESS;
- if (findTLSv13Suites == 1 && findbeforeSuites == 1) {
- /* list has mixed suites */
- return 0;
+ default:
+ WOLFSSL_MSG("Unknown accept state ERROR");
+ return WOLFSSL_FATAL_ERROR;
}
+#endif /* !WOLFSSL_NO_TLS12 */
}
- 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 */
- }
+#endif /* !NO_WOLFSSL_SERVER && !NO_TLS */
+/* end server only parts */
+
+
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+struct chGoodDisableReadCbCtx {
+ ClientHelloGoodCb userCb;
+ void* userCtx;
+};
+
+static int chGoodDisableReadCB(WOLFSSL* ssl, void* ctx)
+{
+ struct chGoodDisableReadCbCtx* cb = (struct chGoodDisableReadCbCtx*)ctx;
+ int ret = 0;
+ if (cb->userCb != NULL)
+ ret = cb->userCb(ssl, cb->userCtx);
+ if (ret >= 0)
+ wolfSSL_SSLDisableRead(ssl);
return ret;
}
-/* parse some bulk lists like !eNULL / !aNULL
- *
- * returns WOLFSSL_SUCCESS on success and sets the cipher suite list
+/**
+ * Statelessly listen for a connection
+ * @param ssl The ssl object to use for listening to connections
+ * @return WOLFSSL_SUCCESS - ClientHello containing a valid cookie was received
+ * The connection can be continued with wolfSSL_accept
+ * WOLFSSL_FAILURE - The I/O layer returned WANT_READ. This is either
+ * because there is no data to read and we are using
+ * non-blocking sockets or we sent a cookie request
+ * and we are waiting for a reply. The user should
+ * call wolfDTLS_accept_stateless again after data
+ * becomes available in the I/O layer.
+ * WOLFSSL_FATAL_ERROR - A fatal error occurred. The ssl object should
+ * be free'd and allocated again to continue.
*/
-static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
- Suites* suites, const char* list)
+int wolfDTLS_accept_stateless(WOLFSSL* ssl)
{
- 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;
+ byte disableRead;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
+ struct chGoodDisableReadCbCtx cb;
- if (suites == NULL || list == NULL) {
- WOLFSSL_MSG("NULL argument");
- return WOLFSSL_FAILURE;
- }
+ WOLFSSL_ENTER("wolfDTLS_SetChGoodCb");
- listattribute = CheckcipherList(list);
+ if (ssl == NULL)
+ return WOLFSSL_FATAL_ERROR;
- 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;
- }
- }
+ /* Save this to restore it later */
+ disableRead = (byte)ssl->options.disableRead;
+ cb.userCb = ssl->chGoodCb;
+ cb.userCtx = ssl->chGoodCtx;
- /* 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;
- }
+ /* Register our own callback so that we can disable reading */
+ if (wolfDTLS_SetChGoodCb(ssl, chGoodDisableReadCB, &cb) != WOLFSSL_SUCCESS)
+ return WOLFSSL_FATAL_ERROR;
- XMEMSET(suitesCpy, 0, suites->suiteSz);
+ ssl->options.returnOnGoodCh = 1;
+ ret = wolfSSL_accept(ssl);
+ ssl->options.returnOnGoodCh = 0;
+ /* restore user options */
+ ssl->options.disableRead = disableRead;
+ (void)wolfDTLS_SetChGoodCb(ssl, cb.userCb, cb.userCtx);
+ if (ret == WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("should not happen. maybe the user called "
+ "wolfDTLS_accept_stateless instead of wolfSSL_accept");
}
-#else
- XMEMSET(suitesCpy, 0, sizeof(suitesCpy));
-#endif
-
- if (suites->suiteSz > 0)
- XMEMCPY(suitesCpy, suites->suites, suites->suiteSz);
- suitesCpySz = suites->suiteSz;
-
- ret = SetCipherList_ex(ctx, ssl, suites, list);
- if (ret != 1) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return WOLFSSL_FAILURE;
+ else if (ssl->error == WC_NO_ERR_TRACE(WANT_READ) ||
+ ssl->error == WC_NO_ERR_TRACE(WANT_WRITE)) {
+ ssl->error = 0;
+ if (ssl->options.dtlsStateful)
+ ret = WOLFSSL_SUCCESS;
+ else
+ ret = WOLFSSL_FAILURE;
}
-
- for (i = 0; i < suitesCpySz &&
- suites->suiteSz <= (WOLFSSL_MAX_SUITE_SZ - SUITE_LEN); i += 2) {
- /* Check for duplicates */
- int duplicate = 0;
- for (j = 0; j < suites->suiteSz; j += 2) {
- if (suitesCpy[i] == suites->suites[j] &&
- suitesCpy[i+1] == suites->suites[j+1]) {
- duplicate = 1;
- break;
- }
- }
- 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;
- }
- }
- }
+ else {
+ ret = WOLFSSL_FATAL_ERROR;
}
-
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
return ret;
}
-#endif
-
-
-int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list)
+int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx)
{
- WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list");
+ WOLFSSL_ENTER("wolfDTLS_SetChGoodCb");
- if (ctx == NULL)
- return WOLFSSL_FAILURE;
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
- if (AllocateCtxSuites(ctx) != 0)
- return WOLFSSL_FAILURE;
+ ssl->chGoodCb = cb;
+ ssl->chGoodCtx = user_ctx;
-#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
+ return WOLFSSL_SUCCESS;
}
+#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)
+#ifndef NO_HANDSHAKE_DONE_CB
+
+int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx)
{
- WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list_bytes");
+ WOLFSSL_ENTER("wolfSSL_SetHsDoneCb");
- if (ctx == NULL)
- return WOLFSSL_FAILURE;
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
- if (AllocateCtxSuites(ctx) != 0)
- return WOLFSSL_FAILURE;
+ ssl->hsDoneCb = cb;
+ ssl->hsDoneCtx = user_ctx;
- return (SetCipherListFromBytes(ctx, ctx->suites, list, listSz)) ?
- WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+ return WOLFSSL_SUCCESS;
}
-#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */
-int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list)
-{
- WOLFSSL_ENTER("wolfSSL_set_cipher_list");
+#endif /* NO_HANDSHAKE_DONE_CB */
- if (ssl == NULL || ssl->ctx == NULL) {
- return WOLFSSL_FAILURE;
- }
+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 (AllocateSuites(ssl) != 0)
- return WOLFSSL_FAILURE;
+ WOLFSSL_ENTER("wolfSSL_Cleanup");
-#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;
+#ifndef WOLFSSL_MUTEX_INITIALIZER
+ if (inits_count_mutex_valid == 1) {
+#endif
+ if (wc_LockMutex(&inits_count_mutex) != 0) {
+ WOLFSSL_MSG("Bad Lock Mutex count");
+ return BAD_MUTEX_E;
+ }
+#ifndef WOLFSSL_MUTEX_INITIALIZER
+ }
#endif
-}
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES)
-int wolfSSL_set_cipher_list_bytes(WOLFSSL* ssl, const byte* list,
- const int listSz)
-{
- WOLFSSL_ENTER("wolfSSL_set_cipher_list_bytes");
+ if (initRefCount > 0) {
+ --initRefCount;
+ if (initRefCount == 0)
+ release = 1;
+ }
- if (ssl == NULL || ssl->ctx == NULL) {
- return WOLFSSL_FAILURE;
+#ifndef WOLFSSL_MUTEX_INITIALIZER
+ if (inits_count_mutex_valid == 1) {
+#endif
+ wc_UnLockMutex(&inits_count_mutex);
+#ifndef WOLFSSL_MUTEX_INITIALIZER
}
+#endif
- 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 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},
-};
+ if (!release)
+ return ret;
-/**
- * Implement RFC 5705
- * TLS 1.3 uses a different exporter definition (section 7.5 of RFC 8446)
- * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error
- */
-int wolfSSL_export_keying_material(WOLFSSL *ssl,
- unsigned char *out, size_t outLen,
- const char *label, size_t labelLen,
- const unsigned char *context, size_t contextLen,
- int use_context)
-{
- byte* seed = NULL;
- word32 seedLen;
- const struct ForbiddenLabels* fl;
+#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
+ wolfSSL_crypto_policy_disable();
+#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
- WOLFSSL_ENTER("wolfSSL_export_keying_material");
+#ifdef OPENSSL_EXTRA
+ wolfSSL_BN_free_one();
+#endif
- if (ssl == NULL || out == NULL || label == NULL ||
- (use_context && contextLen && context == NULL)) {
- WOLFSSL_MSG("Bad argument");
- return WOLFSSL_FAILURE;
+#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;
}
-
- /* 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;
+ #else
+ if ((session_lock_valid == 1) && (wc_FreeRwLock(&session_lock) != 0)) {
+ if (ret == WOLFSSL_SUCCESS)
+ ret = BAD_MUTEX_E;
}
-
- /* 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;
+ 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 */
-#ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- /* Path for TLS 1.3 */
- if (!use_context) {
- contextLen = 0;
- context = (byte*)""; /* Give valid pointer for 0 length memcpy */
- }
-
- if (Tls13_Exporter(ssl, out, (word32)outLen, label, labelLen,
- context, contextLen) != 0) {
- WOLFSSL_MSG("Tls13_Exporter error");
- return WOLFSSL_FAILURE;
- }
- return WOLFSSL_SUCCESS;
+#if !defined(WOLFSSL_MUTEX_INITIALIZER) && \
+ !WOLFSSL_CLEANUP_THREADSAFE_BY_ATOMIC_OPS
+ 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
- /* Path for <=TLS 1.2 */
- seed = (byte*)XMALLOC(seedLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (seed == NULL) {
- WOLFSSL_MSG("malloc error");
- return WOLFSSL_FAILURE;
- }
+#ifdef OPENSSL_EXTRA
+ wolfSSL_RAND_Cleanup();
+#endif
- XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN);
- XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN);
+ if (wolfCrypt_Cleanup() != 0) {
+ WOLFSSL_MSG("Error with wolfCrypt_Cleanup call");
+ if (ret == WOLFSSL_SUCCESS)
+ ret = WC_CLEANUP_E;
+ }
- 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 FIPS_VERSION_GE(5,1)
+ if (wolfCrypt_SetPrivateKeyReadEnable_fips(0, WC_KEYTYPE_ALL) < 0) {
+ if (ret == WOLFSSL_SUCCESS)
+ ret = WC_CLEANUP_E;
}
+#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;
+#ifdef HAVE_GLOBAL_RNG
+#ifndef WOLFSSL_MUTEX_INITIALIZER
+ if ((globalRNGMutex_valid == 1) && (wc_FreeMutex(&globalRNGMutex) != 0)) {
+ if (ret == WOLFSSL_SUCCESS)
+ ret = BAD_MUTEX_E;
}
- PRIVATE_KEY_LOCK();
+ globalRNGMutex_valid = 0;
+#endif /* !WOLFSSL_MUTEX_INITIALIZER */
- XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return WOLFSSL_SUCCESS;
+ #if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG)
+ wolfSSL_FIPS_drbg_free(gDrbgDefCtx);
+ gDrbgDefCtx = NULL;
+ #endif
+#endif
+
+#ifdef HAVE_EX_DATA_CRYPTO
+ 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;
}
-#endif /* HAVE_KEYING_MATERIAL */
-int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl)
+
+/* 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)
{
- int useNb = 0;
+ WOLFSSL_ENTER("wolfSSL_check_domain_name");
- if (ssl == NULL)
+ if (ssl == NULL || dn == NULL) {
+ WOLFSSL_MSG("Bad function argument: NULL");
return WOLFSSL_FAILURE;
+ }
- WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock");
- if (ssl->options.dtls) {
-#ifdef WOLFSSL_DTLS
- useNb = ssl->options.dtlsUseNonblock;
-#endif
+ if (ssl->buffers.domainName.buffer)
+ XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+ 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->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 {
- WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is "
- "DEPRECATED for non-DTLS use.");
+ ssl->error = MEMORY_ERROR;
+ return WOLFSSL_FAILURE;
}
- return useNb;
}
+#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
+const char *wolfSSL_get0_peername(WOLFSSL *ssl) {
+ if (ssl == NULL) {
+ return NULL;
+ }
-#ifndef WOLFSSL_LEANPSK
-
-void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock)
-{
- (void)nonblock;
-
- WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock");
-
- if (ssl == NULL)
- return;
-
- if (ssl->options.dtls) {
-#ifdef WOLFSSL_DTLS
- ssl->options.dtlsUseNonblock = (nonblock != 0);
+ if (ssl->buffers.domainName.buffer)
+ return (const char *)ssl->buffers.domainName.buffer;
+ else if (ssl->session && ssl->session->peer)
+ return ssl->session->peer->subjectCN;
+#ifdef KEEP_PEER_CERT
+ else if (ssl->peerCert.subjectCN[0])
+ return ssl->peerCert.subjectCN;
#endif
- }
else {
- WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is "
- "DEPRECATED for non-DTLS use.");
+ ssl->error = NO_PEER_CERT;
+ return NULL;
}
}
+#endif /* SESSION_CERTS && OPENSSL_EXTRA */
-#ifdef WOLFSSL_DTLS
-
-int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl)
+/* turn on wolfSSL zlib compression
+ returns WOLFSSL_SUCCESS for success, else error (not built in)
+*/
+int wolfSSL_set_compression(WOLFSSL* ssl)
{
- int timeout = 0;
- if (ssl)
- timeout = ssl->dtls_timeout;
-
- WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout", timeout);
- return timeout;
+ WOLFSSL_ENTER("wolfSSL_set_compression");
+ (void)ssl;
+#ifdef HAVE_LIBZ
+ ssl->options.usingCompression = 1;
+ return WOLFSSL_SUCCESS;
+#else
+ return NOT_COMPILED_IN;
+#endif
}
-#ifdef WOLFSSL_DTLS13
-/*
- * This API returns 1 when the user should set a short timeout for receiving
- * data. It is recommended that it is at most 1/4 the value returned by
- * wolfSSL_dtls_get_current_timeout().
- */
-int wolfSSL_dtls13_use_quick_timeout(WOLFSSL* ssl)
-{
- return ssl->dtls13FastTimeout;
-}
+#ifndef USE_WINDOWS_API
+ #if !defined(NO_WRITEV) && !defined(NO_TLS)
-/*
- * 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 */
+ /* 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;
+ size_t sending = 0;
+ size_t idx = 0;
+ int i;
+ int ret;
-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;
-}
+ WOLFSSL_ENTER("wolfSSL_writev");
-#ifndef NO_WOLFSSL_STUB
-int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl)
-{
- WOLFSSL_STUB("SSL_DTLSv1_handle_timeout");
- (void)ssl;
- return 0;
-}
-#endif
+ for (i = 0; i < iovcnt; i++)
+ if (! WC_SAFE_SUM_UNSIGNED(size_t, sending, iov[i].iov_len,
+ sending))
+ return BUFFER_E;
-#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 (sending > sizeof(staticBuffer)) {
+ myBuffer = (byte*)XMALLOC(sending, ssl->heap,
+ DYNAMIC_TYPE_WRITEV);
+ if (!myBuffer)
+ return MEMORY_ERROR;
-/* 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;
+ dynamic = 1;
+ }
- if (timeout > ssl->dtls_timeout_max) {
- WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout max");
- return BAD_FUNC_ARG;
- }
+ for (i = 0; i < iovcnt; i++) {
+ XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len);
+ idx += (int)iov[i].iov_len;
+ }
- ssl->dtls_timeout_init = timeout;
- ssl->dtls_timeout = timeout;
+ /* 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_internal(ssl, myBuffer, sending);
+ PRAGMA_GCC_DIAG_POP
- return WOLFSSL_SUCCESS;
-}
+ if (dynamic)
+ XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV);
+ return ret;
+ }
+ #endif
+#endif
-/* 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 (timeout < ssl->dtls_timeout_init) {
- WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init");
- return BAD_FUNC_ARG;
- }
+#ifdef WOLFSSL_CALLBACKS
- ssl->dtls_timeout_max = timeout;
+ typedef struct itimerval Itimerval;
- return WOLFSSL_SUCCESS;
-}
+ /* don't keep calling simple functions while setting up timer and signals
+ if no inlining these are the next best */
+ #define AddTimes(a, b, c) \
+ do { \
+ (c).tv_sec = (a).tv_sec + (b).tv_sec; \
+ (c).tv_usec = (a).tv_usec + (b).tv_usec;\
+ if ((c).tv_usec >= 1000000) { \
+ (c).tv_sec++; \
+ (c).tv_usec -= 1000000; \
+ } \
+ } while (0)
-int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
-{
- int result = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_dtls_got_timeout");
- if (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
+ #define SubtractTimes(a, b, c) \
+ do { \
+ (c).tv_sec = (a).tv_sec - (b).tv_sec; \
+ (c).tv_usec = (a).tv_usec - (b).tv_usec;\
+ if ((c).tv_usec < 0) { \
+ (c).tv_sec--; \
+ (c).tv_usec += 1000000; \
+ } \
+ } while (0)
-#ifdef 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;
- }
+ #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)) \
- 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;
- }
+ /* do nothing handler */
+ static void myHandler(int signo)
+ {
+ (void)signo;
+ return;
}
- 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");
+ static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb,
+ TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
+ {
+ int ret = WC_NO_ERR_TRACE(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 (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
+ #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; }
- if (!ssl->options.handShakeDone) {
- int result = DtlsMsgPoolSend(ssl, 0);
- if (result < 0) {
- ssl->error = result;
- WOLFSSL_ERROR(result);
- return WOLFSSL_FATAL_ERROR;
+ if (hsCb) {
+ ssl->hsInfoOn = 1;
+ InitHandShakeInfo(&ssl->handShakeInfo, ssl);
}
- }
+ if (toCb) {
+ ssl->toInfoOn = 1;
+ InitTimeoutInfo(&ssl->timeoutInfo);
- return 0;
-}
+ if (gettimeofday(&startTime, 0) < 0)
+ ERR_OUT(GETTIME_ERROR);
-#endif /* DTLS */
-#endif /* LEANPSK */
+ /* 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;
-#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+ /* 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;
-/* 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;
+ /* 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);
- WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret");
+ if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0)
+ ERR_OUT(SETITIMER_ERROR);
+ }
- if (ssl == NULL) {
- WOLFSSL_MSG("need a SSL object");
- return BAD_FUNC_ARG;
- }
-
- if (secret != NULL && secretSz == 0) {
- WOLFSSL_MSG("can't have a new secret without a size");
- return BAD_FUNC_ARG;
- }
-
- /* If secretSz is 0, use the default size. */
- if (secretSz == 0)
- secretSz = COOKIE_SECRET_SZ;
+ /* 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 (secretSz != ssl->buffers.dtlsCookieSecret.length) {
- byte* newSecret;
+ /* 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 (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
- ForceZero(ssl->buffers.dtlsCookieSecret.buffer,
- ssl->buffers.dtlsCookieSecret.length);
- XFREE(ssl->buffers.dtlsCookieSecret.buffer,
- ssl->heap, DYNAMIC_TYPE_COOKIE_PWD);
+ /* if 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;
}
- 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;
+ /* clean up buffers allocated by AddPacketInfo */
+ FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap);
+
+ if (hsCb) {
+ FinishHandShakeInfo(&ssl->handShakeInfo);
+ (hsCb)(&ssl->handShakeInfo);
+ ssl->hsInfoOn = 0;
}
- ssl->buffers.dtlsCookieSecret.buffer = newSecret;
- ssl->buffers.dtlsCookieSecret.length = secretSz;
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Add("wolfSSL_DTLS_SetCookieSecret secret",
- ssl->buffers.dtlsCookieSecret.buffer,
- ssl->buffers.dtlsCookieSecret.length);
- #endif
+ return ret;
}
- /* 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);
+
+#ifndef NO_WOLFSSL_CLIENT
+
+ 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);
}
- else
- XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz);
- WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0);
- return ret;
-}
+#endif
-#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+#ifndef NO_WOLFSSL_SERVER
-/* EITHER SIDE METHODS */
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
- WOLFSSL_METHOD* wolfSSLv23_method(void)
+ int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
+ TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
{
- return wolfSSLv23_method_ex(NULL);
+ WOLFSSL_ENTER("wolfSSL_accept_ex");
+ return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
}
- WOLFSSL_METHOD* wolfSSLv23_method_ex(void* heap)
+
+#endif
+
+#endif /* WOLFSSL_CALLBACKS */
+
+
+#ifndef NO_PSK
+
+ void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx,
+ wc_psk_client_callback cb)
{
- WOLFSSL_METHOD* m = NULL;
- WOLFSSL_ENTER("wolfSSLv23_method");
- #if !defined(NO_WOLFSSL_CLIENT)
- m = wolfSSLv23_client_method_ex(heap);
- #elif !defined(NO_WOLFSSL_SERVER)
- m = wolfSSLv23_server_method_ex(heap);
- #else
- (void)heap;
- #endif
- if (m != NULL) {
- m->side = WOLFSSL_NEITHER_END;
- }
+ WOLFSSL_ENTER("wolfSSL_CTX_set_psk_client_callback");
- return m;
+ if (ctx == NULL)
+ return;
+
+ ctx->havePSK = 1;
+ ctx->client_psk_cb = cb;
}
- #ifdef WOLFSSL_ALLOW_SSLV3
- WOLFSSL_METHOD* wolfSSLv3_method(void)
+ void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb)
{
- return wolfSSLv3_method_ex(NULL);
+ byte haveRSA = 1;
+ int keySz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_set_psk_client_callback");
+
+ if (ssl == NULL)
+ return;
+
+ 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.useAnon, TRUE, TRUE, TRUE, TRUE, ssl->options.side);
}
- WOLFSSL_METHOD* wolfSSLv3_method_ex(void* heap)
+ #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_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_set_psk_use_session_callback");
+
+ if (ssl != NULL) {
+ ssl->options.havePSK = 1;
+ ssl->options.session_psk_cb = cb;
}
- return m;
+ WOLFSSL_LEAVE("wolfSSL_set_psk_use_session_callback", 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)
+ void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx,
+ wc_psk_server_callback cb)
{
- WOLFSSL_STUB("wolfSSLv2_client_method");
- return NULL;
+ WOLFSSL_ENTER("wolfSSL_CTX_set_psk_server_callback");
+ if (ctx == NULL)
+ return;
+ ctx->havePSK = 1;
+ ctx->server_psk_cb = cb;
}
- #endif
- #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
- WOLFSSL_METHOD* wolfSSLv3_client_method(void)
+ void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb)
{
- return wolfSSLv3_client_method_ex(NULL);
+ byte haveRSA = 1;
+ int keySz = 0;
+
+ WOLFSSL_ENTER("wolfSSL_set_psk_server_callback");
+ if (ssl == NULL)
+ return;
+
+ ssl->options.havePSK = 1;
+ ssl->options.server_psk_cb = cb;
+
+ #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.useAnon, TRUE, TRUE, TRUE, TRUE, ssl->options.side);
}
- WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap)
+
+ const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl)
{
- 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_get_psk_identity_hint");
+
+ if (ssl == NULL || ssl->arrays == NULL)
+ return NULL;
+
+ return ssl->arrays->server_hint;
}
- #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
- WOLFSSL_METHOD* wolfSSLv23_client_method(void)
+ const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl)
{
- return wolfSSLv23_client_method_ex(NULL);
+ WOLFSSL_ENTER("wolfSSL_get_psk_identity");
+
+ if (ssl == NULL || ssl->arrays == NULL)
+ return NULL;
+
+ return ssl->arrays->client_identity;
}
- 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
+
+ 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 method;
+ return WOLFSSL_SUCCESS;
}
- /* please see note at top of README if you get an error from connect */
- WOLFSSL_ABI
- int wolfSSL_connect(WOLFSSL* ssl)
+ int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint)
{
- #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13))
- int neededState;
- byte advanceState;
- #endif
- int ret = 0;
+ WOLFSSL_ENTER("wolfSSL_use_psk_identity_hint");
- (void)ret;
+ if (ssl == NULL || ssl->arrays == NULL)
+ return WOLFSSL_FAILURE;
- #ifdef HAVE_ERRNO_H
- errno = 0;
- #endif
+ 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;
+ }
+ 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 BAD_FUNC_ARG;
+ 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 */
- #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 */
- }
- #ifdef OPENSSL_EXTRA
- if (ssl->CBIS != NULL) {
- ssl->CBIS(ssl, SSL_ST_CONNECT, WOLFSSL_SUCCESS);
- ssl->cbmode = SSL_CB_WRITE;
- }
- #endif
- #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+#ifdef HAVE_ANON
- #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
+ int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher");
- WOLFSSL_MSG("TLS 1.2 or lower");
- WOLFSSL_ENTER("wolfSSL_connect");
+ if (ctx == NULL)
+ return WOLFSSL_FAILURE;
- /* 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;
+ ctx->useAnon = 1;
+
+ return WOLFSSL_SUCCESS;
+ }
+
+#endif /* HAVE_ANON */
+
+#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;
}
-#ifdef WOLFSSL_WOLFSENTRY_HOOKS
- if ((ssl->ConnectFilter != NULL) &&
- (ssl->options.connectState == CONNECT_BEGIN)) {
- wolfSSL_netfilter_decision_t res;
- if ((ssl->ConnectFilter(ssl, ssl->ConnectFilter_arg, &res) ==
- WOLFSSL_SUCCESS) &&
- (res == WOLFSSL_NETFILTER_REJECT)) {
- ssl->error = SOCKET_FILTERED_E;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
+ if (ssl->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;
}
-#endif /* WOLFSSL_WOLFSENTRY_HOOKS */
- if (ssl->options.side != WOLFSSL_CLIENT_END) {
- ssl->error = SIDE_ERROR;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
+ if (ssl->buffers.weOwnCertChain) {
+ WOLFSSL_MSG("Unloading cert chain");
+ FreeDer(&ssl->buffers.certChain);
+ ssl->buffers.weOwnCertChain = 0;
}
- #ifdef WOLFSSL_DTLS
- if (ssl->version.major == DTLS_MAJOR) {
- ssl->options.dtls = 1;
- ssl->options.tls = 1;
- ssl->options.tls1_1 = 1;
- ssl->options.dtlsStateful = 1;
+ if (ssl->buffers.weOwnKey) {
+ WOLFSSL_MSG("Unloading key");
+ ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
+ FreeDer(&ssl->buffers.key);
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ FreeDer(&ssl->buffers.keyMask);
+ #endif
+ ssl->buffers.weOwnKey = 0;
}
+
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ if (ssl->buffers.weOwnAltKey) {
+ WOLFSSL_MSG("Unloading alt key");
+ ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length);
+ FreeDer(&ssl->buffers.altKey);
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ FreeDer(&ssl->buffers.altKeyMask);
#endif
+ ssl->buffers.weOwnAltKey = 0;
+ }
+#endif /* WOLFSSL_DUAL_ALG_CERTS */
- /* 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));
+ return WOLFSSL_SUCCESS;
+ }
-#ifdef WOLFSSL_DTLS13
- if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version))
- advanceState = advanceState && !ssl->dtls13SendingAckOrRtx;
-#endif /* WOLFSSL_DTLS13 */
- 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 */
- }
+ int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs");
- ret = RetrySendAlert(ssl);
- if (ret != 0) {
- ssl->error = ret;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
- switch (ssl->options.connectState) {
+ return wolfSSL_CertManagerUnloadCAs(ctx->cm);
+ }
- 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;
+ int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx)
+ {
+ int ret;
- 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 */
- }
+ WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts");
- ssl->options.connectState = HELLO_AGAIN;
- WOLFSSL_MSG("connect state: HELLO_AGAIN");
- FALL_THROUGH;
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
- case HELLO_AGAIN :
+ ret = wolfSSL_RefWithMutexLock(&ctx->ref);
+ if (ret < 0)
+ return ret;
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3)
- return wolfSSL_connect_TLSv13(ssl);
- #endif
+ if (ctx->ref.count > 1) {
+ WOLFSSL_MSG("ctx object must have a ref count of 1 before "
+ "unloading intermediate certs");
+ ret = BAD_STATE_E;
+ }
+ else {
+ ret = wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm);
+ }
- #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 (wolfSSL_RefWithMutexUnlock(&ctx->ref) != 0)
+ WOLFSSL_MSG("Failed to unlock mutex!");
- ssl->options.connectState = HELLO_AGAIN_REPLY;
- WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY");
- FALL_THROUGH;
+ return ret;
+ }
- 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
+#ifdef WOLFSSL_TRUST_PEER_CERT
+ int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
- ssl->options.connectState = FIRST_REPLY_DONE;
- WOLFSSL_MSG("connect state: FIRST_REPLY_DONE");
- FALL_THROUGH;
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
- 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");
- }
+ return wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
+ }
- #endif
- ssl->options.connectState = FIRST_REPLY_FIRST;
- WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST");
- FALL_THROUGH;
+#ifdef WOLFSSL_LOCAL_X509_STORE
+ int wolfSSL_Unload_trust_peers(WOLFSSL* ssl)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
- 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 (ssl == NULL)
+ return BAD_FUNC_ARG;
- ssl->options.connectState = FIRST_REPLY_SECOND;
- WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND");
- FALL_THROUGH;
+ SSL_CM_WARNING(ssl);
+ return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl));
+ }
+#endif /* WOLFSSL_LOCAL_X509_STORE */
+#endif /* WOLFSSL_TRUST_PEER_CERT */
+/* old NO_FILESYSTEM end */
+#endif /* !NO_CERTS */
- #if !defined(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 !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;
+#ifdef OPENSSL_EXTRA
- 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;
+ 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;
+ }
- 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;
+ int wolfSSL_OpenSSL_add_all_algorithms_noconf(void)
+ {
+ WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_noconf");
-#ifdef WOLFSSL_DTLS13
- case WAIT_FINISHED_ACK:
- ssl->options.connectState = FINISHED_DONE;
- FALL_THROUGH;
-#endif /* WOLFSSL_DTLS13 */
+ if (wolfSSL_add_all_algorithms() ==
+ WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR))
+ {
+ return WOLFSSL_FATAL_ERROR;
+ }
- case FINISHED_DONE :
- /* get response */
- while (ssl->options.serverState < SERVER_FINISHED_COMPLETE)
- if ( (ssl->error = ProcessReply(ssl)) < 0) {
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
+ return WOLFSSL_SUCCESS;
+ }
- ssl->options.connectState = SECOND_REPLY_DONE;
- WOLFSSL_MSG("connect state: SECOND_REPLY_DONE");
- FALL_THROUGH;
+ 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. */
- 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 */
+ if (wolfSSL_add_all_algorithms() ==
+ WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR))
+ {
+ return WOLFSSL_FATAL_ERROR;
+ }
+ return WOLFSSL_SUCCESS;
+ }
- if (!ssl->options.dtls) {
- if (!ssl->options.keepResources) {
- FreeHandshakeResources(ssl);
- }
- }
- #ifdef WOLFSSL_DTLS
- else {
- ssl->options.dtlsHsRetain = 1;
- }
- #endif /* WOLFSSL_DTLS */
+#endif
- #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(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;
+ }
- ssl->error = 0; /* clear the error */
- WOLFSSL_LEAVE("wolfSSL_connect", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
- #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */
+ 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 */
- default:
- WOLFSSL_MSG("Unknown connect state ERROR");
- return WOLFSSL_FATAL_ERROR; /* unknown connect state */
+#ifdef OPENSSL_EXTRA
+#ifndef NO_BIO
+ static void ssl_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr, int flags)
+ {
+ WOLFSSL_ENTER("wolfSSL_set_bio");
+
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument, ssl was NULL");
+ return;
}
- #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS || !WOLFSSL_TLS13 */
- }
-#endif /* NO_WOLFSSL_CLIENT */
+ /* free any existing WOLFSSL_BIOs in use but don't free those in
+ * a chain */
+ if ((flags & WOLFSSL_BIO_FLAG_READ) && (ssl->biord != NULL)) {
+ if ((flags & WOLFSSL_BIO_FLAG_WRITE) && (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;
+ }
+ else if ((flags & WOLFSSL_BIO_FLAG_WRITE) && (ssl->biowr != NULL)) {
+ if (ssl->biowr->prev != NULL)
+ wolfSSL_BIO_free(ssl->biowr);
+ ssl->biowr = 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;
+ if (flags & WOLFSSL_BIO_FLAG_READ)
+ ssl->biord = rd;
+ if (flags & WOLFSSL_BIO_FLAG_WRITE)
+ ssl->biowr = wr;
-/* server only parts */
-#ifndef NO_WOLFSSL_SERVER
+ /* set SSL to use BIO callbacks instead */
+ if ((flags & WOLFSSL_BIO_FLAG_READ) &&
+ (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0)))
+ {
+ ssl->CBIORecv = SslBioReceive;
+ }
+ if ((flags & WOLFSSL_BIO_FLAG_WRITE) &&
+ (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0)))
+ {
+ ssl->CBIOSend = SslBioSend;
+ }
- #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS)
- WOLFSSL_METHOD* wolfSSLv2_server_method(void)
+ /* User programs should always retry reading from these BIOs */
+ if (rd) {
+ /* User writes to rd */
+ wolfSSL_BIO_set_retry_write(rd);
+ }
+ if (wr) {
+ /* User reads from wr */
+ wolfSSL_BIO_set_retry_read(wr);
+ }
+ }
+
+ void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr)
{
- WOLFSSL_STUB("wolfSSLv2_server_method");
- return 0;
+ ssl_set_bio(ssl, rd, wr, WOLFSSL_BIO_FLAG_READ | WOLFSSL_BIO_FLAG_WRITE);
}
- #endif
- #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS)
- WOLFSSL_METHOD* wolfSSLv3_server_method(void)
+ void wolfSSL_set_rbio(WOLFSSL* ssl, WOLFSSL_BIO* rd)
{
- return wolfSSLv3_server_method_ex(NULL);
+ ssl_set_bio(ssl, rd, NULL, WOLFSSL_BIO_FLAG_READ);
}
- WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap)
+
+ void wolfSSL_set_wbio(WOLFSSL* ssl, WOLFSSL_BIO* wr)
{
- 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;
+ ssl_set_bio(ssl, NULL, wr, WOLFSSL_BIO_FLAG_WRITE);
+ }
+
+#endif /* !NO_BIO */
+#endif /* OPENSSL_EXTRA */
+
+#ifndef WOLFSSL_NO_CA_NAMES
+ 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;
}
- return method;
}
- #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */
- WOLFSSL_METHOD* wolfSSLv23_server_method(void)
+ void wolfSSL_set_client_CA_list(WOLFSSL* ssl,
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
{
- return wolfSSLv23_server_method_ex(NULL);
+ 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;
+ }
}
- WOLFSSL_METHOD* wolfSSLv23_server_method_ex(void* heap)
+ void wolfSSL_CTX_set0_CA_list(WOLFSSL_CTX* ctx,
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
{
- 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;
+ WOLFSSL_ENTER("wolfSSL_CTX_set0_CA_list");
+ if (ctx != NULL) {
+ wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL);
+ ctx->ca_names = names;
}
- return method;
}
+ void wolfSSL_set0_CA_list(WOLFSSL* ssl,
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
+ {
+ WOLFSSL_ENTER("wolfSSL_set0_CA_list");
+ if (ssl != NULL) {
+ if (ssl->ca_names != ssl->ctx->ca_names)
+ wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL);
+ ssl->ca_names = names;
+ }
+ }
+#endif /* WOLFSSL_NO_CA_NAMES */
- WOLFSSL_ABI
- int wolfSSL_accept(WOLFSSL* ssl)
+#ifdef WOLFSSL_CERT_SETUP_CB
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ /* 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)
{
-#if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13))
- word16 havePSK = 0;
- word16 haveAnon = 0;
- word16 haveMcast = 0;
+ WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb");
+
+ if (ctx != NULL) {
+ ctx->CBClientCert = cb;
+ }
+ }
#endif
- int ret = 0;
- (void)ret;
+ 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 (ssl == NULL)
- return WOLFSSL_FATAL_ERROR;
+ ctx->certSetupCb = cb;
+ ctx->certSetupCbArg = arg;
+ }
- #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;
+ int wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl,
+ const byte** suites, word16* suiteSz,
+ const byte** hashSigAlgo, word16* hashSigAlgoSz)
+ {
+ WOLFSSL_ENTER("wolfSSL_get_client_suites_sigalgs");
+
+ if (suites != NULL)
+ *suites = NULL;
+ if (suiteSz != NULL)
+ *suiteSz = 0;
+ if (hashSigAlgo != NULL)
+ *hashSigAlgo = NULL;
+ if (hashSigAlgoSz != NULL)
+ *hashSigAlgoSz = 0;
+
+ if (ssl != NULL && ssl->clSuites != NULL) {
+ if (suites != NULL && suiteSz != NULL) {
+ *suites = ssl->clSuites->suites;
+ *suiteSz = ssl->clSuites->suiteSz;
}
- ssl->error = 0; /* expected to be zero here */
+ if (hashSigAlgo != NULL && hashSigAlgoSz != NULL) {
+ *hashSigAlgo = ssl->clSuites->hashSigAlgo;
+ *hashSigAlgoSz = ssl->clSuites->hashSigAlgoSz;
+ }
+ return WOLFSSL_SUCCESS;
}
- #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
+ return WOLFSSL_FAILURE;
+ }
-#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");
+#ifndef NO_TLS
+ 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;
+ }
+#endif
- /* 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;
+ /**
+ * @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;
+
+ if (hashAlgo == NULL || sigAlgo == NULL)
+ return BAD_FUNC_ARG;
+
+ input[0] = first;
+ input[1] = second;
+ DecodeSigAlg(input, &hashType, &sigType);
+
+ /* 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 = ML_DSA_LEVEL2k;
+ break;
+ case dilithium_level3_sa_algo:
+ *sigAlgo = ML_DSA_LEVEL3k;
+ break;
+ case dilithium_level5_sa_algo:
+ *sigAlgo = ML_DSA_LEVEL5k;
+ break;
+ case sm2_sa_algo:
+ *sigAlgo = SM2k;
+ break;
+ case invalid_sa_algo:
+ case any_sa_algo:
+ default:
+ *hashAlgo = WC_HASH_TYPE_NONE;
+ *sigAlgo = 0;
+ 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)
+ /* 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
- ))
- {
- 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;
+ 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;
}
}
-#endif /* WOLFSSL_WOLFSENTRY_HOOKS */
+ return ret;
+ }
+#endif /* WOLFSSL_CERT_SETUP_CB */
- #ifdef HAVE_ERRNO_H
- errno = 0;
- #endif
+#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");
- #ifndef NO_PSK
- havePSK = ssl->options.havePSK;
- #endif
- (void)havePSK;
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Bad argument passed to "
+ "wolfSSL_CTX_get_client_CA_list");
+ return NULL;
+ }
- #ifdef HAVE_ANON
- haveAnon = ssl->options.useAnon;
- #endif
- (void)haveAnon;
+ return ctx->client_ca_names;
+ }
- #ifdef WOLFSSL_MULTICAST
- haveMcast = ssl->options.haveMcast;
- #endif
- (void)haveMcast;
+ /* On server side: returns the CAs set via *_set_client_CA_list();
+ * On client side: returns the CAs received from server -- same as
+ * wolfSSL_get0_peer_CA_list() */
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(
+ const WOLFSSL* ssl)
+ {
+ WOLFSSL_ENTER("wolfSSL_get_client_CA_list");
- if (ssl->options.side != WOLFSSL_SERVER_END) {
- ssl->error = SIDE_ERROR;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list");
+ return NULL;
}
- #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) {
+ if (ssl->options.side == WOLFSSL_CLIENT_END)
+ return ssl->peer_ca_names;
+ else
+ return SSL_CLIENT_CA_NAMES(ssl);
+ }
- WOLFSSL_MSG("accept error: server cert required");
- ssl->error = NO_PRIVATE_KEY;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get0_CA_list(
+ const WOLFSSL_CTX *ctx)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_get0_CA_list");
- 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;
- }
- }
- }
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get0_CA_list");
+ return NULL;
}
- #endif
- #ifdef WOLFSSL_DTLS
- if (ssl->version.major == DTLS_MAJOR) {
- ssl->options.dtls = 1;
- ssl->options.tls = 1;
- ssl->options.tls1_1 = 1;
- if (!IsDtlsNotSctpMode(ssl) || !IsDtlsNotSrtpMode(ssl) ||
- IsSCR(ssl))
- ssl->options.dtlsStateful = 1;
+ return ctx->ca_names;
+ }
+
+ /* Always returns the CA's set via *_set0_CA_list */
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_CA_list(const WOLFSSL *ssl)
+ {
+ WOLFSSL_ENTER("wolfSSL_get0_CA_list");
+
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_CA_list");
+ return NULL;
}
- #endif
- if (ssl->buffers.outputBuffer.length > 0
- #ifdef WOLFSSL_ASYNC_CRYPT
- /* do not send buffered or advance state if last error was an
- async pending operation */
- && ssl->error != WC_PENDING_E
- #endif
- ) {
- ret = SendBuffered(ssl);
- if (ret == 0) {
- /* fragOffset is non-zero when sending fragments. On the last
- * fragment, fragOffset is zero again, and the state can be
- * advanced. */
- if (ssl->fragOffset == 0 && !ssl->options.buildingMsg) {
- if (ssl->options.acceptState == ACCEPT_FIRST_REPLY_DONE ||
- ssl->options.acceptState == SERVER_HELLO_SENT ||
- ssl->options.acceptState == CERT_SENT ||
- ssl->options.acceptState == CERT_STATUS_SENT ||
- ssl->options.acceptState == KEY_EXCHANGE_SENT ||
- ssl->options.acceptState == CERT_REQ_SENT ||
- ssl->options.acceptState == ACCEPT_SECOND_REPLY_DONE ||
- ssl->options.acceptState == TICKET_SENT ||
- ssl->options.acceptState == CHANGE_CIPHER_SENT) {
- ssl->options.acceptState++;
- WOLFSSL_MSG("accept state: "
- "Advanced from last buffered fragment send");
- #ifdef WOLFSSL_ASYNC_IO
- /* Cleanup async */
- FreeAsyncCtx(ssl, 0);
- #endif
- }
- }
- else {
- WOLFSSL_MSG("accept state: "
- "Not advanced, more fragments to send");
- }
- }
- else {
- ssl->error = ret;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
-#ifdef WOLFSSL_DTLS13
- if (ssl->options.dtls)
- ssl->dtls13SendingAckOrRtx = 0;
-#endif /* WOLFSSL_DTLS13 */
+ return SSL_CA_NAMES(ssl);
+ }
+
+ /* Always returns the CA's received from the peer */
+ WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_peer_CA_list(
+ const WOLFSSL* ssl)
+ {
+ WOLFSSL_ENTER("wolfSSL_get0_peer_CA_list");
+
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_peer_CA_list");
+ return NULL;
}
- ret = RetrySendAlert(ssl);
- if (ret != 0) {
- ssl->error = ret;
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
+ return ssl->peer_ca_names;
+ }
+
+ #if !defined(NO_CERTS)
+ static int add_to_CA_list(WOLFSSL_STACK* ca_names, WOLFSSL_X509* x509)
+ {
+ WOLFSSL_X509_NAME *nameCopy = NULL;
+
+ nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509));
+ if (nameCopy == NULL) {
+ WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
+ return WOLFSSL_FAILURE;
}
- switch (ssl->options.acceptState) {
+ if (wolfSSL_sk_X509_NAME_push(ca_names, nameCopy) <= 0) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
+ wolfSSL_X509_NAME_free(nameCopy);
+ return WOLFSSL_FAILURE;
+ }
- 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 WOLFSSL_SUCCESS;
+ }
- case ACCEPT_CLIENT_HELLO_DONE :
- if (ssl->options.tls1_3) {
- return wolfSSL_accept_TLSv13(ssl);
+ int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
+ if (ctx == NULL || x509 == NULL) {
+ WOLFSSL_MSG("Bad argument");
+ return WOLFSSL_FAILURE;
+ }
+ if (ctx->client_ca_names == NULL) {
+ ctx->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+ if (ctx->client_ca_names == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ return WOLFSSL_FAILURE;
}
-#endif
+ }
+ return add_to_CA_list(ctx->client_ca_names, x509);
+ }
- ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
- WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
- FALL_THROUGH;
+ int wolfSSL_add_client_CA(WOLFSSL* ssl, WOLFSSL_X509* x509)
+ {
+ WOLFSSL_ENTER("wolfSSL_add_client_CA");
+ if (ssl == NULL || x509 == NULL) {
+ WOLFSSL_MSG("Bad argument");
+ return WOLFSSL_FAILURE;
+ }
+ if (ssl->client_ca_names == NULL) {
+ ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+ if (ssl->client_ca_names == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ return WOLFSSL_FAILURE;
+ }
+ }
+ return add_to_CA_list(ssl->client_ca_names, x509);
+ }
- 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;
+ int wolfSSL_CTX_add1_to_CA_list(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_add1_to_CA_list");
+ if (ctx == NULL || x509 == NULL) {
+ WOLFSSL_MSG("Bad argument");
+ return WOLFSSL_FAILURE;
+ }
+ if (ctx->ca_names == NULL) {
+ ctx->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+ if (ctx->ca_names == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ return WOLFSSL_FAILURE;
}
- ssl->options.acceptState = SERVER_HELLO_SENT;
- WOLFSSL_MSG("accept state SERVER_HELLO_SENT");
- FALL_THROUGH;
+ }
+ return add_to_CA_list(ctx->ca_names, x509);
+ }
- case SERVER_HELLO_SENT :
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3) {
- return wolfSSL_accept_TLSv13(ssl);
+ int wolfSSL_add1_to_CA_list(WOLFSSL* ssl, WOLFSSL_X509* x509)
+ {
+ WOLFSSL_ENTER("wolfSSL_add1_to_CA_list");
+ if (ssl == NULL || x509 == NULL) {
+ WOLFSSL_MSG("Bad argument");
+ return WOLFSSL_FAILURE;
+ }
+ if (ssl->ca_names == NULL) {
+ ssl->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
+ if (ssl->ca_names == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ return WOLFSSL_FAILURE;
}
- #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;
+ }
+ return add_to_CA_list(ssl->ca_names, x509);
+ }
+ #endif /* !NO_CERTS */
- 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;
+ #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 = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
- case CERT_STATUS_SENT :
- #ifdef WOLFSSL_TLS13
- if (ssl->options.tls1_3) {
- return wolfSSL_accept_TLSv13(ssl);
+ 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;
}
- #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;
+ list = wolfSSL_sk_X509_NAME_new(NULL);
+ if (list == NULL) {
+ WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
+ goto cleanup;
+ }
- 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;
-
- 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;
-
- case ACCEPT_SECOND_REPLY_DONE :
- #ifndef NO_CERTS
- /* SERVER: When not resuming and verifying peer but no certificate
- * received and not failing when not received then peer auth good.
- */
- if (!ssl->options.resuming && ssl->options.verifyPeer &&
- !ssl->options.havePeerCert && !ssl->options.failNoCert) {
- ssl->options.peerAuthGood = 1;
- }
- #endif /* !NO_CERTS */
- #ifdef WOLFSSL_NO_CLIENT_AUTH
- if (!ssl->options.resuming) {
- ssl->options.peerAuthGood = 1;
- }
- #endif
-
-#ifdef HAVE_SESSION_TICKET
- if (ssl->options.createTicket && !ssl->options.noTicketTls12) {
- if ( (ssl->error = SendTicket(ssl)) != 0) {
- #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
- ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
- #endif
- WOLFSSL_MSG("Thought we need ticket but failed");
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- }
-#endif /* HAVE_SESSION_TICKET */
- ssl->options.acceptState = TICKET_SENT;
- WOLFSSL_MSG("accept state TICKET_SENT");
- FALL_THROUGH;
-
- case TICKET_SENT:
- /* SERVER: Fail-safe for CLient Authentication. */
- if (!ssl->options.peerAuthGood) {
- WOLFSSL_MSG("Client authentication did not happen");
- return WOLFSSL_FATAL_ERROR;
- }
-
- if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
- #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
- ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
- #endif
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
- ssl->options.acceptState = CHANGE_CIPHER_SENT;
- WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT");
- FALL_THROUGH;
-
- case CHANGE_CIPHER_SENT :
- if ( (ssl->error = SendFinished(ssl)) != 0) {
- #ifdef WOLFSSL_CHECK_ALERT_ON_ERR
- ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
- #endif
- WOLFSSL_ERROR(ssl->error);
- return WOLFSSL_FATAL_ERROR;
- }
-
- ssl->options.acceptState = ACCEPT_FINISHED_DONE;
- WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE");
- FALL_THROUGH;
-
- 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;
- }
+ /* 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;
}
- }
- ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
- WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
- FALL_THROUGH;
+ /*
+ * Original cert will be freed so make sure not to try to access
+ * it in the future.
+ */
+ nameCopy->x509 = NULL;
- 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;
+ if (wolfSSL_sk_X509_NAME_push(list, nameCopy) <= 0) {
+ 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;
- }
-#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
+ CLEAR_ASN_NO_PEM_HEADER_ERROR(err);
-#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;
- }
+ err = WOLFSSL_SUCCESS;
+cleanup:
+ wolfSSL_X509_free(cert);
+ cert = NULL;
+ wolfSSL_BIO_free(bio);
+ if (err != WOLFSSL_SUCCESS) {
+ /* We failed so return NULL */
+ wolfSSL_sk_X509_NAME_pop_free(list, NULL);
+ list = NULL;
}
-#endif
- ssl->error = 0; /* clear the error */
-
- WOLFSSL_LEAVE("wolfSSL_accept", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
-
- default :
- WOLFSSL_MSG("Unknown accept state ERROR");
- return WOLFSSL_FATAL_ERROR;
+ return list;
+ #else
+ (void)fname;
+ return NULL;
+ #endif
}
-#endif /* !WOLFSSL_NO_TLS12 */
- }
-
-#endif /* NO_WOLFSSL_SERVER */
+ #endif
+ #endif /* !NO_BIO */
+#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
-#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
-int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx)
-{
- WOLFSSL_ENTER("wolfDTLS_SetChGoodCb");
+#ifdef OPENSSL_EXTRA
- if (ssl == NULL)
- return BAD_FUNC_ARG;
+ #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
+ };
- ssl->chGoodCb = cb;
- ssl->chGoodCtx = user_ctx;
+ int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username)
+ {
+ int r = 0;
+ SrpSide srp_side = SRP_CLIENT_SIDE;
- return WOLFSSL_SUCCESS;
-}
-#endif
+ WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username");
+ if (ctx == NULL || ctx->srp == NULL || username==NULL)
+ return WOLFSSL_FAILURE;
-#ifndef NO_HANDSHAKE_DONE_CB
+ 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;
+ }
-int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx)
-{
- WOLFSSL_ENTER("wolfSSL_SetHsDoneCb");
+ if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0) {
+ WOLFSSL_MSG("Init SRP CTX failed");
+ XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
+ ctx->srp = NULL;
+ return WOLFSSL_FAILURE;
+ }
+ r = wc_SrpSetUsername(ctx->srp, (const byte*)username,
+ (word32)XSTRLEN(username));
+ if (r < 0) {
+ WOLFSSL_MSG("fail to set srp username.");
+ return WOLFSSL_FAILURE;
+ }
- if (ssl == NULL)
- return BAD_FUNC_ARG;
+ /* if wolfSSL_CTX_set_srp_password has already been called, */
+ /* use saved password here */
+ if (ctx->srp_password != NULL) {
+ if (ctx->srp->user == NULL)
+ return WOLFSSL_FAILURE;
+ return wolfSSL_CTX_set_srp_password(ctx, (char*)ctx->srp_password);
+ }
- ssl->hsDoneCb = cb;
- ssl->hsDoneCtx = user_ctx;
+ return WOLFSSL_SUCCESS;
+ }
- return WOLFSSL_SUCCESS;
-}
+ int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password)
+ {
+ int r;
+ byte salt[SRP_SALT_SIZE];
-#endif /* NO_HANDSHAKE_DONE_CB */
+ WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password");
+ if (ctx == NULL || ctx->srp == NULL || password == NULL)
+ return WOLFSSL_FAILURE;
-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->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");
+ return WOLFSSL_FAILURE;
+ }
+ r = wc_SrpSetPassword(ctx->srp, (const byte*)password,
+ (word32)XSTRLEN(password));
+ if (r < 0) {
+ WOLFSSL_MSG("wc_SrpSetPassword failed.");
+ return WOLFSSL_FAILURE;
+ }
+ XFREE(ctx->srp_password, NULL, DYNAMIC_TYPE_SRP);
+ ctx->srp_password = NULL;
+ } else {
+ /* save password for wolfSSL_set_srp_username */
+ XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
- WOLFSSL_ENTER("wolfSSL_Cleanup");
+ 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;
+ }
-#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;
+ /**
+ * 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;
}
-#ifndef WOLFSSL_MUTEX_INITIALIZER
+ return WOLFSSL_SUCCESS;
}
-#endif
- if (initRefCount > 0) {
- --initRefCount;
- if (initRefCount == 0)
- release = 1;
+ char* wolfSSL_get_srp_username(WOLFSSL *ssl)
+ {
+ if (ssl && ssl->ctx && ssl->ctx->srp) {
+ return (char*) ssl->ctx->srp->user;
+ }
+ return NULL;
}
+ #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */
-#ifndef WOLFSSL_MUTEX_INITIALIZER
- if (inits_count_mutex_valid == 1) {
-#endif
- wc_UnLockMutex(&inits_count_mutex);
-#ifndef WOLFSSL_MUTEX_INITIALIZER
+ /* keyblock size in bytes or -1 */
+ int wolfSSL_get_keyblock_size(WOLFSSL* ssl)
+ {
+ if (ssl == NULL)
+ return WOLFSSL_FATAL_ERROR;
+
+ return 2 * (ssl->specs.key_size + ssl->specs.iv_size +
+ ssl->specs.hash_size);
}
-#endif
- if (!release)
- return ret;
+#endif /* OPENSSL_EXTRA */
-#ifdef OPENSSL_EXTRA
- wolfSSL_BN_free_one();
-#endif
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || \
+ defined(WOLFSSL_WPAS_SMALL)
-#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;
+ /* 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;
+
+ *ms = ssl->arrays->masterSecret;
+ *sr = ssl->arrays->serverRandom;
+ *cr = ssl->arrays->clientRandom;
+
+ *msLen = SECRET_LEN;
+ *srLen = RAN_LEN;
+ *crLen = RAN_LEN;
+
+ return WOLFSSL_SUCCESS;
}
- session_lock_valid = 0;
+
+ void wolfSSL_set_accept_state(WOLFSSL* ssl)
+ {
+ WOLFSSL_ENTER("wolfSSL_set_accept_state");
+
+ if (ssl == NULL)
+ return;
+
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ #ifdef HAVE_ECC
+ WC_DECLARE_VAR(key, ecc_key, 1, 0);
+ 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;
+ }
+ wc_ecc_free(key);
+ }
+ }
+ WC_FREE_VAR_EX(key, ssl->heap, DYNAMIC_TYPE_ECC);
#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;
+
+ #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;
}
- #else
- EvictSessionFromCache(&SessionCache[i].Sessions[j]);
#endif
}
+
+ if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error initializing server side");
+ }
}
- #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;
+#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+ /* return true if connection established */
+ /* this works for TLS and DTLS */
+ int wolfSSL_is_init_finished(const WOLFSSL* ssl)
+ {
+ if (ssl == NULL)
+ return 0;
+
+#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_NO_CLIENT)
+ if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls
+ && IsAtLeastTLSv1_3(ssl->version)) {
+ return ssl->options.serverState == SERVER_FINISHED_ACKED;
+ }
+#endif /* WOLFSSL_DTLS13 && !WOLFSSL_NO_CLIENT */
+
+ /* Can't use ssl->options.connectState and ssl->options.acceptState
+ * because they differ in meaning for TLS <=1.2 and 1.3 */
+ if (ssl->options.handShakeState == HANDSHAKE_DONE)
+ return 1;
+
+ return 0;
}
- inits_count_mutex_valid = 0;
-#endif
#ifdef OPENSSL_EXTRA
- wolfSSL_RAND_Cleanup();
-#endif
-
- if (wolfCrypt_Cleanup() != 0) {
- WOLFSSL_MSG("Error with wolfCrypt_Cleanup call");
- if (ret == WOLFSSL_SUCCESS)
- ret = WC_CLEANUP_E;
+ 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 FIPS_VERSION_GE(5,1)
- if (wolfCrypt_SetPrivateKeyReadEnable_fips(0, WC_KEYTYPE_ALL) < 0) {
- if (ret == WOLFSSL_SUCCESS)
- ret = WC_CLEANUP_E;
+
+ 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;
}
#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;
+ 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 (long)ctx->mask;
}
- 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;
-}
+ /* forward declaration */
+ static long wolf_set_options(long old_op, long op);
-void SetupSession(WOLFSSL* ssl)
-{
- WOLFSSL_SESSION* session = ssl->session;
+ long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_set_options");
- WOLFSSL_ENTER("SetupSession");
+ if (ctx == NULL)
+ return BAD_FUNC_ARG;
- 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;
+ ctx->mask = (unsigned long)wolf_set_options((long)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 (long)ctx->mask;
}
- 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;
+
+ 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 &= (unsigned long)~opt;
+ return (long)ctx->mask;
}
-#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
+#ifdef OPENSSL_EXTRA
-WOLFSSL_ABI
-void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm)
-{
- /* static table now, no flushing needed */
- (void)ctx;
- (void)tm;
-}
+ int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd)
+ {
+ WOLFSSL_ENTER("wolfSSL_set_rfd");
+ ssl->rfd = rfd; /* not used directly to allow IO callbacks */
-void wolfSSL_CTX_flush_sessions(WOLFSSL_CTX* ctx, long tm)
-{
- int i, j;
- byte id[ID_LEN];
+ ssl->IOCB_ReadCtx = &ssl->rfd;
- (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
- }
+ #ifdef WOLFSSL_DTLS
+ if (ssl->options.dtls) {
+ ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
+ ssl->buffers.dtlsCtx.rfd = rfd;
}
- SESSION_ROW_UNLOCK(&SessionCache[i]);
- }
-}
+ #endif
+ return WOLFSSL_SUCCESS;
+ }
-/* 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;
+ int wolfSSL_set_wfd(WOLFSSL* ssl, int wfd)
+ {
+ WOLFSSL_ENTER("wolfSSL_set_wfd");
+ ssl->wfd = wfd; /* not used directly to allow IO callbacks */
- return WOLFSSL_SUCCESS;
-}
+ ssl->IOCB_WriteCtx = &ssl->wfd;
+ return WOLFSSL_SUCCESS;
+ }
+#endif /* OPENSSL_EXTRA */
-/**
- * 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(NO_CERTS) && (defined(OPENSSL_EXTRA) || \
+ defined(WOLFSSL_WPAS_SMALL))
- int ret = WOLFSSL_SUCCESS;
- (void)ret;
+ WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(const WOLFSSL_CTX* ctx)
+ {
+ if (ctx == NULL) {
+ return NULL;
+ }
- if (ctx == NULL)
- ret = BAD_FUNC_ARG;
+ if (ctx->x509_store_pt != NULL)
+ return ctx->x509_store_pt;
+ return &((WOLFSSL_CTX*)ctx)->x509_store;
+ }
- 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;
+ void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
+ {
+ WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store");
+ if (ctx == NULL || str == NULL || ctx->cm == str->cm) {
+ return;
}
- }
-#if 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);
+
+ if (wolfSSL_CertManager_up_ref(str->cm) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_CertManager_up_ref error");
+ return;
}
- else {
- ret = wolfSSL_CTX_set_TicketHint(ctx, to);
+ /* free cert manager if have one */
+ if (ctx->cm != NULL) {
+ wolfSSL_CertManagerFree(ctx->cm);
}
- }
-#endif /* OPENSSL_EXTRA && HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER */
+ ctx->cm = str->cm;
+ ctx->x509_store.cm = str->cm;
-#if defined(WOLFSSL_ERROR_CODE_OPENSSL)
- if (ret == WOLFSSL_SUCCESS) {
- return prev_timeout;
- }
- else {
- return ret;
+ /* 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*/
}
-#else
- return ret;
-#endif /* WOLFSSL_ERROR_CODE_OPENSSL */
-}
+#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");
-#ifndef NO_CLIENT_CACHE
+ if (ctx == NULL || str == NULL) {
+ WOLFSSL_MSG("Bad parameter");
+ return WOLFSSL_FAILURE;
+ }
-/* 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;
+ /* NO-OP when setting existing store */
+ if (str == CTX_STORE(ctx))
+ return WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_GetSessionClient");
+ if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
+ return WOLFSSL_FAILURE;
+ }
- if (ssl->ctx->sessionCacheOff) {
- WOLFSSL_MSG("Session Cache off");
- return NULL;
+ /* 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 (ssl->options.side == WOLFSSL_SERVER_END)
- return NULL;
-
- len = min(SERVER_ID_LEN, (word32)len);
+ int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
+ {
+ WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store");
- /* Do not access ssl->ctx->get_sess_cb from here. It is using a different
- * set of ID's */
+ if (ssl == NULL || str == NULL) {
+ WOLFSSL_MSG("Bad parameter");
+ return WOLFSSL_FAILURE;
+ }
- row = HashObject(id, len, &error) % CLIENT_SESSION_ROWS;
- if (error != 0) {
- WOLFSSL_MSG("Hash session failed");
- return NULL;
- }
+ /* NO-OP when setting existing store */
+ if (str == SSL_STORE(ssl))
+ return WOLFSSL_SUCCESS;
- if (wc_LockMutex(&clisession_mutex) != 0) {
- WOLFSSL_MSG("Client cache mutex lock failed");
- return NULL;
+ /* 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;
}
- /* 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 */
- }
- clSess = ClientCache[row].Clients;
- for (; count > 0; --count) {
- WOLFSSL_SESSION* current;
- SessionRow* sessRow;
+ int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
+ {
+ WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store");
- if (clSess[idx].serverRow >= SESSION_ROWS) {
- WOLFSSL_MSG("Client cache serverRow invalid");
- break;
+ if (ssl == NULL || str == NULL) {
+ WOLFSSL_MSG("Bad parameter");
+ return WOLFSSL_FAILURE;
}
- /* lock row */
- sessRow = &SessionCache[clSess[idx].serverRow];
- if (SESSION_ROW_RD_LOCK(sessRow) != 0) {
- WOLFSSL_MSG("Session cache row lock failure");
- break;
- }
+ /* NO-OP when setting existing store */
+ if (str == SSL_STORE(ssl))
+ return WOLFSSL_SUCCESS;
-#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");
+ if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
+ return WOLFSSL_FAILURE;
}
- SESSION_ROW_UNLOCK(sessRow);
- idx = idx > 0 ? idx - 1 : CLIENT_SESSIONS_PER_ROW - 1;
+ /* 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) */
- wc_UnLockMutex(&clisession_mutex);
+#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;
+ }
-#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
- ;
-}
+ 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;
+ }
-#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;
+ wc_pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx)
+ {
+ if (ctx == NULL || ctx->passwd_cb == NULL) {
+ return NULL;
+ }
- *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 ctx->passwd_cb;
}
- *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;
+ void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx)
+ {
+ if (ctx == NULL) {
+ return NULL;
}
- 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;
-}
+ return ctx->passwd_userdata;
+ }
-int TlsSessionCacheGetAndRdLock(const byte *id, const WOLFSSL_SESSION **sess,
- word32 *lockedRow, byte side)
-{
- return TlsSessionCacheGetAndLock(id, sess, lockedRow, 1, side);
-}
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
-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];
+#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 (unsigned long)wc_GetErrorNodeErr();
#else
- byte* tmpTicket = NULL;
-#endif
-#ifdef WOLFSSL_TLS13
- byte *preallocNonce = NULL;
- byte preallocNonceLen = 0;
- byte preallocNonceUsed = 0;
-#endif /* WOLFSSL_TLS13 */
- byte tmpBufSet = 0;
+ return (unsigned long)(0 - NOT_COMPILED_IN);
#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 defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if (output == NULL) {
- WOLFSSL_MSG("NULL output");
- return WOLFSSL_FAILURE;
+ int wolfSSL_num_locks(void)
+ {
+ return 0;
}
- 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;
+ void wolfSSL_set_locking_callback(mutex_cb* f)
+ {
+ WOLFSSL_ENTER("wolfSSL_set_locking_callback");
- 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 (wc_SetMutexCb(f) != 0) {
+ WOLFSSL_MSG("Error when setting mutex call back");
}
- /* 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
+ mutex_cb* wolfSSL_get_locking_callback(void)
+ {
+ WOLFSSL_ENTER("wolfSSL_get_locking_callback");
-#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;
+ return wc_GetMutexCb();
}
-#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*/
+ typedef unsigned long (idCb)(void);
+ static idCb* inner_idCb = NULL;
- /* 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;
+ unsigned long wolfSSL_thread_id(void)
+ {
+ if (inner_idCb != NULL) {
+ return inner_idCb();
}
-#endif /* WOLFSSL_TLS13 */
-#ifdef WOLFSSL_SMALL_STACK
- if (tmpTicket != NULL) {
- XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER);
- tmpTicket = NULL;
+ else {
+ return 0;
}
-#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;
+
+ void wolfSSL_set_id_callback(unsigned long (*f)(void))
+ {
+ inner_idCb = f;
}
-#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_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];
+
+ WOLFSSL_ENTER("wolfSSL_ERR_print_errors");
+
+ if (bio == NULL) {
+ WOLFSSL_MSG("BIO passed in was null");
+ return;
}
- }
-#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 */
+
+ do {
+ ret = wc_PeekErrorNode(0, &file, &reason, &line);
+ if (ret >= 0) {
+ const char* r = wolfSSL_ERR_reason_error_string(
+ (unsigned long)(0 - ret));
+ if (XSNPRINTF(buf, sizeof(buf),
+ "error:%d:wolfSSL library:%s:%s:%d\n",
+ ret, r, file, line)
+ >= (int)sizeof(buf))
+ {
+ WOLFSSL_MSG("Buffer overrun formatting error message");
}
+ wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf));
+ wc_RemoveErrorNode(0);
}
- else {
- output->ticketNonce.data = preallocNonce;
- output->ticketNonce.len = preallocNonceLen;
- preallocNonce = NULL;
+ } while (ret >= 0);
+ if (wolfSSL_BIO_write(bio, "", 1) != 1) {
+ WOLFSSL_MSG("Issue writing final string terminator");
}
}
- if (preallocNonce != NULL)
- XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK);
-#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/
+#endif /* !NO_BIO */
+#endif /* WOLFSSL_HAVE_ERROR_QUEUE */
-#endif
+#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
-#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- if (peer != NULL) {
- wolfSSL_X509_free(peer);
- }
-#endif
+#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 error;
-}
+ /* return max size of buffer */
+ if (outSz == 0) {
+ return RAN_LEN;
+ }
-WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret,
- byte restoreSessionCerts)
-{
- WOLFSSL_SESSION* ret = NULL;
+ if (ssl == NULL || out == NULL) {
+ return 0;
+ }
- (void)restoreSessionCerts; /* Kept for compatibility */
+ if (ssl->arrays == NULL) {
+ WOLFSSL_MSG("Arrays struct not saved after handshake");
+ return 0;
+ }
- if (wolfSSL_GetSessionFromCache(ssl, ssl->session) == WOLFSSL_SUCCESS) {
- ret = ssl->session;
+ if (outSz > RAN_LEN) {
+ size = RAN_LEN;
}
else {
- WOLFSSL_MSG("wolfSSL_GetSessionFromCache did not return a session");
+ size = outSz;
}
- if (ret != NULL && masterSecret != NULL)
- XMEMCPY(masterSecret, ret->masterSecret, SECRET_LEN);
-
- return ret;
+ XMEMCPY(out, ssl->arrays->serverRandom, size);
+ return size;
}
+#endif /* !NO_WOLFSSL_SERVER */
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */
-int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
+#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)
{
- SessionRow* sessRow = NULL;
- int ret = WOLFSSL_SUCCESS;
+ WOLFSSL_EVP_PKEY* ret = NULL;
- session = ClientSessionToSession(session);
+ WOLFSSL_ENTER("wolfSSL_get_server_tmp_key");
- if (ssl == NULL || session == NULL || !session->isSetup) {
- WOLFSSL_MSG("ssl or session NULL or not set up");
+ if (ssl == NULL || pkey == NULL) {
+ WOLFSSL_MSG("Bad argument passed in");
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;
- }
+#ifdef HAVE_ECC
+ if (ssl->peerEccKey != NULL) {
+ unsigned char* der;
+ const unsigned char* pt;
+ unsigned int derSz = 0;
+ int sz;
- if (ret == WOLFSSL_SUCCESS) {
- if (ssl->session == session) {
- WOLFSSL_MSG("ssl->session and session same");
+ PRIVATE_KEY_UNLOCK();
+ if (wc_ecc_export_x963(ssl->peerEccKey, NULL, &derSz)
+ != WC_NO_ERR_TRACE(LENGTH_ONLY_E))
+ {
+ WOLFSSL_MSG("get ecc der size failed");
+ PRIVATE_KEY_LOCK();
+ return WOLFSSL_FAILURE;
}
- 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 */
+ PRIVATE_KEY_LOCK();
- if (ret != WOLFSSL_SUCCESS)
- return ret;
+ 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;
+ }
-#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");
+ 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);
}
-#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;
+ *pkey = ret;
+#ifdef HAVE_ECC
+ if (ret != NULL)
+ return WOLFSSL_SUCCESS;
+ else
#endif
-
- return WOLFSSL_SUCCESS;
+ return WOLFSSL_FAILURE;
}
+#endif /* !NO_WOLFSSL_SERVER */
-#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)
+/**
+ * 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)
{
- 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 sanityConfirmed = 0;
- WOLFSSL_MSG("Trying to add client cache entry");
+ (void)options;
- 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;
- }
+ switch (major) {
+ #ifndef NO_TLS
+ case SSLv3_MAJOR:
+ #ifdef WOLFSSL_ALLOW_SSLV3
+ if (!(options & WOLFSSL_OP_NO_SSLv3)) {
+ sanityConfirmed = 1;
}
- }
- 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");
- }
+ #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("Skipping client cache");
+ if (!sanityConfirmed) {
+ WOLFSSL_MSG("All compiled in TLS versions disabled");
+ return WOLFSSL_FAILURE;
}
-
- return ret;
+ return WOLFSSL_SUCCESS;
}
-#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.
+ * 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))
+
+/**
+ * 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.
*/
-WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session)
+static int Set_CTX_min_proto_version(WOLFSSL_CTX* ctx, int version)
{
- 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;
+ WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version_ex");
+
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
}
- else {
- /* Plain WOLFSSL_SESSION object */
- return (WOLFSSL_SESSION*)session;
+
+ 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;
}
-#else
- return (WOLFSSL_SESSION*)session;
+
+ 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;
+ }
+
+ return CheckSslMethodVersion(ctx->method->version.major, ctx->mask);
}
-int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
- const byte* id, byte idSz, int* sessionIndex, int side,
- word16 useTicket, ClientSession** clientCacheEntry)
+/* 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)
{
- 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 ret;
+ int proto = 0;
+ int maxProto = 0;
int i;
- int overwrite = 0;
- (void)ctx;
- (void)sessionIndex;
- (void)useTicket;
- (void)clientCacheEntry;
+ int idx = 0;
- WOLFSSL_ENTER("AddSessionToCache");
+ WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version");
- if (idSz == 0) {
- WOLFSSL_MSG("AddSessionToCache idSz == 0");
- return BAD_FUNC_ARG;
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
}
- 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 (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 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;
+ 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;
+ }
}
- 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;
+ /* 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;
}
}
-
- 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 */
+ 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);
}
-#endif
+ ret = Set_CTX_min_proto_version(ctx, proto);
return ret;
}
-void AddSession(WOLFSSL* ssl)
+/**
+ * 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 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;
- }
+ int ret;
+ WOLFSSL_ENTER("Set_CTX_max_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 (!ctx || !ctx->method) {
+ WOLFSSL_MSG("Bad parameter");
+ 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
+#ifndef NO_OLD_TLS
+ case SSL2_VERSION:
+ WOLFSSL_MSG("wolfSSL does not support SSLv2");
+ return WOLFSSL_FAILURE;
#endif
- ssl->options.side,
-#ifdef HAVE_SESSION_TICKET
- ssl->options.useTicket,
-#else
- 0,
+ 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 NO_SESSION_CACHE_REF
- NULL
-#else
- (ssl->options.side == WOLFSSL_CLIENT_END) ?
- &ssl->clientSession : NULL
+#ifdef WOLFSSL_DTLS
+ case DTLS1_VERSION:
+ case DTLS1_2_VERSION:
+ break;
#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);
+ default:
+ WOLFSSL_MSG("Unrecognized protocol version or not compiled in");
+ return WOLFSSL_FAILURE;
}
-#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;
+ 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) {
+ #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;
}
}
-#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 ret;
}
-int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session)
+/* 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 row, col, result = WOLFSSL_FAILURE;
- SessionRow* sessRow;
- WOLFSSL_SESSION* cacheSession;
-
- WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex");
-
- session = ClientSessionToSession(session);
+ int i;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ int minProto;
- row = idx >> SESSIDX_ROW_SHIFT;
- col = idx & SESSIDX_IDX_MASK;
+ WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version");
- if (session == NULL ||
- row < 0 || row >= SESSION_ROWS || col >= SESSIONS_PER_ROW) {
- return WOLFSSL_FAILURE;
+ if (ctx == NULL) {
+ return ret;
}
- sessRow = &SessionCache[row];
- if (SESSION_ROW_RD_LOCK(sessRow) != 0) {
- return BAD_MUTEX_E;
+ /* 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);
}
-#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 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;
+ }
}
- 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_min_proto_version(WOLFSSL* ssl, int ver)
{
- WOLFSSL_X509_CHAIN* chain = NULL;
+ WOLFSSL_ENTER("Set_SSL_min_proto_version");
- WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain");
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
+ }
- session = ClientSessionToSession(session);
+ 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;
+ }
- if (session)
- chain = &session->chain;
+ 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;
+ }
- WOLFSSL_LEAVE("wolfSSL_SESSION_get_peer_chain", chain ? 1 : 0);
- return chain;
+ return CheckSslMethodVersion(ssl->version.major, ssl->options.mask);
}
-
-#ifdef OPENSSL_EXTRA
-/* gets the peer certificate associated with the session passed in
- * returns null on failure, the caller should not free the returned pointer */
-WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session)
+int wolfSSL_set_min_proto_version(WOLFSSL* ssl, int version)
{
- WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain");
+ int i;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);;
- session = ClientSessionToSession(session);
- if (session) {
- int count;
+ WOLFSSL_ENTER("wolfSSL_set_min_proto_version");
- count = wolfSSL_get_chain_count(&session->chain);
- if (count < 1 || count >= MAX_CHAIN_DEPTH) {
- WOLFSSL_MSG("bad count found");
- return NULL;
- }
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ if (version != 0) {
+ return Set_SSL_min_proto_version(ssl, version);
+ }
- if (session->peer == NULL) {
- session->peer = wolfSSL_get_chain_X509(&session->chain, 0);
- }
- return session->peer;
+ /* when 0 is specified as version, try to find out the min version */
+ for (i= 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) {
+ ret = Set_SSL_min_proto_version(ssl, protoVerTbl[i]);
+ if (ret == WOLFSSL_SUCCESS)
+ break;
}
- WOLFSSL_MSG("No session passed in");
- return NULL;
+ return ret;
}
-#endif /* OPENSSL_EXTRA */
-#endif /* SESSION_INDEX && SESSION_CERTS */
-
-
-#ifdef WOLFSSL_SESSION_STATS
-static int get_locked_session_stats(word32* active, word32* total, word32* peak)
+static int Set_SSL_max_proto_version(WOLFSSL* ssl, int ver)
{
- 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;
- }
+ WOLFSSL_ENTER("Set_SSL_max_proto_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 */
- }
+ if (!ssl) {
+ WOLFSSL_MSG("Bad parameter");
+ return WOLFSSL_FAILURE;
+ }
- 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) )
+ 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
- {
- 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]);
+#ifdef WOLFSSL_DTLS
+ case DTLS1_VERSION:
+ case DTLS1_2_VERSION:
+ break;
#endif
-
- if (active) {
- *active = now;
- }
- if (total) {
- *total = seen;
- }
-
-#ifdef WOLFSSL_PEAK_SESSIONS
- if (peak) {
- *peak = PeakSessions;
+ default:
+ WOLFSSL_MSG("Unrecognized protocol version or not compiled in");
+ return WOLFSSL_FAILURE;
}
-#else
- (void)peak;
-#endif
- WOLFSSL_LEAVE("get_locked_session_stats", result);
-
- return result;
+ return CheckSslMethodVersion(ssl->version.major, ssl->options.mask);
}
-
-/* return WOLFSSL_SUCCESS on ok */
-int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
- word32* maxSessions)
+int wolfSSL_set_max_proto_version(WOLFSSL* ssl, int version)
{
- int result = WOLFSSL_SUCCESS;
-
- WOLFSSL_ENTER("wolfSSL_get_session_stats");
+ int i;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);;
- if (maxSessions) {
- *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS;
+ WOLFSSL_ENTER("wolfSSL_set_max_proto_version");
- if (active == NULL && total == NULL && peak == NULL)
- return result; /* we're done */
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
}
-
- /* user must provide at least one query value */
- if (active == NULL && total == NULL && peak == NULL) {
- return BAD_FUNC_ARG;
+ if (version != 0) {
+ return Set_SSL_max_proto_version(ssl, version);
}
- result = get_locked_session_stats(active, total, peak);
-
- WOLFSSL_LEAVE("wolfSSL_get_session_stats", result);
+ /* 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;
+ }
- return result;
+ return ret;
}
-#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");
+static int GetMinProtoVersion(int minDowngrade)
+{
+ int ret;
- return ret;
+ switch (minDowngrade) {
+#ifndef NO_OLD_TLS
+ #ifdef WOLFSSL_ALLOW_SSLV3
+ case SSLv3_MINOR:
+ ret = SSL3_VERSION;
+ break;
+ #endif
+ #ifdef WOLFSSL_ALLOW_TLSV10
+ case TLSv1_MINOR:
+ ret = TLS1_VERSION;
+ break;
+ #endif
+ case TLSv1_1_MINOR:
+ ret = TLS1_1_VERSION;
+ break;
+#endif
+#ifndef WOLFSSL_NO_TLS12
+ case TLSv1_2_MINOR:
+ ret = TLS1_2_VERSION;
+ break;
+#endif
+#ifdef WOLFSSL_TLS13
+ case TLSv1_3_MINOR:
+ ret = TLS1_3_VERSION;
+ break;
+#endif
+ default:
+ ret = 0;
+ break;
}
- #endif /* SESSION_STATS */
-
-#else /* NO_SESSION_CACHE */
-
-WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session)
-{
- return (WOLFSSL_SESSION*)session;
+ return ret;
}
-/* No session cache version */
-WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret,
- byte restoreSessionCerts)
+int wolfSSL_CTX_get_min_proto_version(WOLFSSL_CTX* ctx)
{
- (void)ssl;
- (void)masterSecret;
- (void)restoreSessionCerts;
-
- return NULL;
-}
-
-#endif /* NO_SESSION_CACHE */
+ int ret = 0;
+ WOLFSSL_ENTER("wolfSSL_CTX_get_min_proto_version");
-/* call before SSL_connect, if verifying will add name check to
- date check and signature check */
-WOLFSSL_ABI
-int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn)
-{
- WOLFSSL_ENTER("wolfSSL_check_domain_name");
-
- if (ssl == NULL || dn == NULL) {
- WOLFSSL_MSG("Bad function argument: NULL");
- return WOLFSSL_FAILURE;
- }
-
- if (ssl->buffers.domainName.buffer)
- XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
-
- 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->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 (ctx != NULL) {
+ if (ctx->minProto) {
+ ret = 0;
+ }
+ else {
+ ret = GetMinProtoVersion(ctx->minDowngrade);
+ }
}
else {
- ssl->error = MEMORY_ERROR;
- return WOLFSSL_FAILURE;
+ ret = GetMinProtoVersion(WOLFSSL_MIN_DOWNGRADE);
}
+
+ WOLFSSL_LEAVE("wolfSSL_CTX_get_min_proto_version", ret);
+
+ return ret;
}
-/* turn on wolfSSL zlib compression
- returns WOLFSSL_SUCCESS for success, else error (not built in)
-*/
-int wolfSSL_set_compression(WOLFSSL* ssl)
+/* returns the maximum allowed protocol version given the 'options' used
+ * returns WOLFSSL_FATAL_ERROR on no match */
+static int GetMaxProtoVersion(long options)
{
- WOLFSSL_ENTER("wolfSSL_set_compression");
- (void)ssl;
-#ifdef HAVE_LIBZ
- ssl->options.usingCompression = 1;
- return WOLFSSL_SUCCESS;
-#else
- return NOT_COMPILED_IN;
+#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;
}
-#ifndef USE_WINDOWS_API
- #ifndef NO_WRITEV
+/* 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 */
- /* 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;
+ WOLFSSL_ENTER("wolfSSL_CTX_get_max_proto_version");
- WOLFSSL_ENTER("wolfSSL_writev");
+ if (ctx != NULL) {
+ options = wolfSSL_CTX_get_options(ctx);
+ }
- for (i = 0; i < iovcnt; i++)
- sending += (int)iov[i].iov_len;
+ if ((ctx != NULL) && ctx->maxProto) {
+ ret = 0;
+ }
+ else {
+ ret = GetMaxProtoVersion(options);
+ }
- if (sending > (int)sizeof(staticBuffer)) {
- myBuffer = (byte*)XMALLOC(sending, ssl->heap,
- DYNAMIC_TYPE_WRITEV);
- if (!myBuffer)
- return MEMORY_ERROR;
+ WOLFSSL_LEAVE("wolfSSL_CTX_get_max_proto_version", ret);
- dynamic = 1;
- }
+ if (ret == WC_NO_ERR_TRACE(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 */
- for (i = 0; i < iovcnt; i++) {
- XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len);
- idx += (int)iov[i].iov_len;
- }
+#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)
+{
+ size_t size;
- /* 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
+ /* return max size of buffer */
+ if (outSz == 0) {
+ return RAN_LEN;
+ }
- if (dynamic)
- XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV);
+ if (ssl == NULL || out == NULL) {
+ return 0;
+ }
- return ret;
- }
- #endif
-#endif
+ if (ssl->arrays == NULL) {
+ WOLFSSL_MSG("Arrays struct not saved after handshake");
+ return 0;
+ }
+ if (outSz > RAN_LEN) {
+ size = RAN_LEN;
+ }
+ else {
+ size = outSz;
+ }
-#ifdef WOLFSSL_CALLBACKS
+ XMEMCPY(out, ssl->arrays->clientRandom, size);
+ return size;
+}
+#endif /* !NO_WOLFSSL_CLIENT */
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */
- typedef struct itimerval Itimerval;
+#ifdef OPENSSL_EXTRA
- /* don't keep calling simple functions while setting up timer and signals
- if no inlining these are the next best */
+ unsigned long wolfSSLeay(void)
+ {
+#ifdef SSLEAY_VERSION_NUMBER
+ return SSLEAY_VERSION_NUMBER;
+#else
+ return OPENSSL_VERSION_NUMBER;
+#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)
+ 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 wolfSSL_OpenSSL_version();
+#endif
+ }
+#endif /* OPENSSL_EXTRA */
- #define SubtractTimes(a, b, c) \
- do { \
- (c).tv_sec = (a).tv_sec - (b).tv_sec; \
- (c).tv_usec = (a).tv_usec - (b).tv_usec;\
- if ((c).tv_usec < 0) { \
- (c).tv_sec--; \
- (c).tv_usec += 1000000; \
- } \
- } while (0)
+#ifdef OPENSSL_EXTRA
+ void wolfSSL_ERR_free_strings(void)
+ {
+ /* handled internally */
+ }
- #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)) \
+ void wolfSSL_cleanup_all_ex_data(void)
+ {
+ /* nothing to do here */
+ }
+#endif /* OPENSSL_EXTRA */
- /* do nothing handler */
- static void myHandler(int signo)
+#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) || \
+ defined(HAVE_CURL)
+ void wolfSSL_ERR_clear_error(void)
{
- (void)signo;
- return;
+ WOLFSSL_ENTER("wolfSSL_ERR_clear_error");
+ #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
+ wc_ClearErrorNodes();
+ #endif
}
+#endif
-
- static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb,
- TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+ int wolfSSL_clear(WOLFSSL* ssl)
{
- 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_ENTER("wolfSSL_clear");
- #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; }
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
+ }
- if (hsCb) {
- ssl->hsInfoOn = 1;
- InitHandShakeInfo(&ssl->handShakeInfo, ssl);
+ 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;
+ }
}
- 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;
+ /* reset error */
+ ssl->error = 0;
- /* 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;
+ /* 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_TLS13
+ #ifdef WOLFSSL_SEND_HRR_COOKIE
+ ssl->options.hrrSentCookie = 0;
+ #endif
+ ssl->options.hrrSentKeyShare = 0;
+ #endif
+ #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
- /* 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 defined(HAVE_TLS_EXTENSIONS) && !defined(NO_TLS)
+ TLSX_FreeAll(ssl->extensions, ssl->heap);
+ ssl->extensions = NULL;
+ #endif
- if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0)
- ERR_OUT(SETITIMER_ERROR);
+ 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));
- /* 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
+ FreeCiphers(ssl);
+ InitCiphers(ssl);
+ InitCipherSpecs(&ssl->specs);
- /* 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 (InitSSL_Suites(ssl) != WOLFSSL_SUCCESS)
+ return WOLFSSL_FAILURE;
- /* if we had a timeout call callback */
- if (ssl->timeoutInfo.timeoutName[0]) {
- ssl->timeoutInfo.timeoutValue.tv_sec = timeout.tv_sec;
- ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec;
- (toCb)(&ssl->timeoutInfo);
- }
- ssl->toInfoOn = 0;
- }
+ if (InitHandshakeHashes(ssl) != 0)
+ return WOLFSSL_FAILURE;
- /* clean up buffers allocated by AddPacketInfo */
- FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap);
+#ifdef KEEP_PEER_CERT
+ FreeX509(&ssl->peerCert);
+ InitX509(&ssl->peerCert, 0, ssl->heap);
+#endif
- if (hsCb) {
- FinishHandShakeInfo(&ssl->handShakeInfo);
- (hsCb)(&ssl->handShakeInfo);
- ssl->hsInfoOn = 0;
- }
- return ret;
+#ifdef WOLFSSL_QUIC
+ wolfSSL_quic_clear(ssl);
+#endif
+#ifdef HAVE_OCSP
+#if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)
+ ssl->response_idx = 0;
+#endif
+#endif
+ return WOLFSSL_SUCCESS;
}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
-#ifndef NO_WOLFSSL_CLIENT
-
- int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
- TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
+#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_MEMCACHED)
+ long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode)
{
- WOLFSSL_ENTER("wolfSSL_connect_ex");
- return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
- }
+ /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
-#endif
+ WOLFSSL_ENTER("wolfSSL_CTX_set_mode");
+ switch(mode) {
+ case WOLFSSL_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 WOLFSSL_MODE_AUTO_RETRY:
+ ctx->autoRetry = 1;
+ break;
+ default:
+ WOLFSSL_MSG("Mode Not Implemented");
+ }
+ /* WOLFSSL_MODE_AUTO_RETRY
+ * Should not return WOLFSSL_FATAL_ERROR with renegotiation on read/write */
-#ifndef NO_WOLFSSL_SERVER
+ return mode;
+ }
- int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb,
- TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout)
+ long wolfSSL_CTX_clear_mode(WOLFSSL_CTX* ctx, long mode)
{
- WOLFSSL_ENTER("wolfSSL_accept_ex");
- return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
- }
+ /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
-#endif
+ WOLFSSL_ENTER("wolfSSL_CTX_clear_mode");
+ switch(mode) {
+ case WOLFSSL_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 WOLFSSL_MODE_AUTO_RETRY:
+ ctx->autoRetry = 0;
+ break;
+ default:
+ WOLFSSL_MSG("Mode Not Implemented");
+ }
-#endif /* WOLFSSL_CALLBACKS */
+ /* WOLFSSL_MODE_AUTO_RETRY
+ * Should not return WOLFSSL_FATAL_ERROR with renegotiation on read/write */
+ return 0;
+ }
+#endif
-#ifndef NO_PSK
+#ifdef OPENSSL_EXTRA
- void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx,
- wc_psk_client_callback cb)
+ #ifndef NO_WOLFSSL_STUB
+ long wolfSSL_SSL_get_mode(WOLFSSL* ssl)
{
- WOLFSSL_ENTER("wolfSSL_CTX_set_psk_client_callback");
-
- if (ctx == NULL)
- return;
-
- ctx->havePSK = 1;
- ctx->client_psk_cb = cb;
+ /* TODO: */
+ (void)ssl;
+ WOLFSSL_STUB("SSL_get_mode");
+ return 0;
}
+ #endif
- void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb)
+ #ifndef NO_WOLFSSL_STUB
+ long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx)
{
- byte haveRSA = 1;
- int keySz = 0;
-
- WOLFSSL_ENTER("wolfSSL_set_psk_client_callback");
-
- if (ssl == NULL)
- return;
+ /* TODO: */
+ (void)ctx;
+ WOLFSSL_STUB("SSL_CTX_get_mode");
+ return 0;
+ }
+ #endif
- 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);
+ #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");
}
- #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
+ #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
*/
- void wolfSSL_set_psk_use_session_callback(WOLFSSL* ssl,
- wc_psk_use_session_cb_func cb)
+ unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line)
{
- WOLFSSL_ENTER("wolfSSL_set_psk_use_session_callback");
+ #ifdef WOLFSSL_HAVE_ERROR_QUEUE
+ int ret = wc_PullErrorNode(file, NULL, line);
+ if (ret < 0) {
+ if (ret == WC_NO_ERR_TRACE(BAD_STATE_E))
+ return 0; /* no errors in queue */
+ WOLFSSL_MSG("Issue getting error node");
+ WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret);
+ ret = 0 - ret; /* return absolute value of error */
- if (ssl != NULL) {
- ssl->options.havePSK = 1;
- ssl->options.session_psk_cb = cb;
+ /* panic and try to clear out nodes */
+ wc_ClearErrorNodes();
}
+ return (unsigned long)ret;
+ #else
+ (void)file;
+ (void)line;
- WOLFSSL_LEAVE("wolfSSL_set_psk_use_session_callback", WOLFSSL_SUCCESS);
- }
+ return 0;
#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;
}
- void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb)
- {
- byte haveRSA = 1;
- int keySz = 0;
-
- WOLFSSL_ENTER("wolfSSL_set_psk_server_callback");
- if (ssl == NULL)
- return;
- ssl->options.havePSK = 1;
- ssl->options.server_psk_cb = cb;
+#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";
- #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);
+ /* 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 */
- const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_psk_identity_hint");
- if (ssl == NULL || ssl->arrays == NULL)
- return NULL;
+ void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file,
+ int line)
+ {
+ WOLFSSL_ENTER("wolfSSL_ERR_put_error");
- return ssl->arrays->server_hint;
+ #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;
}
- const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl)
+ /* 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 WOLFSSL_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)
{
- WOLFSSL_ENTER("wolfSSL_get_psk_identity");
+#ifdef WOLFSSL_HAVE_ERROR_QUEUE
+ int ret;
- if (ssl == NULL || ssl->arrays == NULL)
- return NULL;
+ WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data");
- return ssl->arrays->client_identity;
- }
+ if (flags != NULL)
+ *flags = WOLFSSL_ERR_TXT_STRING; /* Clear the flags */
- 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 */
+ ret = wc_PullErrorNode(file, data, line);
+ if (ret < 0) {
+ if (ret == WC_NO_ERR_TRACE(BAD_STATE_E))
+ return 0; /* no errors in queue */
+ WOLFSSL_MSG("Error with pulling error node!");
+ WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret);
+ ret = 0 - ret; /* return absolute value of error */
+
+ /* panic and try to clear out nodes */
+ wc_ClearErrorNodes();
}
- return 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
}
- int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint)
+#endif /* OPENSSL_EXTRA */
+
+
+#if (defined(KEEP_PEER_CERT) && defined(SESSION_CERTS)) || \
+ (defined(OPENSSL_EXTRA) && defined(SESSION_CERTS))
+ /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object.
+ *
+ * x509 WOLFSSL_X509 object to decode into.
+ * in X509 DER data.
+ * len Length of the X509 DER data.
+ * returns the new certificate on success, otherwise NULL.
+ */
+ static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len)
{
- WOLFSSL_ENTER("wolfSSL_use_psk_identity_hint");
+ int ret;
+ WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
+ if (x509 == NULL || in == NULL || len <= 0)
+ return BAD_FUNC_ARG;
- if (ssl == NULL || ssl->arrays == NULL)
- return WOLFSSL_FAILURE;
+ WC_ALLOC_VAR_EX(cert, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
+ return MEMORY_E);
- 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';
+ /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object.
+ */
+ InitDecodedCert(cert, (byte*)in, (word32)len, NULL);
+ if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL, NULL)) == 0) {
+ /* Check if x509 was not previously initialized by wolfSSL_X509_new() */
+ if (x509->dynamicMemory != TRUE)
+ InitX509(x509, 0, NULL);
+ ret = CopyDecodedToX509(x509, cert);
}
- return WOLFSSL_SUCCESS;
- }
+ FreeDecodedCert(cert);
+ WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
- void* wolfSSL_get_psk_callback_ctx(WOLFSSL* ssl)
- {
- return ssl ? ssl->options.psk_ctx : NULL;
+ return ret;
}
- void* wolfSSL_CTX_get_psk_callback_ctx(WOLFSSL_CTX* ctx)
+#endif /* (KEEP_PEER_CERT & SESSION_CERTS) || (OPENSSL_EXTRA & SESSION_CERTS) */
+
+
+#ifdef KEEP_PEER_CERT
+ WOLFSSL_ABI
+ WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl)
{
- 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;
+ WOLFSSL_X509* ret = NULL;
+ WOLFSSL_ENTER("wolfSSL_get_peer_certificate");
+ if (ssl != NULL) {
+ if (ssl->peerCert.issuer.sz)
+ ret = wolfSSL_X509_dup(&ssl->peerCert);
+#ifdef SESSION_CERTS
+ else if (ssl->session->chain.count > 0) {
+ if (DecodeToX509(&ssl->peerCert,
+ ssl->session->chain.certs[0].buffer,
+ ssl->session->chain.certs[0].length) == 0) {
+ ret = wolfSSL_X509_dup(&ssl->peerCert);
+ }
+ }
+#endif
+ }
+ WOLFSSL_LEAVE("wolfSSL_get_peer_certificate", ret != NULL);
+ return ret;
}
-#endif /* NO_PSK */
+#endif /* KEEP_PEER_CERT */
-#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;
+#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");
- ctx->useAnon = 1;
+ if (ssl == NULL)
+ return NULL;
- return WOLFSSL_SUCCESS;
+ /* 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;
+}
-#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;
+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 0 on success or no issuer found
+ * WOLFSSL_FATAL_ERROR on a fatal error
+ */
+static int PushCAx509Chain(WOLFSSL_CERT_MANAGER* cm,
+ WOLFSSL_X509 *x, WOLFSSL_STACK* sk)
+{
+ int i;
+ for (i = 0; i < MAX_CHAIN_DEPTH; i++) {
+ WOLFSSL_X509* issuer = NULL;
+ if (x509GetIssuerFromCM(&issuer, cm, x) != WOLFSSL_SUCCESS)
+ break;
+ if (wolfSSL_sk_X509_push(sk, issuer) <= 0) {
+ wolfSSL_X509_free(issuer);
+ issuer = NULL;
+ return WOLFSSL_FATAL_ERROR;
+ }
+ x = issuer;
+ }
+ return 0;
+}
- 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;
+/* Builds up and creates a stack of peer certificates for ssl->peerCertChain
+ or ssl->verifiedChain based off of the ssl session chain. Attempts to place
+ CA certificates at the bottom of the stack for a verified chain. Returns
+ stack of WOLFSSL_X509 certs or NULL on failure */
+static WOLF_STACK_OF(WOLFSSL_X509)* CreatePeerCertChain(const WOLFSSL* ssl,
+ int verifiedFlag)
+{
+ WOLFSSL_STACK* sk;
+ WOLFSSL_X509* x509;
+ int i = 0;
+ int err;
- 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_ENTER("wolfSSL_set_peer_cert_chain");
+ if ((ssl == NULL) || (ssl->session->chain.count == 0))
+ return NULL;
- WOLFSSL_LEAVE("wolfSSL_CTX_load_verify_buffer_ex", ret);
- return ret;
+ sk = wolfSSL_sk_X509_new_null();
+ for (i = 0; i < ssl->session->chain.count; 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;
+ }
+ err = DecodeToX509(x509, ssl->session->chain.certs[i].buffer,
+ ssl->session->chain.certs[i].length);
+ if (err == 0 && wolfSSL_sk_X509_push(sk, x509) <= 0)
+ err = WOLFSSL_FATAL_ERROR;
+ if (err == 0 && i == ssl->session->chain.count-1 && verifiedFlag) {
+ /* On the last element in the verified chain try to add the CA chain
+ * if we have one for this cert */
+ SSL_CM_WARNING(ssl);
+ err = PushCAx509Chain(SSL_CM(ssl), x509, sk);
+ }
+ if (err != 0) {
+ WOLFSSL_MSG("Error decoding cert");
+ wolfSSL_X509_free(x509);
+ x509 = NULL;
+ 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");
}
+ return sk;
+}
- 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);
- }
+/* Builds up and creates a stack of peer certificates for ssl->peerCertChain
+ returns the stack on success and NULL on failure */
+WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl)
+{
+ WOLFSSL_STACK* sk;
-#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");
+ WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain");
+ if ((ssl == NULL) || (ssl->session->chain.count == 0))
+ return NULL;
- /* sanity check on arguments */
- if (sz < 0 || in == NULL || ctx == NULL) {
- return BAD_FUNC_ARG;
- }
+ sk = CreatePeerCertChain(ssl, 0);
- #if (WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY)
- verify = VERIFY_SKIP_DATE;
- #else
- verify = GET_VERIFY_SETTING_CTX(ctx);
- #endif
+ if (sk != NULL) {
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+ if (ssl->session->peer)
+ wolfSSL_X509_free(ssl->session->peer);
- 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);
+ ssl->session->peer = wolfSSL_sk_X509_shift(sk);
+ ssl->session->peerVerifyRet = ssl->peerVerifyRet;
+ }
+ if (ssl->peerCertChain != NULL)
+ wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL);
+ /* This is Free'd when ssl is Free'd */
+ ssl->peerCertChain = sk;
}
-#endif /* WOLFSSL_TRUST_PEER_CERT */
+ return sk;
+}
+#ifdef KEEP_PEER_CERT
+/**
+ * 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;
- int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx,
- const unsigned char* in, long sz, int format)
- {
- int ret = WOLFSSL_FAILURE;
+ WOLFSSL_ENTER("wolfSSL_get0_verified_chain");
- 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;
+ if (ssl == NULL || ssl->ctx == NULL) {
+ WOLFSSL_MSG("Bad parameter");
+ return NULL;
}
-
- 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;
+ peerCert = wolfSSL_get_peer_certificate((WOLFSSL*)ssl);
+ if (peerCert == NULL) {
+ WOLFSSL_MSG("wolfSSL_get_peer_certificate error");
+ return NULL;
}
-
-#ifdef WOLF_PRIVATE_KEY_ID
- int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
- long sz, int devId, long keySz)
- {
- int ret = wolfSSL_CTX_use_PrivateKey_Id(ctx, id, sz, devId);
-
- if (ret == WOLFSSL_SUCCESS)
- ctx->privateKeySz = (word32)keySz;
-
- return ret;
+ /* 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 = CreatePeerCertChain((WOLFSSL*)ssl, 1);
+ if (chain == NULL) {
+ WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error");
+ return NULL;
}
- 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;
- }
-
- return ret;
+ if (ssl->verifiedChain != NULL) {
+ wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL);
}
+ ((WOLFSSL*)ssl)->verifiedChain = chain;
- 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 ret;
+ storeCtx = wolfSSL_X509_STORE_CTX_new();
+ if (storeCtx == NULL) {
+ WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_new error");
+ return NULL;
}
-#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));
+ 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;
}
-
- 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);
+ 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 /* KEEP_PEER_CERT */
+#endif /* SESSION_CERTS && OPENSSL_EXTRA */
+#ifndef NO_CERTS
-#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);
+/* 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;
+ }
- if (p == NULL || g == NULL) {
- XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- return MEMORY_E;
+ 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,
+ (int)ssl->buffers.certificate->length,
+ ssl->heap);
+ #endif
}
- #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);
+ 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;
}
- #endif
- #endif /* WOLFSSL_WPAS */
-#else
- ret = NOT_COMPILED_IN;
-#endif /* WOLFSSL_PEM_TO_DER */
- }
-
- if (ret == 0) {
- if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0)
- ret = WOLFSSL_BAD_FILETYPE;
- else if (ssl)
- ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz);
- else
- ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz);
+ #ifndef WOLFSSL_X509_STORE_CERTS
+ ssl->ctx->ourCert = wolfSSL_X509_d2i_ex(NULL,
+ ssl->ctx->certificate->buffer,
+ (int)ssl->ctx->certificate->length,
+ ssl->heap);
+ #endif
+ ssl->ctx->ownOurCert = 1;
}
+ return ssl->ctx->ourCert;
}
+ }
- FreeDer(&der);
+ return NULL;
+}
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- #endif
-
- return ret;
+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,
+ (int)ctx->certificate->length,
+ ctx->heap);
+ #endif
+ ctx->ownOurCert = 1;
+ }
+ return ctx->ourCert;
}
+ return NULL;
+}
+#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */
+#endif /* NO_CERTS */
-
- /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */
- int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz,
- int format)
- {
- if (ssl == NULL)
- return BAD_FUNC_ARG;
-
- return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format);
+#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;
}
-
- /* 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);
+ #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
-#endif /* NO_DH */
-
+ if (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error initializing client side");
+ }
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
- int wolfSSL_use_certificate_buffer(WOLFSSL* ssl,
- const unsigned char* in, long sz, int format)
- {
- WOLFSSL_ENTER("wolfSSL_use_certificate_buffer");
- if (ssl == NULL)
- return BAD_FUNC_ARG;
- return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0,
- GET_VERIFY_SETTING_SSL(ssl));
- }
+int wolfSSL_get_shutdown(const WOLFSSL* ssl)
+{
+ int isShutdown = 0;
+ WOLFSSL_ENTER("wolfSSL_get_shutdown");
- 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;
+ 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;
+ }
- return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE,
- ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl));
}
-#ifdef WOLF_PRIVATE_KEY_ID
- int wolfSSL_use_PrivateKey_id(WOLFSSL* ssl, const unsigned char* id,
- long sz, int devId, long keySz)
- {
- int ret = wolfSSL_use_PrivateKey_Id(ssl, id, sz, devId);
+ WOLFSSL_LEAVE("wolfSSL_get_shutdown", isShutdown);
+ return isShutdown;
+}
- if (ret == WOLFSSL_SUCCESS)
- ssl->buffers.keySz = (word32)keySz;
- return ret;
+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_use_PrivateKey_Id(WOLFSSL* ssl, const unsigned char* id,
- long sz, int devId)
- {
- int ret = WOLFSSL_FAILURE;
+/* 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");
- 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;
+ if (version == NULL) {
+ return "Bad arg";
+ }
- ret = WOLFSSL_SUCCESS;
+ 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 ret;
}
-
- int wolfSSL_use_PrivateKey_Label(WOLFSSL* ssl, const char* label, int devId)
- {
- int ret = WOLFSSL_FAILURE;
- word32 sz = (word32)XSTRLEN(label) + 1;
-
- if (ssl->buffers.weOwnKey)
- FreeDer(&ssl->buffers.key);
- if (AllocDer(&ssl->buffers.key, (word32)sz, PRIVATEKEY_TYPE,
- ssl->heap) == 0) {
- XMEMCPY(ssl->buffers.key->buffer, label, sz);
- ssl->buffers.weOwnKey = 1;
- ssl->buffers.keyLabel = 1;
- if (devId != INVALID_DEVID)
- ssl->buffers.keyDevId = devId;
- else
- ssl->buffers.keyDevId = ssl->devId;
-
- ret = WOLFSSL_SUCCESS;
+#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";
}
-
- return ret;
}
-#endif /* WOLF_PRIVATE_KEY_ID */
+#endif /* WOLFSSL_DTLS */
+ return "unknown";
+}
- 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));
+const char* wolfSSL_get_version(const WOLFSSL* ssl)
+{
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Bad argument");
+ return "unknown";
}
- 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);
- }
+ return wolfSSL_internal_get_version(&ssl->version);
+}
- /* 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;
- }
+/* current library version */
+const char* wolfSSL_lib_version(void)
+{
+ return LIBWOLFSSL_VERSION_STRING;
+}
- 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;
- }
+#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
- 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;
- }
+/* current library version in hex */
+word32 wolfSSL_lib_version_hex(void)
+{
+ return LIBWOLFSSL_VERSION_HEX;
+}
-#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;
+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;
+}
+
+WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_current_cipher");
+ if (ssl) {
+ ssl->cipher.cipherSuite0 = ssl->options.cipherSuite0;
+ ssl->cipher.cipherSuite = ssl->options.cipherSuite;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ ssl->cipher.bits = ssl->specs.key_size * 8;
+#endif
+ return &ssl->cipher;
}
+ else
+ return NULL;
+}
- int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs");
+const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher)
+{
+ WOLFSSL_ENTER("wolfSSL_CIPHER_get_name");
- if (ctx == NULL)
- return BAD_FUNC_ARG;
-
- return wolfSSL_CertManagerUnloadCAs(ctx->cm);
+ if (cipher == NULL) {
+ return NULL;
}
- int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts");
-
- if (ctx == NULL)
- return BAD_FUNC_ARG;
+ #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \
+ !defined(WOLFSSL_QT)
+ return GetCipherNameIana(cipher->cipherSuite0, cipher->cipherSuite);
+ #else
+ return wolfSSL_get_cipher_name_from_suite(cipher->cipherSuite0,
+ cipher->cipherSuite);
+ #endif
+}
- if (ctx->ref.count > 1) {
- WOLFSSL_MSG("ctx object must have a ref count of 1 before "
- "unloading intermediate certs");
- return BAD_STATE_E;
- }
+const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher)
+{
+ WOLFSSL_ENTER("wolfSSL_CIPHER_get_version");
- return wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm);
+ if (cipher == NULL || cipher->ssl == NULL) {
+ return NULL;
}
+ return wolfSSL_get_version(cipher->ssl);
+}
-#ifdef WOLFSSL_TRUST_PEER_CERT
- int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
+const char* wolfSSL_get_cipher(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_cipher");
+ return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl));
+}
- if (ctx == NULL)
- return BAD_FUNC_ARG;
+/* 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);
+}
- return wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
- }
+const char* wolfSSL_get_cipher_name_from_suite(byte cipherSuite0,
+ byte cipherSuite)
+{
+ return GetCipherNameInternal(cipherSuite0, cipherSuite);
+}
-#ifdef WOLFSSL_LOCAL_X509_STORE
- int wolfSSL_Unload_trust_peers(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
+const char* wolfSSL_get_cipher_name_iana_from_suite(byte cipherSuite0,
+ byte cipherSuite)
+{
+ return GetCipherNameIana(cipherSuite0, cipherSuite);
+}
- if (ssl == NULL)
- return BAD_FUNC_ARG;
+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, NULL, NULL,
+ flags);
+}
- 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 */
+word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher)
+{
+ word16 cipher_id = 0;
-#ifdef OPENSSL_EXTRA
+ WOLFSSL_ENTER("wolfSSL_CIPHER_get_id");
- int wolfSSL_add_all_algorithms(void)
- {
- WOLFSSL_ENTER("wolfSSL_add_all_algorithms");
- if (initRefCount != 0 || wolfSSL_Init() == WOLFSSL_SUCCESS)
- return WOLFSSL_SUCCESS;
- else
- return WOLFSSL_FATAL_ERROR;
+ if (cipher && cipher->ssl) {
+ cipher_id = (word16)(cipher->ssl->options.cipherSuite0 << 8) |
+ cipher->ssl->options.cipherSuite;
}
- int wolfSSL_OpenSSL_add_all_algorithms_noconf(void)
- {
- WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_noconf");
+ return cipher_id;
+}
- if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR)
- return WOLFSSL_FATAL_ERROR;
+const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value)
+{
+ const WOLFSSL_CIPHER* cipher = NULL;
+ byte cipherSuite0, cipherSuite;
+ WOLFSSL_ENTER("wolfSSL_get_cipher_by_value");
- return WOLFSSL_SUCCESS;
- }
+ /* extract cipher id information */
+ cipherSuite = (value & 0xFF);
+ cipherSuite0 = ((value >> 8) & 0xFF);
- 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. */
+ /* TODO: lookup by cipherSuite0 / cipherSuite */
+ (void)cipherSuite0;
+ (void)cipherSuite;
- if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) {
- return WOLFSSL_FATAL_ERROR;
- }
- return WOLFSSL_SUCCESS;
+ return cipher;
+}
+
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \
+ !defined(NO_DH)
+#ifdef HAVE_FFDHE
+static const char* wolfssl_ffdhe_name(word16 group)
+{
+ const char* str = NULL;
+ switch (group) {
+ case WOLFSSL_FFDHE_2048:
+ str = "FFDHE_2048";
+ break;
+ case WOLFSSL_FFDHE_3072:
+ str = "FFDHE_3072";
+ break;
+ case WOLFSSL_FFDHE_4096:
+ str = "FFDHE_4096";
+ break;
+ case WOLFSSL_FFDHE_6144:
+ str = "FFDHE_6144";
+ break;
+ case WOLFSSL_FFDHE_8192:
+ str = "FFDHE_8192";
+ break;
+ default:
+ break;
}
+ return str;
+}
+#endif
+/* Return the name of the curve used for key exchange as a printable string.
+ *
+ * ssl The SSL/TLS object.
+ * returns NULL if ECDH was not used, otherwise the name as a string.
+ */
+const char* wolfSSL_get_curve_name(WOLFSSL* ssl)
+{
+ const char* cName = NULL;
- /* 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;
+ WOLFSSL_ENTER("wolfSSL_get_curve_name");
+
+ if (ssl == NULL)
+ return NULL;
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM)
+ /* 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) {
+#ifndef WOLFSSL_NO_ML_KEM
+#if defined(WOLFSSL_WC_MLKEM)
+ #ifndef WOLFSSL_NO_ML_KEM_512
+ case WOLFSSL_ML_KEM_512:
+ return "ML_KEM_512";
+ case WOLFSSL_SECP256R1MLKEM512:
+ return "SecP256r1MLKEM512";
+#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS
+ case WOLFSSL_P256_ML_KEM_512_OLD:
+ return "P256_ML_KEM_512_OLD";
+#endif
+ #ifdef HAVE_CURVE25519
+ case WOLFSSL_X25519MLKEM512:
+ return "X25519MLKEM512";
+ #endif
+ #endif
+ #ifndef WOLFSSL_NO_ML_KEM_768
+ case WOLFSSL_ML_KEM_768:
+ return "ML_KEM_768";
+ case WOLFSSL_SECP384R1MLKEM768:
+ return "SecP384r1MLKEM768";
+#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS
+ case WOLFSSL_P384_ML_KEM_768_OLD:
+ return "P384_ML_KEM_768_OLD";
+#endif
+ case WOLFSSL_SECP256R1MLKEM768:
+ return "SecP256r1MLKEM768";
+ #ifdef HAVE_CURVE25519
+ case WOLFSSL_X25519MLKEM768:
+ return "X25519MLKEM768";
+ #endif
+ #ifdef HAVE_CURVE448
+ case WOLFSSL_X448MLKEM768:
+ return "X448MLKEM768";
+ #endif
+ #endif
+ #ifndef WOLFSSL_NO_ML_KEM_1024
+ case WOLFSSL_ML_KEM_1024:
+ return "ML_KEM_1024";
+ case WOLFSSL_SECP521R1MLKEM1024:
+ return "SecP521r1MLKEM1024";
+#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS
+ case WOLFSSL_P521_ML_KEM_1024_OLD:
+ return "P521_ML_KEM_1024_OLD";
+#endif
+ case WOLFSSL_SECP384R1MLKEM1024:
+ return "SecP384r1MLKEM1024";
+ #endif
+#elif defined(HAVE_LIBOQS)
+ case WOLFSSL_ML_KEM_512:
+ return "ML_KEM_512";
+ case WOLFSSL_ML_KEM_768:
+ return "ML_KEM_768";
+ case WOLFSSL_ML_KEM_1024:
+ return "ML_KEM_1024";
+ case WOLFSSL_SECP256R1MLKEM512:
+ return "SecP256r1MLKEM512";
+ case WOLFSSL_SECP384R1MLKEM768:
+ return "SecP384r1MLKEM768";
+ case WOLFSSL_SECP256R1MLKEM768:
+ return "SecP256r1MLKEM768";
+ case WOLFSSL_SECP521R1MLKEM1024:
+ return "SecP521r1MLKEM1024";
+ case WOLFSSL_SECP384R1MLKEM1024:
+ return "SecP384r1MLKEM1024";
+ #ifdef HAVE_CURVE25519
+ case WOLFSSL_X25519MLKEM512:
+ return "X25519MLKEM512";
+ case WOLFSSL_X25519MLKEM768:
+ return "X25519MLKEM768";
+ #endif
+ #ifdef HAVE_CURVE448
+ case WOLFSSL_X448MLKEM768:
+ return "X448MLKEM768";
+ #endif
+#endif /* WOLFSSL_WC_MLKEM */
+#endif /* WOLFSSL_NO_ML_KEM */
+#ifdef WOLFSSL_MLKEM_KYBER
+#if defined(WOLFSSL_WC_MLKEM)
+ #ifndef WOLFSSL_NO_KYBER512
+ case WOLFSSL_KYBER_LEVEL1:
+ return "KYBER_LEVEL1";
+ case WOLFSSL_P256_KYBER_LEVEL1:
+ return "P256_KYBER_LEVEL1";
+ #ifdef HAVE_CURVE25519
+ case WOLFSSL_X25519_KYBER_LEVEL1:
+ return "X25519_KYBER_LEVEL1";
+ #endif
+ #endif
+ #ifndef WOLFSSL_NO_KYBER768
+ case WOLFSSL_KYBER_LEVEL3:
+ return "KYBER_LEVEL3";
+ case WOLFSSL_P384_KYBER_LEVEL3:
+ return "P384_KYBER_LEVEL3";
+ case WOLFSSL_P256_KYBER_LEVEL3:
+ return "P256_KYBER_LEVEL3";
+ #ifdef HAVE_CURVE25519
+ case WOLFSSL_X25519_KYBER_LEVEL3:
+ return "X25519_KYBER_LEVEL3";
+ #endif
+ #ifdef HAVE_CURVE448
+ case WOLFSSL_X448_KYBER_LEVEL3:
+ return "X448_KYBER_LEVEL3";
#endif
+ #endif
+ #ifndef WOLFSSL_NO_KYBER1024
+ case WOLFSSL_KYBER_LEVEL5:
+ return "KYBER_LEVEL5";
+ case WOLFSSL_P521_KYBER_LEVEL5:
+ return "P521_KYBER_LEVEL5";
+ #endif
+#elif defined (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_P256_KYBER_LEVEL3:
+ return "P256_KYBER_LEVEL3";
+ case WOLFSSL_P521_KYBER_LEVEL5:
+ return "P521_KYBER_LEVEL5";
+ #ifdef HAVE_CURVE25519
+ case WOLFSSL_X25519_KYBER_LEVEL1:
+ return "X25519_KYBER_LEVEL1";
+ case WOLFSSL_X25519_KYBER_LEVEL3:
+ return "X25519_KYBER_LEVEL3";
+ #endif
+ #ifdef HAVE_CURVE448
+ case WOLFSSL_X448_KYBER_LEVEL3:
+ return "X448_KYBER_LEVEL3";
+ #endif
+#endif /* WOLFSSL_WC_MLKEM */
+#endif /* WOLFSSL_MLKEM_KYBER */
+ }
}
+#endif /* WOLFSSL_TLS13 && WOLFSSL_HAVE_MLKEM */
+#ifdef HAVE_FFDHE
+ if (ssl->namedGroup != 0) {
+ cName = wolfssl_ffdhe_name(ssl->namedGroup);
+ }
#endif
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
- defined(WOLFSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown");
- if (mode)
- ctx->quietShutdown = 1;
+#ifdef HAVE_CURVE25519
+ if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) {
+ cName = "X25519";
}
+#endif
+#ifdef HAVE_CURVE448
+ if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) {
+ cName = "X448";
+ }
+#endif
- void wolfSSL_set_quiet_shutdown(WOLFSSL* ssl, int mode)
- {
- WOLFSSL_ENTER("wolfSSL_set_quiet_shutdown");
- if (mode)
- ssl->options.quietShutdown = 1;
+#ifdef HAVE_ECC
+ if (ssl->ecdhCurveOID != 0 && cName == NULL) {
+ cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL,
+ NULL));
}
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL ||
- WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+#endif
+
+ return cName;
+}
+#endif
#ifdef OPENSSL_EXTRA
-#ifndef NO_BIO
- void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr)
- {
- WOLFSSL_ENTER("wolfSSL_set_bio");
+#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, WC_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", WC_NID_auth_rsa},
+ {"PSK", WC_NID_auth_psk},
+ {"SRP", WC_NID_auth_srp},
+ {"ECDSA", WC_NID_auth_ecdsa},
+ {"None", WC_NID_auth_null},
+ {NULL, WC_NID_undef}
+ };
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad argument, ssl was NULL");
- return;
- }
+ const char* authStr;
+ char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- /* 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 (GetCipherSegment(cipher, n) == NULL) {
+ WOLFSSL_MSG("no suitable cipher name found");
+ return WC_NID_undef;
+ }
+
+ authStr = GetCipherAuthStr(n);
+
+ if (authStr != NULL) {
+ const struct authnid* sa;
+ for(sa = authnid_tbl; sa->alg_name != NULL; sa++) {
+ if (XSTRCMP(sa->alg_name, authStr) == 0) {
+ return sa->nid;
}
- 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;
+ return WC_NID_undef;
+}
+/* return cipher NID corresponding to cipher suite
+ * @param cipher a pointer to WOLFSSL_CIPHER
+ * return NID if found, WC_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)", WC_NID_aes_256_gcm},
+ {"AESGCM(128)", WC_NID_aes_128_gcm},
+ {"AESCCM(128)", WC_NID_aes_128_ccm},
+ {"AES(128)", WC_NID_aes_128_cbc},
+ {"AES(256)", WC_NID_aes_256_cbc},
+ {"CAMELLIA(256)", WC_NID_camellia_256_cbc},
+ {"CAMELLIA(128)", WC_NID_camellia_128_cbc},
+ {"RC4", WC_NID_rc4},
+ {"3DES", WC_NID_des_ede3_cbc},
+ {"CHACHA20/POLY1305(256)", WC_NID_chacha20_poly1305},
+ {"None", WC_NID_undef},
+ {NULL, WC_NID_undef}
+ };
- /* set SSL to use BIO callbacks instead */
- if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0)) {
- ssl->CBIORecv = BioReceive;
- }
- if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0)) {
- ssl->CBIOSend = BioSend;
- }
+ const char* encStr;
+ char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- /* User programs should always retry reading from these BIOs */
- if (rd) {
- /* User writes to rd */
- BIO_set_retry_write(rd);
- }
- if (wr) {
- /* User reads from wr */
- BIO_set_retry_read(wr);
- }
+ WOLFSSL_ENTER("wolfSSL_CIPHER_get_cipher_nid");
+
+ if (GetCipherSegment(cipher, n) == NULL) {
+ WOLFSSL_MSG("no suitable cipher name found");
+ return WC_NID_undef;
}
-#endif /* !NO_BIO */
-#endif /* OPENSSL_EXTRA */
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA)
- void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx,
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list");
- if (ctx != NULL) {
- wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL);
- ctx->client_ca_names = names;
+ encStr = GetCipherEncStr(n);
+
+ if (encStr != NULL) {
+ const struct ciphernid* c;
+ for(c = ciphernid_tbl; c->alg_name != NULL; c++) {
+ if (XSTRCMP(c->alg_name, encStr) == 0) {
+ return c->nid;
+ }
}
}
- void wolfSSL_set_client_CA_list(WOLFSSL* ssl,
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
- {
- WOLFSSL_ENTER("wolfSSL_set_client_CA_list");
- if (ssl != NULL) {
- if (ssl->client_ca_names != ssl->ctx->client_ca_names)
- wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
- ssl->client_ca_names = names;
- }
+ return WC_NID_undef;
+}
+/* return digest NID corresponding to cipher suite
+ * @param cipher a pointer to WOLFSSL_CIPHER
+ * return NID if found, WC_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", WC_NID_sha1},
+ {"SHA256", WC_NID_sha256},
+ {"SHA384", WC_NID_sha384},
+ {NULL, WC_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");
+
+ if ((name = GetCipherSegment(cipher, n)) == NULL) {
+ WOLFSSL_MSG("no suitable cipher name found");
+ return WC_NID_undef;
}
- #ifdef OPENSSL_EXTRA
- /* registers client cert callback, called during handshake if server
- requests client auth but user has not loaded client cert/key */
- void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb");
+ /* in MD5 case, NID will be WC_NID_md5 */
+ if (XSTRSTR(name, "MD5") != NULL) {
+ return WC_NID_md5;
+ }
- if (ctx != NULL) {
- ctx->CBClientCert = cb;
+ 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;
+ }
}
}
- void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx,
- CertSetupCallback cb, void *arg)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_cert_cb");
- if (ctx == NULL)
- return;
+ return WC_NID_undef;
+}
+/* return key exchange NID corresponding to cipher suite
+ * @param cipher a pointer to WOLFSSL_CIPHER
+ * return NID if found, WC_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", WC_NID_kx_ecdhe_psk},
+ {"ECDH", WC_NID_kx_ecdhe},
+ {"DHEPSK", WC_NID_kx_dhe_psk},
+ {"DH", WC_NID_kx_dhe},
+ {"RSAPSK", WC_NID_kx_rsa_psk},
+ {"SRP", WC_NID_kx_srp},
+ {"EDH", WC_NID_kx_dhe},
+ {"RSA", WC_NID_kx_rsa},
+ {NULL, WC_NID_undef}
+ };
- ctx->certSetupCb = cb;
- ctx->certSetupCbArg = arg;
+ 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 WC_NID_undef;
}
- int wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl,
- const byte** suites, word16* suiteSz,
- const byte** hashSigAlgo, word16* hashSigAlgoSz)
- {
- WOLFSSL_ENTER("wolfSSL_get_client_suites_sigalgs");
+ /* in TLS 1.3 case, NID will be WC_NID_kx_any */
+ if (XSTRCMP(n[0], "TLS13") == 0) {
+ return WC_NID_kx_any;
+ }
- if (suites != NULL)
- *suites = NULL;
- if (suiteSz != NULL)
- *suiteSz = 0;
- if (hashSigAlgo != NULL)
- *hashSigAlgo = NULL;
- if (hashSigAlgoSz != NULL)
- *hashSigAlgoSz = 0;
+ keaStr = GetCipherKeaStr(n);
- if (ssl != NULL && ssl->clSuites != NULL) {
- if (suites != NULL && suiteSz != NULL) {
- *suites = ssl->clSuites->suites;
- *suiteSz = ssl->clSuites->suiteSz;
- }
- if (hashSigAlgo != NULL && hashSigAlgoSz != NULL) {
- *hashSigAlgo = ssl->clSuites->hashSigAlgo;
- *hashSigAlgoSz = ssl->clSuites->hashSigAlgoSz;
+ if (keaStr != NULL) {
+ const struct kxnid* k;
+ for(k = kxnid_table; k->name != NULL; k++) {
+ if (XSTRCMP(k->name, keaStr) == 0) {
+ return k->nid;
}
- return WOLFSSL_SUCCESS;
}
- return WOLFSSL_FAILURE;
- }
- WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first,
- byte second)
- {
- WOLFSSL_CIPHERSUITE_INFO info;
- info.rsaAuth = (byte)(CipherRequires(first, second, REQUIRES_RSA) ||
- CipherRequires(first, second, REQUIRES_RSA_SIG));
- info.eccAuth = (byte)(CipherRequires(first, second, REQUIRES_ECC) ||
- /* Static ECC ciphers may require RSA for authentication */
- (CipherRequires(first, second, REQUIRES_ECC_STATIC) &&
- !CipherRequires(first, second, REQUIRES_RSA_SIG)));
- info.eccStatic =
- (byte)CipherRequires(first, second, REQUIRES_ECC_STATIC);
- info.psk = (byte)CipherRequires(first, second, REQUIRES_PSK);
- return info;
}
- /**
- * @param first First byte of the hash and signature algorithm
- * @param second Second byte of the hash and signature algorithm
- * @param hashAlgo The enum wc_HashType of the MAC algorithm
- * @param sigAlgo The enum Key_Sum of the authentication algorithm
- */
- int wolfSSL_get_sigalg_info(byte first, byte second,
- int* hashAlgo, int* sigAlgo)
- {
- byte input[2];
- byte hashType;
- byte sigType;
+ return WC_NID_undef;
+}
+/* check if cipher suite is AEAD
+ * @param cipher a pointer to WOLFSSL_CIPHER
+ * return 1 if cipher is AEAD, 0 otherwise
+ */
+int wolfSSL_CIPHER_is_aead(const WOLFSSL_CIPHER* cipher)
+{
+ char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- if (hashAlgo == NULL || sigAlgo == NULL)
- return BAD_FUNC_ARG;
+ WOLFSSL_ENTER("wolfSSL_CIPHER_is_aead");
- input[0] = first;
- input[1] = second;
- DecodeSigAlg(input, &hashType, &sigType);
+ if (GetCipherSegment(cipher, n) == NULL) {
+ WOLFSSL_MSG("no suitable cipher name found");
+ return WC_NID_undef;
+ }
- /* 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;
+ 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 (cipher == NULL)
+ return WOLFSSL_FAILURE;
+
+ dp = cipher->description;
+ if (dp == NULL)
+ return WOLFSSL_FAILURE;
+
+ cipher_names = GetCipherNames();
+
+ 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;
+ }
+
+ /* keaStr */
+ keaStr = GetCipherKeaStr(n);
+ /* authStr */
+ authStr = GetCipherAuthStr(n);
+ /* encStr */
+ encStr = GetCipherEncStr(n);
+ if ((cipher->bits = SetCipherBits(encStr)) ==
+ WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
+ {
+ WOLFSSL_MSG("Cipher Bits Not Set.");
+ }
+ /* macStr */
+ macStr = GetCipherMacStr(n);
+
+
+ /* Build up the string by copying onto the end. */
+ XSTRNCPY(dp, name, (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += strLen;
+
+ XSTRNCPY(dp, " ", (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += strLen;
+ XSTRNCPY(dp, protocol, (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += strLen;
+
+ XSTRNCPY(dp, " Kx=", (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += strLen;
+ XSTRNCPY(dp, keaStr, (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += strLen;
+
+ XSTRNCPY(dp, " Au=", (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += strLen;
+ XSTRNCPY(dp, authStr, (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += strLen;
+
+ XSTRNCPY(dp, " Enc=", (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += strLen;
+ XSTRNCPY(dp, encStr, (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += strLen;
+
+ XSTRNCPY(dp, " Mac=", (size_t)len);
+ dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp);
+ len -= strLen; dp += (size_t)strLen;
+ XSTRNCPY(dp, macStr, (size_t)len);
+ dp[len-1] = '\0';
+
+ return WOLFSSL_SUCCESS;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_QT */
+
+static WC_INLINE const char* wolfssl_kea_to_string(int kea)
+{
+ const char* keaStr;
+
+ switch (kea) {
+ case no_kea:
+ keaStr = "None";
break;
- case rsa_pss_pss_algo:
- *sigAlgo = RSAPSSk;
+#ifndef NO_RSA
+ case rsa_kea:
+ keaStr = "RSA";
break;
- case ed448_sa_algo:
- *sigAlgo = ED448k;
+#endif
+#ifndef NO_DH
+ case diffie_hellman_kea:
+ keaStr = "DHE";
break;
- case falcon_level1_sa_algo:
- *sigAlgo = FALCON_LEVEL1k;
+#endif
+ case fortezza_kea:
+ keaStr = "FZ";
break;
- case falcon_level5_sa_algo:
- *sigAlgo = FALCON_LEVEL5k;
+#ifndef NO_PSK
+ case psk_kea:
+ keaStr = "PSK";
break;
- case dilithium_level2_sa_algo:
- *sigAlgo = DILITHIUM_LEVEL2k;
+ #ifndef NO_DH
+ case dhe_psk_kea:
+ keaStr = "DHEPSK";
break;
- case dilithium_level3_sa_algo:
- *sigAlgo = DILITHIUM_LEVEL3k;
+ #endif
+ #ifdef HAVE_ECC
+ case ecdhe_psk_kea:
+ keaStr = "ECDHEPSK";
break;
- case dilithium_level5_sa_algo:
- *sigAlgo = DILITHIUM_LEVEL5k;
+ #endif
+#endif
+#ifdef HAVE_ECC
+ case ecc_diffie_hellman_kea:
+ keaStr = "ECDHE";
break;
- case sm2_sa_algo:
- *sigAlgo = SM2k;
+ case ecc_static_diffie_hellman_kea:
+ keaStr = "ECDH";
+ break;
+#endif
+ case any_kea:
+ keaStr = "any";
break;
- case invalid_sa_algo:
default:
- *hashAlgo = WC_HASH_TYPE_NONE;
- *sigAlgo = 0;
- return BAD_FUNC_ARG;
- }
+ keaStr = "unknown";
+ break;
+ }
- /* 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;
+ return keaStr;
+}
+
+static WC_INLINE const char* wolfssl_sigalg_to_string(int sig_algo)
+{
+ const char* authStr;
+
+ switch (sig_algo) {
+ case anonymous_sa_algo:
+ authStr = "None";
break;
- case md5_mac:
- *hashAlgo = WC_HASH_TYPE_MD5;
+#ifndef NO_RSA
+ case rsa_sa_algo:
+ authStr = "RSA";
break;
- case sha_mac:
- *hashAlgo = WC_HASH_TYPE_SHA;
+ #ifdef WC_RSA_PSS
+ case rsa_pss_sa_algo:
+ authStr = "RSA-PSS";
break;
- case sha224_mac:
- *hashAlgo = WC_HASH_TYPE_SHA224;
+ #endif
+#endif
+#ifndef NO_DSA
+ case dsa_sa_algo:
+ authStr = "DSA";
break;
- case sha256_mac:
- *hashAlgo = WC_HASH_TYPE_SHA256;
+#endif
+#ifdef HAVE_ECC
+ case ecc_dsa_sa_algo:
+ authStr = "ECDSA";
break;
- case sha384_mac:
- *hashAlgo = WC_HASH_TYPE_SHA384;
+#endif
+#ifdef WOLFSSL_SM2
+ case sm2_sa_algo:
+ authStr = "SM2";
break;
- case sha512_mac:
- *hashAlgo = WC_HASH_TYPE_SHA512;
+#endif
+#ifdef HAVE_ED25519
+ case ed25519_sa_algo:
+ authStr = "Ed25519";
break;
- case blake2b_mac:
- *hashAlgo = WC_HASH_TYPE_BLAKE2B;
+#endif
+#ifdef HAVE_ED448
+ case ed448_sa_algo:
+ authStr = "Ed448";
break;
- case sm3_mac:
-#ifdef WOLFSSL_SM3
- *hashAlgo = WC_HASH_TYPE_SM3;
-#else
- *hashAlgo = WC_HASH_TYPE_NONE;
#endif
+ case any_sa_algo:
+ authStr = "any";
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;
+ authStr = "unknown";
+ break;
}
- #endif /* OPENSSL_EXTRA */
-#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */
+ return authStr;
+}
-#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");
+static WC_INLINE const char* wolfssl_cipher_to_string(int cipher, int key_size)
+{
+ const char* encStr;
- if (ctx == NULL) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get_client_CA_list");
- return NULL;
- }
+ (void)key_size;
- return ctx->client_ca_names;
+ 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 == AES_128_KEY_SIZE)
+ encStr = "AES(128)";
+ else if (key_size == AES_256_KEY_SIZE)
+ encStr = "AES(256)";
+ else
+ encStr = "AES(?)";
+ break;
+ #ifdef HAVE_AESGCM
+ case wolfssl_aes_gcm:
+ if (key_size == AES_128_KEY_SIZE)
+ encStr = "AESGCM(128)";
+ else if (key_size == AES_256_KEY_SIZE)
+ encStr = "AESGCM(256)";
+ else
+ encStr = "AESGCM(?)";
+ break;
+ #endif
+ #ifdef HAVE_AESCCM
+ case wolfssl_aes_ccm:
+ if (key_size == AES_128_KEY_SIZE)
+ encStr = "AESCCM(128)";
+ else if (key_size == AES_256_KEY_SIZE)
+ 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 == ARIA_128_KEY_SIZE)
+ encStr = "Aria(128)";
+ else if (key_size == ARIA_192_KEY_SIZE)
+ encStr = "Aria(192)";
+ else if (key_size == ARIA_256_KEY_SIZE)
+ encStr = "Aria(256)";
+ else
+ encStr = "Aria(?)";
+ break;
+#endif
+#ifdef HAVE_CAMELLIA
+ case wolfssl_camellia:
+ if (key_size == CAMELLIA_128_KEY_SIZE)
+ encStr = "Camellia(128)";
+ else if (key_size == CAMELLIA_256_KEY_SIZE)
+ encStr = "Camellia(256)";
+ else
+ encStr = "Camellia(?)";
+ break;
+#endif
+ default:
+ encStr = "unknown";
+ break;
}
- /* returns the CA's set on server side or the CA's sent from server when
- * on client side */
- WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(
- const WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_get_client_CA_list");
+ return encStr;
+}
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list");
- return NULL;
- }
+static WC_INLINE const char* wolfssl_mac_to_string(int mac)
+{
+ const char* macStr;
- return SSL_CA_NAMES(ssl);
+ 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 WOLFSSL_SHA224
+ case sha224_mac:
+ macStr = "SHA224";
+ break;
+#endif
+#ifndef NO_SHA256
+ case sha256_mac:
+ macStr = "SHA256";
+ break;
+#endif
+#ifdef WOLFSSL_SHA384
+ case sha384_mac:
+ macStr = "SHA384";
+ break;
+#endif
+#ifdef WOLFSSL_SHA512
+ case sha512_mac:
+ macStr = "SHA512";
+ break;
+#endif
+ default:
+ macStr = "unknown";
+ break;
}
- #if !defined(NO_CERTS)
- int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
- {
- WOLFSSL_X509_NAME *nameCopy = NULL;
+ return macStr;
+}
- WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
+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 (ctx == NULL || x509 == NULL){
- WOLFSSL_MSG("Bad argument");
- return WOLFSSL_FAILURE;
- }
+ if (cipher == NULL || in == NULL)
+ return NULL;
- 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;
- }
- }
+#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,(size_t)len);
+ return ret;
+ }
+#endif
- nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509));
- if (nameCopy == NULL) {
- WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
- return WOLFSSL_FAILURE;
- }
+ /* 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);
+ if (cipher->ssl->specs.cipher_type == aead)
+ macStr = "AEAD";
+ else
+ macStr = wolfssl_mac_to_string(cipher->ssl->specs.mac_algorithm);
- 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;
- }
+ /* Build up the string by copying onto the end. */
+ XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- return WOLFSSL_SUCCESS;
- }
- #endif
+ XSTRNCPY(in, " ", (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- #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;
+ XSTRNCPY(in, " Kx=", (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, keaStr, (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- WOLFSSL_ENTER("wolfSSL_load_client_CA_file");
+ XSTRNCPY(in, " Au=", (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, authStr, (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- bio = wolfSSL_BIO_new_file(fname, "rb");
- if (bio == NULL) {
- WOLFSSL_MSG("wolfSSL_BIO_new_file error");
- goto cleanup;
- }
+ XSTRNCPY(in, " Enc=", (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, encStr, (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- list = wolfSSL_sk_X509_NAME_new(NULL);
- if (list == NULL) {
- WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
- goto cleanup;
- }
+ XSTRNCPY(in, " Mac=", (size_t)len);
+ in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
+ XSTRNCPY(in, macStr, (size_t)len);
+ in[len-1] = '\0';
- /* 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;
+ return ret;
+}
- 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;
- }
+int wolfSSL_OCSP_parse_url(const char* url, char** host, char** port,
+ char** path, int* ssl)
+{
+ const char* u = url;
+ const char* upath; /* path in u */
+ const char* uport; /* port in u */
+ const char* hostEnd;
- wolfSSL_X509_free(cert);
- cert = NULL;
- }
+ WOLFSSL_ENTER("OCSP_parse_url");
- CLEAR_ASN_NO_PEM_HEADER_ERROR(err);
+ *host = NULL;
+ *port = NULL;
+ *path = NULL;
+ *ssl = 0;
- err = WOLFSSL_SUCCESS;
-cleanup:
- wolfSSL_X509_free(cert);
- wolfSSL_BIO_free(bio);
- if (err != WOLFSSL_SUCCESS) {
- /* We failed so return NULL */
- wolfSSL_sk_X509_NAME_pop_free(list, NULL);
- list = NULL;
- }
- return list;
- #else
- (void)fname;
- return NULL;
- #endif
- }
- #endif
- #endif /* !NO_BIO */
-#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */
+ if (*(u++) != 'h') goto err;
+ if (*(u++) != 't') goto err;
+ if (*(u++) != 't') goto err;
+ if (*(u++) != 'p') goto err;
+ if (*u == 's') {
+ *ssl = 1;
+ u++;
+ *port = CopyString("443", -1, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ else if (*u == ':') {
+ *ssl = 0;
+ *port = CopyString("80", -1, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ else
+ goto err;
+ if (*port == NULL)
+ goto err;
+ if (*(u++) != ':') goto err;
+ if (*(u++) != '/') goto err;
+ if (*(u++) != '/') goto err;
+
+ /* Look for path */
+ upath = XSTRSTR(u, "/");
+ *path = CopyString(upath == NULL ? "/" : upath, -1, NULL,
+ DYNAMIC_TYPE_OPENSSL);
+
+ /* Look for port */
+ uport = XSTRSTR(u, ":");
+ if (uport != NULL) {
+ if (*(++uport) == '\0')
+ goto err;
+ /* port must be before path */
+ if (upath != NULL && uport >= upath)
+ goto err;
+ XFREE(*port, NULL, DYNAMIC_TYPE_OPENSSL);
+ *port = CopyString(uport, upath != NULL ? (int)(upath - uport) : -1,
+ NULL, DYNAMIC_TYPE_OPENSSL);
+ if (*port == NULL)
+ goto err;
+ hostEnd = uport - 1;
+ }
+ else
+ hostEnd = upath;
-#ifdef OPENSSL_EXTRA
+ *host = CopyString(u, hostEnd != NULL ? (int)(hostEnd - u) : -1, NULL,
+ DYNAMIC_TYPE_OPENSSL);
+ if (*host == NULL)
+ goto err;
- #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
+ return WOLFSSL_SUCCESS;
+err:
+ XFREE(*host, NULL, DYNAMIC_TYPE_OPENSSL);
+ *host = NULL;
+ XFREE(*port, NULL, DYNAMIC_TYPE_OPENSSL);
+ *port = NULL;
+ XFREE(*path, NULL, DYNAMIC_TYPE_OPENSSL);
+ *path = NULL;
+ return WOLFSSL_FAILURE;
+}
- WOLFSSL_ENTER("wolfSSL_CTX_set_default_verify_paths");
+#ifndef NO_WOLFSSL_STUB
+WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void)
+{
+ WOLFSSL_STUB("COMP_zlib");
+ return 0;
+}
-#ifdef XGETENV
- certDir = XGETENV("SSL_CERT_DIR");
- certFile = XGETENV("SSL_CERT_FILE");
- flags = WOLFSSL_LOAD_FLAG_PEM_CA_ONLY;
+WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void)
+{
+ WOLFSSL_STUB("COMP_rle");
+ return 0;
+}
- 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;
- }
+int wolfSSL_COMP_add_compression_method(int method, void* data)
+{
+ (void)method;
+ (void)data;
+ WOLFSSL_STUB("COMP_add_compression_method");
+ return 0;
+}
- ret = wolfSSL_CTX_load_verify_locations_ex(ctx, certFile, certDir,
- flags);
- if (ret != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG_EX("Failed to load CA certs from SSL_CERT_FILE: %s"
- " SSL_CERT_DIR: %s. Error: %d", certFile,
- certDir, ret);
- return WOLFSSL_FAILURE;
- }
- return ret;
- }
-#endif
+const WOLFSSL_COMP_METHOD* wolfSSL_get_current_compression(const WOLFSSL *ssl) {
+ (void)ssl;
+ return NULL;
+}
-#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;
- }
+const WOLFSSL_COMP_METHOD* wolfSSL_get_current_expansion(const WOLFSSL *ssl) {
+ (void)ssl;
+ return NULL;
+}
+
+const char* wolfSSL_COMP_get_name(const WOLFSSL_COMP_METHOD *comp)
+{
+ static const char ret[] = "not supported";
+
+ (void)comp;
+ WOLFSSL_STUB("wolfSSL_COMP_get_name");
+ return ret;
+}
#endif
- WOLFSSL_LEAVE("wolfSSL_CTX_set_default_verify_paths", ret);
+/* 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;
+}
- 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
- };
+#endif /* OPENSSL_EXTRA */
- 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];
+#ifdef OPENSSL_EXTRA
+#ifndef NO_CERTS
- WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username");
- if (ctx == NULL || ctx->srp == NULL || username==NULL)
- return WOLFSSL_FAILURE;
+#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 (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;
- }
+int wolfSSL_i2d_PrivateKey_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key)
+{
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ int derSz = 0;
+ byte* der = 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;
- }
+ if (bio == NULL || key == NULL) {
+ return WOLFSSL_FAILURE;
+ }
- /* if wolfSSL_CTX_set_srp_password has already been called, */
- /* execute wc_SrpSetPassword here */
- if (ctx->srp_password != NULL) {
- WC_RNG rng;
- if (wc_InitRng(&rng) < 0){
- WOLFSSL_MSG("wc_InitRng failed");
- return WOLFSSL_FAILURE;
- }
- XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
- r = wc_RNG_GenerateBlock(&rng, salt, sizeof(salt)/sizeof(salt[0]));
- wc_FreeRng(&rng);
- if (r < 0) {
- WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
- return WOLFSSL_FAILURE;
- }
+ derSz = wolfSSL_i2d_PrivateKey(key, NULL);
+ if (derSz <= 0) {
+ WOLFSSL_MSG("wolfSSL_i2d_PrivateKey (for getting size) 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;
- }
+ der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (!der) {
+ WOLFSSL_MSG("malloc failed");
+ return WOLFSSL_FAILURE;
+ }
- XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
- ctx->srp_password = NULL;
- }
+ derSz = wolfSSL_i2d_PrivateKey(key, &der);
+ if (derSz <= 0) {
+ WOLFSSL_MSG("wolfSSL_i2d_PrivateKey failed");
+ goto cleanup;
+ }
- return WOLFSSL_SUCCESS;
+ if (wolfSSL_BIO_write(bio, der, derSz) != derSz) {
+ goto cleanup;
}
- int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password)
- {
- int r;
- byte salt[SRP_SALT_SIZE];
+ ret = WOLFSSL_SUCCESS;
- WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password");
- if (ctx == NULL || ctx->srp == NULL || password == NULL)
- return WOLFSSL_FAILURE;
+cleanup:
+ XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
- 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);
+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;
- 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 (key == NULL) {
+ return WOLFSSL_FATAL_ERROR;
}
- /**
- * 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;
- }
-
- char* wolfSSL_get_srp_username(WOLFSSL *ssl)
- {
- if (ssl && ssl->ctx && ssl->ctx->srp) {
- return (char*) ssl->ctx->srp->user;
- }
- return NULL;
+ key_type = key->type;
+ if ((key_type != WC_EVP_PKEY_EC) && (key_type != WC_EVP_PKEY_RSA)) {
+ return WOLFSSL_FATAL_ERROR;
}
- #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 2 * (ssl->specs.key_size + ssl->specs.iv_size +
- ssl->specs.hash_size);
+#ifndef NO_RSA
+ if (key_type == WC_EVP_PKEY_RSA) {
+ return wolfSSL_i2d_RSAPublicKey(key->rsa, der);
}
+#endif
-#endif /* OPENSSL_EXTRA */
+ /* Now that RSA is taken care of, we only need to consider the ECC case. */
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+#ifdef HAVE_ECC
- /* 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;
+ /* We need to get the DER, then convert it to a public key. But what we get
+ * might be a buffered private key so we need to decode it and then encode
+ * the public part. */
+ ret = wolfSSL_EVP_PKEY_get_der(key, &local_der);
+ if (ret <= 0) {
+ /* In this case, there was no buffered DER at all. This could be the
+ * case where the key that was passed in was generated. So now we
+ * have to create the local DER. */
+ local_derSz = (word32)wolfSSL_i2d_ECPrivateKey(key->ecc, &local_der);
+ if (local_derSz == 0) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ } else {
+ local_derSz = (word32)ret;
+ ret = 0;
+ }
- *ms = ssl->arrays->masterSecret;
- *sr = ssl->arrays->serverRandom;
- *cr = ssl->arrays->clientRandom;
+ 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;
+ }
+ }
- *msLen = SECRET_LEN;
- *srLen = RAN_LEN;
- *crLen = RAN_LEN;
+ if (ret == 0) {
+ ret = wc_ecc_init(eccKey);
+ }
- return WOLFSSL_SUCCESS;
+ 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);
+ }
}
- void wolfSSL_set_accept_state(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_set_accept_state");
+ if (ret == 0) {
+ pub_derSz = (word32)wc_EccPublicKeyDerSize(eccKey, 1);
+ if ((int)pub_derSz <= 0) {
+ ret = WOLFSSL_FAILURE;
+ }
+ }
- if (ssl == NULL)
- return;
+ if (ret == 0) {
+ pub_der = (unsigned char*)XMALLOC(pub_derSz, NULL,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (pub_der == NULL) {
+ WOLFSSL_MSG("Failed to allocate output buffer.");
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
- if (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;
+ if (ret == 0) {
+ pub_derSz = (word32)wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 1);
+ if ((int)pub_derSz <= 0) {
+ ret = WOLFSSL_FATAL_ERROR;
+ }
+ }
- #ifdef WOLFSSL_SMALL_STACK
- key = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap,
- DYNAMIC_TYPE_ECC);
- if (key == NULL) {
- WOLFSSL_MSG("Error allocating memory for ecc_key");
- }
- #endif
- 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);
- }
+ /* 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;
}
- #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;
+ if (ret == 0) {
+ XMEMCPY(*der, pub_der, pub_derSz);
}
- #endif
}
-
- if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error initializing server side");
+ else {
+ XMEMCPY(*der, pub_der, pub_derSz);
+ *der += pub_derSz;
}
}
-#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+ XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(local_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
- /* return true if connection established */
- int wolfSSL_is_init_finished(const WOLFSSL* ssl)
- {
- if (ssl == NULL)
- return 0;
+ wc_ecc_free(eccKey);
+ XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC);
- /* 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;
+#else
+ ret = WOLFSSL_FATAL_ERROR;
+#endif /* HAVE_ECC */
- return 0;
+ if (ret == 0) {
+ return (int)pub_derSz;
}
+ return ret;
+#else
+ return WOLFSSL_FATAL_ERROR;
+#endif /* !NO_RSA || HAVE_ECC */
+}
+#endif /* !NO_ASN && !NO_PWDBASED */
+
+#endif /* !NO_CERTS */
+#endif /* OPENSSL_EXTRA */
+
#ifdef OPENSSL_EXTRA
- void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx,
- WOLFSSL_RSA*(*f)(WOLFSSL*, int, int))
- {
- /* wolfSSL verifies all these internally */
- (void)ctx;
- (void)f;
+
+/* 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;
}
+ return wolfSSL_X509_VERIFY_PARAM_set1_host(ssl->param, name, 0);
+}
- 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;
- }
+/******************************************************************************
+* 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;
- ssl->options.sentNotify = (opt&WOLFSSL_SENT_SHUTDOWN) > 0;
- ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0;
- }
-#endif
+ return wolfSSL_X509_VERIFY_PARAM_set1(ctx->param, vpm);
+}
- 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;
+/******************************************************************************
+* 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;
}
- /* forward declaration */
- static long wolf_set_options(long old_op, long op);
+ return ctx->param;
+}
- long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_options");
+WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl)
+{
+ if (ssl == NULL) {
+ return NULL;
+ }
+ return ssl->param;
+}
- if (ctx == NULL)
- return BAD_FUNC_ARG;
+#endif /* OPENSSL_EXTRA */
- 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 defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
+/* Gets an index to store SSL structure at.
+ *
+ * Returns positive index on success and negative values on failure
+ */
+int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void)
+{
+ WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx");
- 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;
- }
+ /* store SSL at index 0 */
+ return 0;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
#ifdef OPENSSL_EXTRA
-
- int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd)
- {
- WOLFSSL_ENTER("wolfSSL_set_rfd");
- ssl->rfd = rfd; /* not used directly to allow IO callbacks */
-
- ssl->IOCB_ReadCtx = &ssl->rfd;
-
- #ifdef WOLFSSL_DTLS
- if (ssl->options.dtls) {
- ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
- ssl->buffers.dtlsCtx.rfd = rfd;
- }
- #endif
-
- return WOLFSSL_SUCCESS;
+/* Sets a function callback that will send information about the state of all
+ * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed
+ * in.
+ *
+ * ctx WOLFSSL_CTX structure to set callback function in
+ * f callback function to use
+ */
+void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx,
+ void (*f)(const WOLFSSL* ssl, int type, int val))
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback");
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Bad function argument");
}
-
-
- 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;
+ else {
+ ctx->CBIS = f;
}
-#endif /* OPENSSL_EXTRA */
-
-#if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL))
-
-#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
- /**
- * Implemented in a similar way that ngx_ssl_ocsp_validate does it when
- * SSL_get0_verified_chain is not available.
- * @param ssl WOLFSSL object to extract certs from
- * @return Stack of verified certs
- */
- WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl)
- {
- WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL;
- WOLFSSL_X509_STORE_CTX* storeCtx = NULL;
- WOLFSSL_X509* peerCert = NULL;
-
- WOLFSSL_ENTER("wolfSSL_get0_verified_chain");
-
- if (ssl == NULL || ssl->ctx == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return NULL;
- }
+}
- peerCert = wolfSSL_get_peer_certificate((WOLFSSL*)ssl);
- if (peerCert == NULL) {
- WOLFSSL_MSG("wolfSSL_get_peer_certificate error");
- return NULL;
- }
- /* wolfSSL_get_peer_certificate returns a copy. We want the internal
- * member so that we don't have to worry about free'ing it. We call
- * wolfSSL_get_peer_certificate so that we don't have to worry about
- * setting up the internal pointer. */
- wolfSSL_X509_free(peerCert);
- peerCert = (WOLFSSL_X509*)&ssl->peerCert;
- chain = wolfSSL_get_peer_cert_chain(ssl);
- if (chain == NULL) {
- WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error");
- return NULL;
- }
- storeCtx = wolfSSL_X509_STORE_CTX_new();
- if (storeCtx == NULL) {
- WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_new error");
- return NULL;
- }
- if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl),
- peerCert, chain) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init error");
- wolfSSL_X509_STORE_CTX_free(storeCtx);
- return NULL;
- }
- if (wolfSSL_X509_verify_cert(storeCtx) <= 0) {
- WOLFSSL_MSG("wolfSSL_X509_verify_cert error");
- wolfSSL_X509_STORE_CTX_free(storeCtx);
- return NULL;
- }
- wolfSSL_X509_STORE_CTX_free(storeCtx);
- return chain;
+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");
}
-#endif /* SESSION_CERTS && OPENSSL_EXTRA */
-
- WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx)
- {
- if (ctx == NULL) {
- return NULL;
- }
-
- if (ctx->x509_store_pt != NULL)
- return ctx->x509_store_pt;
- return &ctx->x509_store;
+ else {
+ ssl->CBIS = f;
}
+}
- void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store");
- if (ctx == NULL || str == NULL || ctx->cm == str->cm) {
- return;
- }
-
- if (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;
-
- /* free existing store if it exists */
- wolfSSL_X509_STORE_free(ctx->x509_store_pt);
- ctx->x509_store.cache = str->cache;
- ctx->x509_store_pt = str; /* take ownership of store and free it
- with CTX free */
- ctx->cm->x509_store_p = ctx->x509_store_pt;/* CTX has ownership
- and free it with CTX free*/
- }
-#ifdef OPENSSL_ALL
- int wolfSSL_CTX_set1_verify_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_CTX_set1_verify_cert_store");
+unsigned long wolfSSL_ERR_peek_error(void)
+{
+ WOLFSSL_ENTER("wolfSSL_ERR_peek_error");
- if (ctx == NULL || str == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
+ return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL);
+}
- /* NO-OP when setting existing store */
- if (str == CTX_STORE(ctx))
- return WOLFSSL_SUCCESS;
+#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES_H
+#include
+#endif
- if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
- return WOLFSSL_FAILURE;
- }
+int wolfSSL_ERR_GET_LIB(unsigned long err)
+{
+ unsigned long value;
- /* 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;
+ value = (err & 0xFFFFFFL);
+ switch (value) {
+ case -PARSE_ERROR:
+ return WOLFSSL_ERR_LIB_SSL;
+ case -ASN_NO_PEM_HEADER:
+ case -WOLFSSL_PEM_R_NO_START_LINE_E:
+ case -WOLFSSL_PEM_R_PROBLEMS_GETTING_PASSWORD_E:
+ case -WOLFSSL_PEM_R_BAD_PASSWORD_READ_E:
+ case -WOLFSSL_PEM_R_BAD_DECRYPT_E:
+ return WOLFSSL_ERR_LIB_PEM;
+ case -WOLFSSL_EVP_R_BAD_DECRYPT_E:
+ case -WOLFSSL_EVP_R_BN_DECODE_ERROR:
+ case -WOLFSSL_EVP_R_DECODE_ERROR:
+ case -WOLFSSL_EVP_R_PRIVATE_KEY_DECODE_ERROR:
+ return WOLFSSL_ERR_LIB_EVP;
+ case -WOLFSSL_ASN1_R_HEADER_TOO_LONG_E:
+ return WOLFSSL_ERR_LIB_ASN1;
+ default:
+ return 0;
}
+}
+
+#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES
+#include
#endif
- int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store");
+/* This function is to find global error values that are the same through out
+ * all library version. With wolfSSL having only one set of error codes the
+ * return value is pretty straight forward. The only thing needed is all wolfSSL
+ * error values are typically negative.
+ *
+ * Returns the error reason
+ */
+int wolfSSL_ERR_GET_REASON(unsigned long err)
+{
+ int ret = (int)err;
- if (ssl == NULL || str == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
+ WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON");
- /* NO-OP when setting existing store */
- if (str == SSL_STORE(ssl))
- return WOLFSSL_SUCCESS;
+#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) == -WC_NO_ERR_TRACE(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
- /* 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;
+ /* check if error value is in range of wolfCrypt or wolfSSL errors */
+ ret = 0 - ret; /* setting as negative value */
+
+ if ((ret <= WC_SPAN1_FIRST_E && ret >= WC_SPAN1_LAST_E) ||
+ (ret <= WC_SPAN2_FIRST_E && ret >= WC_SPAN2_LAST_E) ||
+ (ret <= WOLFSSL_FIRST_E && ret >= WOLFSSL_LAST_E))
+ {
+ return ret;
+ }
+ else {
+ WOLFSSL_MSG("Not in range of typical error values");
+ ret = (int)err;
}
+ return ret;
+}
- int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
- {
- WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store");
+#ifndef NO_TLS
+/* 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");
- if (ssl == NULL || str == NULL) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
+ return AlertTypeToString(alertID);
+}
- /* NO-OP when setting existing store */
- if (str == SSL_STORE(ssl))
- return WOLFSSL_SUCCESS;
+const char* wolfSSL_alert_desc_string_long(int alertID)
+{
+ WOLFSSL_ENTER("wolfSSL_alert_desc_string_long");
- if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
- return WOLFSSL_FAILURE;
- }
+ return AlertTypeToString(alertID);
+}
+#endif /* !NO_TLS */
- /* 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;
+#define STATE_STRINGS_PROTO(s) \
+ { \
+ {"SSLv3 " s, \
+ "SSLv3 " s, \
+ "SSLv3 " s}, \
+ {"TLSv1 " s, \
+ "TLSv1 " s, \
+ "TLSv1 " s}, \
+ {"TLSv1_1 " s, \
+ "TLSv1_1 " s, \
+ "TLSv1_1 " s}, \
+ {"TLSv1_2 " s, \
+ "TLSv1_2 " s, \
+ "TLSv1_2 " s}, \
+ {"TLSv1_3 " s, \
+ "TLSv1_3 " s, \
+ "TLSv1_3 " s}, \
+ {"DTLSv1 " s, \
+ "DTLSv1 " s, \
+ "DTLSv1 " s}, \
+ {"DTLSv1_2 " s, \
+ "DTLSv1_2 " s, \
+ "DTLSv1_2 " s}, \
+ {"DTLSv1_3 " s, \
+ "DTLSv1_3 " s, \
+ "DTLSv1_3 " s}, \
}
-#endif /* !NO_CERTS && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */
-
-#ifdef WOLFSSL_ENCRYPTED_KEYS
- 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;
+#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}, \
}
+/* 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_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;
- }
-
- wc_pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx)
- {
- if (ctx == NULL || ctx->passwd_cb == NULL) {
- return NULL;
- }
+ 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
+ };
- return ctx->passwd_cb;
- }
+ enum IOMode {
+ SS_READ = 0,
+ SS_WRITE,
+ SS_NEITHER
+ };
+ 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
+ };
- void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx)
- {
- if (ctx == NULL) {
- return NULL;
- }
+ int protocol = 0;
+ int cbmode = 0;
+ int state = 0;
- return ctx->passwd_userdata;
+ WOLFSSL_ENTER("wolfSSL_state_string_long");
+ if (ssl == NULL) {
+ WOLFSSL_MSG("Null argument passed in");
+ return NULL;
}
-#endif /* WOLFSSL_ENCRYPTED_KEYS */
-
-
-#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
+ /* Get state of callback */
+ if (ssl->cbmode == WOLFSSL_CB_MODE_WRITE) {
+ cbmode = SS_WRITE;
}
-#endif
-
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
-
- int wolfSSL_num_locks(void)
- {
- return 0;
+ else if (ssl->cbmode == WOLFSSL_CB_MODE_READ) {
+ cbmode = SS_READ;
}
-
- void wolfSSL_set_locking_callback(mutex_cb* f)
- {
- WOLFSSL_ENTER("wolfSSL_set_locking_callback");
-
- if (wc_SetMutexCb(f) != 0) {
- WOLFSSL_MSG("Error when setting mutex call back");
- }
+ else {
+ cbmode = SS_NEITHER;
}
- mutex_cb* wolfSSL_get_locking_callback(void)
- {
- WOLFSSL_ENTER("wolfSSL_get_locking_callback");
-
- return wc_GetMutexCb();
+ /* Get protocol version */
+ switch (ssl->version.major) {
+ case SSLv3_MAJOR:
+ switch (ssl->version.minor) {
+ case SSLv3_MINOR:
+ protocol = SSL_V3;
+ break;
+ case TLSv1_MINOR:
+ protocol = TLS_V1;
+ break;
+ case TLSv1_1_MINOR:
+ protocol = TLS_V1_1;
+ break;
+ case TLSv1_2_MINOR:
+ protocol = TLS_V1_2;
+ break;
+ case TLSv1_3_MINOR:
+ protocol = TLS_V1_3;
+ break;
+ default:
+ protocol = UNKNOWN;
+ }
+ break;
+ case DTLS_MAJOR:
+ switch (ssl->version.minor) {
+ case DTLS_MINOR:
+ protocol = DTLS_V1;
+ break;
+ case DTLSv1_2_MINOR:
+ protocol = DTLS_V1_2;
+ break;
+ case DTLSv1_3_MINOR:
+ protocol = DTLS_V1_3;
+ break;
+ default:
+ protocol = UNKNOWN;
+ }
+ break;
+ default:
+ protocol = UNKNOWN;
}
-
- typedef unsigned long (idCb)(void);
- static idCb* inner_idCb = NULL;
-
- unsigned long wolfSSL_thread_id(void)
- {
- if (inner_idCb != NULL) {
- return inner_idCb();
- }
- else {
- return 0;
+ /* accept process */
+ if (ssl->cbmode == WOLFSSL_CB_MODE_READ) {
+ state = ssl->cbtype;
+ switch (state) {
+ case hello_request:
+ state = ss_server_hellorequest;
+ break;
+ case client_hello:
+ state = ss_client_hello;
+ break;
+ case server_hello:
+ state = ss_server_hello;
+ break;
+ case hello_verify_request:
+ state = ss_server_helloverify;
+ break;
+ case session_ticket:
+ state = ss_server_sessionticket;
+ break;
+ case end_of_early_data:
+ state = ss_client_endofearlydata;
+ break;
+ case hello_retry_request:
+ state = ss_server_helloretryrequest;
+ break;
+ case encrypted_extensions:
+ state = ss_server_encryptedextensions;
+ break;
+ case certificate:
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ state = ss_client_cert;
+ else if (ssl->options.side == WOLFSSL_CLIENT_END)
+ state = ss_server_cert;
+ else {
+ WOLFSSL_MSG("Unknown State");
+ state = ss_null_state;
+ }
+ break;
+ case server_key_exchange:
+ state = ss_server_keyexchange;
+ break;
+ case certificate_request:
+ state = ss_server_certrequest;
+ break;
+ case server_hello_done:
+ state = ss_server_hellodone;
+ break;
+ case certificate_verify:
+ state = ss_client_certverify;
+ break;
+ case client_key_exchange:
+ state = ss_client_keyexchange;
+ break;
+ case finished:
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ state = ss_client_finished;
+ else if (ssl->options.side == WOLFSSL_CLIENT_END)
+ state = ss_server_finished;
+ else {
+ WOLFSSL_MSG("Unknown State");
+ state = ss_null_state;
+ }
+ break;
+ case certificate_status:
+ state = ss_server_certificatestatus;
+ break;
+ case key_update:
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ state = ss_client_keyupdate;
+ else if (ssl->options.side == WOLFSSL_CLIENT_END)
+ state = ss_server_keyupdate;
+ else {
+ WOLFSSL_MSG("Unknown State");
+ state = ss_null_state;
+ }
+ break;
+ case change_cipher_hs:
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ state = ss_client_changecipherspec;
+ else if (ssl->options.side == WOLFSSL_CLIENT_END)
+ state = ss_server_changecipherspec;
+ else {
+ WOLFSSL_MSG("Unknown State");
+ state = ss_null_state;
+ }
+ break;
+ default:
+ WOLFSSL_MSG("Unknown State");
+ state = ss_null_state;
}
}
+ else {
+ /* Send process */
+ if (ssl->options.side == WOLFSSL_SERVER_END)
+ state = ssl->options.serverState;
+ else
+ state = ssl->options.clientState;
+ switch (state) {
+ case SERVER_HELLOVERIFYREQUEST_COMPLETE:
+ state = ss_server_helloverify;
+ break;
+ case SERVER_HELLO_RETRY_REQUEST_COMPLETE:
+ state = ss_server_helloretryrequest;
+ break;
+ case SERVER_HELLO_COMPLETE:
+ state = ss_server_hello;
+ break;
+ case SERVER_ENCRYPTED_EXTENSIONS_COMPLETE:
+ state = ss_server_encryptedextensions;
+ break;
+ case SERVER_CERT_COMPLETE:
+ state = ss_server_cert;
+ break;
+ case SERVER_KEYEXCHANGE_COMPLETE:
+ state = ss_server_keyexchange;
+ break;
+ case SERVER_HELLODONE_COMPLETE:
+ state = ss_server_hellodone;
+ break;
+ case SERVER_CHANGECIPHERSPEC_COMPLETE:
+ state = ss_server_changecipherspec;
+ break;
+ case SERVER_FINISHED_COMPLETE:
+ state = ss_server_finished;
+ break;
+ case CLIENT_HELLO_RETRY:
+ case CLIENT_HELLO_COMPLETE:
+ state = ss_client_hello;
+ break;
+ case CLIENT_KEYEXCHANGE_COMPLETE:
+ state = ss_client_keyexchange;
+ break;
+ case CLIENT_CHANGECIPHERSPEC_COMPLETE:
+ state = ss_client_changecipherspec;
+ break;
+ case CLIENT_FINISHED_COMPLETE:
+ state = ss_client_finished;
+ break;
+ case HANDSHAKE_DONE:
+ state = ss_handshake_done;
+ break;
+ default:
+ WOLFSSL_MSG("Unknown State");
+ state = ss_null_state;
+ }
+ }
- void wolfSSL_set_id_callback(unsigned long (*f)(void))
- {
- inner_idCb = f;
+ if (protocol == UNKNOWN) {
+ WOLFSSL_MSG("Unknown protocol");
+ return "";
+ }
+ else {
+ return OUTPUT_STR[state][protocol][cbmode];
}
+}
-#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];
+#endif /* OPENSSL_EXTRA */
- WOLFSSL_ENTER("wolfSSL_ERR_print_errors");
+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");
+ }
- if (bio == NULL) {
- WOLFSSL_MSG("BIO passed in was null");
- return;
- }
+ /* 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");
+ }
- do {
- ret = wc_PeekErrorNode(0, &file, &reason, &line);
- if (ret >= 0) {
- const char* r = wolfSSL_ERR_reason_error_string(0 - ret);
- if (XSNPRINTF(buf, sizeof(buf),
- "error:%d:wolfSSL library:%s:%s:%d\n",
- ret, r, file, line)
- >= (int)sizeof(buf))
- {
- WOLFSSL_MSG("Buffer overrun formatting error message");
- }
- wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf));
- wc_RemoveErrorNode(0);
- }
- } while (ret >= 0);
- if (wolfSSL_BIO_write(bio, "", 1) != 1) {
- WOLFSSL_MSG("Issue writing final string terminator");
- }
+ if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) {
+ WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2");
}
-#endif /* !NO_BIO */
-#endif /* WOLFSSL_HAVE_ERROR_QUEUE */
-#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */
+#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 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;
+ if ((op & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) {
+ WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2");
+ }
- /* return max size of buffer */
- if (outSz == 0) {
- return RAN_LEN;
+ if ((op & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) {
+ WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1");
}
- if (ssl == NULL || out == NULL) {
- return 0;
+ if ((op & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) {
+ WOLFSSL_MSG("\tSSL_OP_NO_TLSv1");
}
- if (ssl->arrays == NULL) {
- WOLFSSL_MSG("Arrays struct not saved after handshake");
- return 0;
+ if ((op & WOLFSSL_OP_NO_SSLv3) == WOLFSSL_OP_NO_SSLv3) {
+ WOLFSSL_MSG("\tSSL_OP_NO_SSLv3");
}
- if (outSz > RAN_LEN) {
- size = RAN_LEN;
+ if ((op & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) ==
+ WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) {
+ WOLFSSL_MSG("\tWOLFSSL_OP_CIPHER_SERVER_PREFERENCE");
}
- else {
- size = outSz;
+
+ 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
}
- XMEMCPY(out, ssl->arrays->serverRandom, size);
- return size;
+ return old_op | op;
}
-#endif /* !NO_WOLFSSL_SERVER */
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */
-#ifdef OPENSSL_EXTRA
-#if !defined(NO_WOLFSSL_SERVER)
-/* Used to get the peer ephemeral public key sent during the connection
- * NOTE: currently wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) must be called
- * before the ephemeral key is stored.
- * return WOLFSSL_SUCCESS on success */
-int wolfSSL_get_peer_tmp_key(const WOLFSSL* ssl, WOLFSSL_EVP_PKEY** pkey)
+static int FindHashSig(const Suites* suites, byte first, byte second)
{
- WOLFSSL_EVP_PKEY* ret = NULL;
+ word16 i;
- WOLFSSL_ENTER("wolfSSL_get_server_tmp_key");
+ if (suites == NULL || suites->hashSigAlgoSz == 0) {
+ WOLFSSL_MSG("Suites pointer error or suiteSz 0");
+ return SUITES_ERROR;
+ }
- if (ssl == NULL || pkey == NULL) {
- WOLFSSL_MSG("Bad argument passed in");
- return WOLFSSL_FAILURE;
+ for (i = 0; i < suites->hashSigAlgoSz-1; i += 2) {
+ if (suites->hashSigAlgo[i] == first &&
+ suites->hashSigAlgo[i+1] == second )
+ return i;
}
-#ifdef HAVE_ECC
- if (ssl->peerEccKey != NULL) {
- unsigned char* der;
- const unsigned char* pt;
- unsigned int derSz = 0;
- int sz;
+ return MATCH_SUITE_ERROR;
+}
- 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();
+long wolfSSL_set_options(WOLFSSL* ssl, long op)
+{
+ word16 haveRSA = 1;
+ word16 havePSK = 0;
+ int keySz = 0;
- 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;
- }
+ WOLFSSL_ENTER("wolfSSL_set_options");
- 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);
+ if (ssl == NULL) {
+ return 0;
+ }
+
+ ssl->options.mask = (unsigned long)wolf_set_options((long)ssl->options.mask, op);
+
+ if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3) == WOLFSSL_OP_NO_TLSv1_3) {
+ WOLFSSL_MSG("Disabling TLS 1.3");
+ if (ssl->version.minor == TLSv1_3_MINOR)
+ ssl->version.minor = TLSv1_2_MINOR;
+ }
+
+ if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) {
+ WOLFSSL_MSG("Disabling TLS 1.2");
+ if (ssl->version.minor == TLSv1_2_MINOR)
+ ssl->version.minor = TLSv1_1_MINOR;
+ }
+
+ if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) {
+ WOLFSSL_MSG("Disabling TLS 1.1");
+ if (ssl->version.minor == TLSv1_1_MINOR)
+ ssl->version.minor = TLSv1_MINOR;
+ }
+
+ if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) {
+ WOLFSSL_MSG("Disabling TLS 1.0");
+ if (ssl->version.minor == TLSv1_MINOR)
+ ssl->version.minor = SSLv3_MINOR;
+ }
+
+ if ((ssl->options.mask & WOLFSSL_OP_NO_COMPRESSION)
+ == WOLFSSL_OP_NO_COMPRESSION) {
+ #ifdef HAVE_LIBZ
+ ssl->options.usingCompression = 0;
+ #endif
+ }
+
+#if defined(HAVE_SESSION_TICKET) && (defined(OPENSSL_EXTRA) \
+ || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL))
+ if ((ssl->options.mask & WOLFSSL_OP_NO_TICKET) == WOLFSSL_OP_NO_TICKET) {
+ ssl->options.noTicketTls12 = 1;
}
#endif
- *pkey = ret;
-#ifdef HAVE_ECC
- if (ret != NULL)
- return WOLFSSL_SUCCESS;
- else
+
+ /* in the case of a version change the cipher suites should be reset */
+#ifndef NO_PSK
+ havePSK = ssl->options.havePSK;
+#endif
+#ifdef NO_RSA
+ haveRSA = 0;
+#endif
+#ifndef NO_CERTS
+ keySz = ssl->buffers.keySz;
#endif
+
+ if (ssl->options.side != WOLFSSL_NEITHER_END) {
+ if (AllocateSuites(ssl) != 0)
+ return 0;
+ if (!ssl->suites->setSuites) {
+ InitSuites(ssl->suites, ssl->version, keySz, haveRSA,
+ havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig,
+ ssl->options.haveECC, TRUE, ssl->options.haveStaticECC,
+ ssl->options.useAnon,
+ TRUE, TRUE, TRUE, TRUE, ssl->options.side);
+ }
+ else {
+ /* Only preserve overlapping suites */
+ Suites tmpSuites;
+ word16 in, out;
+ word16 haveECDSAsig, haveStaticECC;
+#ifdef NO_RSA
+ haveECDSAsig = 1;
+ haveStaticECC = 1;
+#else
+ haveECDSAsig = 0;
+ haveStaticECC = ssl->options.haveStaticECC;
+#endif
+ XMEMSET(&tmpSuites, 0, sizeof(Suites));
+ /* Get all possible ciphers and sigalgs for the version. Following
+ * options limit the allowed ciphers so let's try to get as many as
+ * possible.
+ * - haveStaticECC turns off haveRSA
+ * - haveECDSAsig turns off haveRSAsig */
+ InitSuites(&tmpSuites, ssl->version, 0, 1, 1, 1, haveECDSAsig, 1, 1,
+ haveStaticECC, 1, 1, 1, 1, 1, ssl->options.side);
+ for (in = 0, out = 0; in < ssl->suites->suiteSz; in += SUITE_LEN) {
+ if (FindSuite(&tmpSuites, ssl->suites->suites[in],
+ ssl->suites->suites[in+1]) >= 0) {
+ ssl->suites->suites[out] = ssl->suites->suites[in];
+ ssl->suites->suites[out+1] = ssl->suites->suites[in+1];
+ out += SUITE_LEN;
+ }
+ }
+ ssl->suites->suiteSz = out;
+ for (in = 0, out = 0; in < ssl->suites->hashSigAlgoSz; in += 2) {
+ if (FindHashSig(&tmpSuites, ssl->suites->hashSigAlgo[in],
+ ssl->suites->hashSigAlgo[in+1]) >= 0) {
+ ssl->suites->hashSigAlgo[out] =
+ ssl->suites->hashSigAlgo[in];
+ ssl->suites->hashSigAlgo[out+1] =
+ ssl->suites->hashSigAlgo[in+1];
+ out += 2;
+ }
+ }
+ ssl->suites->hashSigAlgoSz = out;
+ }
+ }
+
+ return (long)ssl->options.mask;
+}
+
+
+long wolfSSL_get_options(const WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_options");
+ if(ssl == NULL)
return WOLFSSL_FAILURE;
+ return (long)ssl->options.mask;
}
-#endif /* !NO_WOLFSSL_SERVER */
+#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;
-/**
- * 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_ENTER("wolfSSL_clear_num_renegotiations");
+ if (s == NULL)
+ return 0;
+
+ total = s->secure_rene_count;
+ s->secure_rene_count = 0;
+ return total;
+}
+
+
+/* return the number of renegotiations since wolfSSL_new */
+long wolfSSL_total_renegotiations(WOLFSSL *s)
{
- int sanityConfirmed = 0;
+ WOLFSSL_ENTER("wolfSSL_total_renegotiations");
+ return wolfSSL_num_renegotiations(s);
+}
- (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;
+/* return the number of renegotiations since wolfSSL_new */
+long wolfSSL_num_renegotiations(WOLFSSL* s)
+{
+ if (s == NULL) {
+ return 0;
}
- return WOLFSSL_SUCCESS;
+
+ return s->secure_rene_count;
}
-/**
- * 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))
-/**
- * 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)
+/* Is there a renegotiation currently in progress? */
+int wolfSSL_SSL_renegotiate_pending(WOLFSSL *s)
{
- WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version_ex");
+ return s && s->options.handShakeDone &&
+ s->options.handShakeState != HANDSHAKE_DONE ? 1 : 0;
+}
+#endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */
- if (ctx == NULL) {
+#ifdef OPENSSL_EXTRA
+
+long wolfSSL_clear_options(WOLFSSL* ssl, long opt)
+{
+ WOLFSSL_ENTER("wolfSSL_clear_options");
+ if(ssl == NULL)
return WOLFSSL_FAILURE;
- }
+ ssl->options.mask &= (unsigned long)~opt;
+ return (long)ssl->options.mask;
+}
- 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");
+#ifdef HAVE_PK_CALLBACKS
+long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
+{
+ if (ssl == NULL) {
return WOLFSSL_FAILURE;
}
- return CheckSslMethodVersion(ctx->method->version.major, ctx->mask);
+ ssl->loggingCtx = arg;
+ return WOLFSSL_SUCCESS;
}
+#endif /* HAVE_PK_CALLBACKS */
-/* 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 HAVE_CERTIFICATE_STATUS_REQUEST
+long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
{
- int ret;
- int proto = 0;
- int maxProto = 0;
- int i;
- int idx = 0;
+ WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type");
- WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version");
+ if (s == NULL){
+ return BAD_FUNC_ARG;
+ }
- if (ctx == NULL) {
+ if (type == WOLFSSL_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;
}
- 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;
- }
- }
- }
- 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;
- }
- }
- }
- /* 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;
- }
- }
- 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;
+long wolfSSL_get_tlsext_status_type(WOLFSSL *s)
+{
+ TLSX* extension;
+
+ if (s == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ extension = TLSX_Find(s->extensions, TLSX_STATUS_REQUEST);
+ return extension != NULL ? WOLFSSL_TLSEXT_STATUSTYPE_ocsp : WOLFSSL_FATAL_ERROR;
}
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
-/**
- * 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)
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg)
{
- int ret;
- WOLFSSL_ENTER("Set_CTX_max_proto_version");
+ (void)s;
+ (void)arg;
+ WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts");
+ return WOLFSSL_FAILURE;
+}
+#endif
- if (!ctx || !ctx->method) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
- }
+/*** 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
- 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;
+/*** 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
-#ifdef WOLFSSL_DTLS
- case DTLS1_VERSION:
- case DTLS1_2_VERSION:
- break;
+
+/*** TBD ***/
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg)
+{
+ (void)s;
+ (void)arg;
+ WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids");
+ return WOLFSSL_FAILURE;
+}
#endif
- 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 ret;
+#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 WOLFSSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx,
+ WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength))
+{
+ (void)ctx;
+ (void)dh;
+ WOLFSSL_STUB("WOLFSSL_CTX_set_tmp_dh_callback");
+}
+#endif
-/* 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)
+#ifndef NO_WOLFSSL_STUB
+/*** TBD ***/
+WOLF_STACK_OF(WOLFSSL_COMP) *WOLFSSL_COMP_get_compression_methods(void)
{
- int i;
- int ret = WOLFSSL_FAILURE;
- int minProto;
+ WOLFSSL_STUB("WOLFSSL_COMP_get_compression_methods");
+ return NULL;
+}
+#endif
- WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version");
- if (ctx == NULL) {
- return ret;
- }
+#if !defined(NETOS)
+void wolfSSL_ERR_load_SSL_strings(void)
+{
- /* 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
- /* 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;
- }
- }
+#ifdef HAVE_MAX_FRAGMENT
+#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
+/**
+ * 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 ret;
+ 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;
+
+ return wolfSSL_UseMaxFragment(s, mode);
}
+#endif /* !NO_WOLFSSL_CLIENT && !NO_TLS */
+#endif /* HAVE_MAX_FRAGMENT */
+#endif /* OPENSSL_EXTRA */
-static int Set_SSL_min_proto_version(WOLFSSL* ssl, int ver)
+#ifdef WOLFSSL_HAVE_TLS_UNIQUE
+size_t wolfSSL_get_finished(const WOLFSSL *ssl, void *buf, size_t count)
{
- WOLFSSL_ENTER("Set_SSL_min_proto_version");
+ byte len = 0;
- if (ssl == NULL) {
+ WOLFSSL_ENTER("wolfSSL_get_finished");
+
+ if (!ssl || !buf || count < TLS_FINISHED_SZ) {
+ WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
- 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;
+ if (ssl->options.side == WOLFSSL_SERVER_END) {
+ len = ssl->serverFinished_len;
+ XMEMCPY(buf, ssl->serverFinished, len);
}
-
- 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;
+ else {
+ len = ssl->clientFinished_len;
+ XMEMCPY(buf, ssl->clientFinished, len);
}
-
- return CheckSslMethodVersion(ssl->version.major, ssl->options.mask);
+ return len;
}
-int wolfSSL_set_min_proto_version(WOLFSSL* ssl, int version)
+size_t wolfSSL_get_peer_finished(const WOLFSSL *ssl, void *buf, size_t count)
{
- int i;
- int ret = WOLFSSL_FAILURE;;
-
- WOLFSSL_ENTER("wolfSSL_set_min_proto_version");
+ byte len = 0;
+ WOLFSSL_ENTER("wolfSSL_get_peer_finished");
- if (ssl == NULL) {
+ if (!ssl || !buf || count < TLS_FINISHED_SZ) {
+ WOLFSSL_MSG("Bad parameter");
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;
+ 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);
}
- return ret;
+ return len;
}
+#endif /* WOLFSSL_HAVE_TLS_UNIQUE */
-static int Set_SSL_max_proto_version(WOLFSSL* ssl, int ver)
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
+ defined(OPENSSL_ALL)
+long wolfSSL_get_verify_result(const WOLFSSL *ssl)
{
-
- WOLFSSL_ENTER("Set_SSL_max_proto_version");
-
- if (!ssl) {
- WOLFSSL_MSG("Bad parameter");
+ if (ssl == NULL) {
return WOLFSSL_FAILURE;
}
- 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;
+ return (long)ssl->peerVerifyRet;
+}
#endif
- default:
- WOLFSSL_MSG("Unrecognized protocol version or not compiled in");
- return WOLFSSL_FAILURE;
- }
- return CheckSslMethodVersion(ssl->version.major, ssl->options.mask);
+#ifdef OPENSSL_EXTRA
+
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of accepts attempted by CTX in it's lifetime */
+long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_accept");
+ (void)ctx;
+ return 0;
}
+#endif
-int wolfSSL_set_max_proto_version(WOLFSSL* ssl, int version)
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of connects attempted CTX in it's lifetime */
+long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx)
{
- int i;
- int ret = WOLFSSL_FAILURE;;
+ WOLFSSL_STUB("wolfSSL_CTX_sess_connect");
+ (void)ctx;
+ return 0;
+}
+#endif
- WOLFSSL_ENTER("wolfSSL_set_max_proto_version");
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
- if (version != 0) {
- return Set_SSL_max_proto_version(ssl, version);
- }
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of accepts completed by CTX in it's lifetime */
+long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good");
+ (void)ctx;
+ return 0;
+}
+#endif
- /* 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;
- }
- return ret;
+#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
-static int GetMinProtoVersion(int minDowngrade)
-{
- int ret;
- switch (minDowngrade) {
-#ifndef NO_OLD_TLS
- #ifdef WOLFSSL_ALLOW_SSLV3
- case SSLv3_MINOR:
- ret = SSL3_VERSION;
- break;
- #endif
- #ifdef WOLFSSL_ALLOW_TLSV10
- case TLSv1_MINOR:
- ret = TLS1_VERSION;
- break;
- #endif
- case TLSv1_1_MINOR:
- ret = TLS1_1_VERSION;
- break;
-#endif
-#ifndef WOLFSSL_NO_TLS12
- case TLSv1_2_MINOR:
- ret = TLS1_2_VERSION;
- break;
-#endif
-#ifdef WOLFSSL_TLS13
- case TLSv1_3_MINOR:
- ret = TLS1_3_VERSION;
- break;
+#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
- default:
- ret = 0;
- break;
- }
- return ret;
-}
-int wolfSSL_CTX_get_min_proto_version(WOLFSSL_CTX* ctx)
+#ifndef NO_WOLFSSL_STUB
+/* shows the number of renegotiation accepts attempted by CTX */
+long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx)
{
- int ret = 0;
+ WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate");
+ (void)ctx;
+ return 0;
+}
+#endif
- WOLFSSL_ENTER("wolfSSL_CTX_get_min_proto_version");
- if (ctx != NULL) {
- if (ctx->minProto) {
- ret = 0;
- }
- else {
- ret = GetMinProtoVersion(ctx->minDowngrade);
- }
- }
- else {
- ret = GetMinProtoVersion(WOLFSSL_MIN_DOWNGRADE);
- }
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_hits");
+ (void)ctx;
+ return 0;
+}
+#endif
- WOLFSSL_LEAVE("wolfSSL_CTX_get_min_proto_version", ret);
- return ret;
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits");
+ (void)ctx;
+ return 0;
}
+#endif
-/* returns the maximum allowed protocol version given the 'options' used
- * returns WOLFSSL_FATAL_ERROR on no match */
-static int GetMaxProtoVersion(long options)
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx)
{
-#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_STUB("wolfSSL_CTX_sess_cache_full");
+ (void)ctx;
+ return 0;
}
+#endif
-/* returns the maximum protocol version for 'ctx' */
-int wolfSSL_CTX_get_max_proto_version(WOLFSSL_CTX* ctx)
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx)
{
- int ret = 0;
- long options = 0; /* default to nothing set */
+ WOLFSSL_STUB("wolfSSL_CTX_sess_misses");
+ (void)ctx;
+ return 0;
+}
+#endif
- WOLFSSL_ENTER("wolfSSL_CTX_get_max_proto_version");
- if (ctx != NULL) {
- options = wolfSSL_CTX_get_options(ctx);
- }
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx)
+{
+ WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts");
+ (void)ctx;
+ return 0;
+}
+#endif
- if ((ctx != NULL) && ctx->maxProto) {
- ret = 0;
- }
- else {
- ret = GetMaxProtoVersion(options);
+int wolfSSL_get_read_ahead(const WOLFSSL* ssl)
+{
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
}
- WOLFSSL_LEAVE("wolfSSL_CTX_get_max_proto_version", ret);
+ return ssl->readAhead;
+}
- if (ret == WOLFSSL_FATAL_ERROR) {
- WOLFSSL_MSG("Error getting max proto version");
- ret = 0; /* setting ret to 0 to match compat return */
+
+int wolfSSL_set_read_ahead(WOLFSSL* ssl, int v)
+{
+ if (ssl == NULL) {
+ return WOLFSSL_FAILURE;
}
- return ret;
+
+ ssl->readAhead = (byte)v;
+
+ return WOLFSSL_SUCCESS;
}
-#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)
-{
- size_t size;
- /* return max size of buffer */
- if (outSz == 0) {
- return RAN_LEN;
+int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx)
+{
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
}
- if (ssl == NULL || out == NULL) {
- return 0;
- }
+ return ctx->readAhead;
+}
- if (ssl->arrays == NULL) {
- WOLFSSL_MSG("Arrays struct not saved after handshake");
- return 0;
- }
- if (outSz > RAN_LEN) {
- size = RAN_LEN;
- }
- else {
- size = outSz;
+int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v)
+{
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
}
- XMEMCPY(out, ssl->arrays->clientRandom, size);
- return size;
+ ctx->readAhead = (byte)v;
+
+ return WOLFSSL_SUCCESS;
}
-#endif /* !NO_WOLFSSL_CLIENT */
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */
-#ifdef OPENSSL_EXTRA
- unsigned long wolfSSLeay(void)
- {
- return SSLEAY_VERSION_NUMBER;
+long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx,
+ void* arg)
+{
+ if (ctx == NULL) {
+ return WOLFSSL_FAILURE;
}
- unsigned long wolfSSL_OpenSSL_version_num(void)
- {
- return OPENSSL_VERSION_NUMBER;
- }
+ ctx->userPRFArg = arg;
+ return WOLFSSL_SUCCESS;
+}
- const char* wolfSSLeay_version(int type)
- {
- (void)type;
-#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
- return wolfSSL_OpenSSL_version(type);
-#else
- return wolfSSL_OpenSSL_version();
-#endif
- }
#endif /* OPENSSL_EXTRA */
-#ifdef OPENSSL_EXTRA
- void wolfSSL_ERR_free_strings(void)
- {
- /* handled internally */
- }
-
- void wolfSSL_cleanup_all_ex_data(void)
- {
- /* nothing to do here */
- }
-
-#endif /* OPENSSL_EXTRA */
+#if defined(OPENSSL_EXTRA) && defined(KEEP_PEER_CERT) && \
+ defined(HAVE_EX_DATA) && !defined(NO_FILESYSTEM)
+int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname)
+{
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
-#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) || \
- defined(HAVE_CURL)
- void wolfSSL_ERR_clear_error(void)
+ WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file");
+ if (ssl != NULL && fname != NULL)
{
- WOLFSSL_ENTER("wolfSSL_ERR_clear_error");
- #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
- wc_ClearErrorNodes();
+ #ifdef WOLFSSL_SMALL_STACK
+ byte staticBuffer[1]; /* force heap usage */
+ #else
+ byte staticBuffer[FILE_BUFFER_SIZE];
#endif
- }
-#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 defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
- int wolfSSL_clear(WOLFSSL* ssl)
- {
- WOLFSSL_ENTER("wolfSSL_clear");
+ file = XFOPEN(fname, "rb");
+ if (file == XBADFILE)
+ return WOLFSSL_BAD_FILE;
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
+ if (XFSEEK(file, 0, XSEEK_END) != 0) {
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
}
-
- 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;
- }
+ sz = XFTELL(file);
+ if (XFSEEK(file, 0, XSEEK_SET) != 0) {
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
}
- /* reset error */
- ssl->error = 0;
-
- /* reset option bits */
- ssl->options.isClosed = 0;
- ssl->options.connReset = 0;
- ssl->options.sentNotify = 0;
- ssl->options.closeNotify = 0;
- ssl->options.sendVerify = 0;
- ssl->options.serverState = NULL_STATE;
- ssl->options.clientState = NULL_STATE;
- ssl->options.connectState = CONNECT_BEGIN;
- ssl->options.acceptState = ACCEPT_BEGIN;
- ssl->options.handShakeState = NULL_STATE;
- ssl->options.handShakeDone = 0;
- ssl->options.processReply = 0; /* doProcessInit */
- ssl->options.havePeerVerify = 0;
- ssl->options.havePeerCert = 0;
- ssl->options.peerAuthGood = 0;
- ssl->options.tls1_3 = 0;
- ssl->options.haveSessionId = 0;
- ssl->options.tls = 0;
- ssl->options.tls1_1 = 0;
- #ifdef WOLFSSL_DTLS
- ssl->options.dtlsStateful = 0;
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- ssl->options.noPskDheKe = 0;
- #ifdef HAVE_SUPPORTED_CURVES
- ssl->options.onlyPskDheKe = 0;
- #endif
- #endif
- #ifdef HAVE_SESSION_TICKET
- #ifdef WOLFSSL_TLS13
- ssl->options.ticketsSent = 0;
- #endif
- ssl->options.rejectTicket = 0;
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- ssl->earlyData = no_early_data;
- ssl->earlyDataSz = 0;
- #endif
-
- #if defined(HAVE_TLS_EXTENSIONS) && !defined(NO_TLS)
- TLSX_FreeAll(ssl->extensions, ssl->heap);
- ssl->extensions = NULL;
- #endif
-
- if (ssl->keys.encryptionOn) {
- ForceZero(ssl->buffers.inputBuffer.buffer -
- ssl->buffers.inputBuffer.offset,
- ssl->buffers.inputBuffer.bufferSize);
- #ifdef WOLFSSL_CHECK_MEM_ZERO
- wc_MemZero_Check(ssl->buffers.inputBuffer.buffer -
- ssl->buffers.inputBuffer.offset,
- ssl->buffers.inputBuffer.bufferSize);
- #endif
+ if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
+ WOLFSSL_MSG("cmp_peer_cert_to_file size error");
+ XFCLOSE(file);
+ return WOLFSSL_BAD_FILE;
}
- ssl->keys.encryptionOn = 0;
- XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
- if (InitSSL_Suites(ssl) != WOLFSSL_SUCCESS)
- return WOLFSSL_FAILURE;
+ if (sz > (long)sizeof(staticBuffer)) {
+ WOLFSSL_MSG("Getting dynamic buffer");
+ myBuffer = (byte*)XMALLOC((size_t)sz, ctx->heap, DYNAMIC_TYPE_FILE);
+ dynamic = 1;
+ }
- if (InitHandshakeHashes(ssl) != 0)
- return WOLFSSL_FAILURE;
+ if ((myBuffer != NULL) &&
+ (sz > 0) &&
+ (XFREAD(myBuffer, 1, (size_t)sz, file) == (size_t)sz) &&
+ (PemToDer(myBuffer, (long)sz, CERT_TYPE,
+ &fileDer, ctx->heap, NULL, NULL) == 0) &&
+ (fileDer->length != 0) &&
+ (fileDer->length == peer_cert->derCert->length) &&
+ (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer,
+ fileDer->length) == 0))
+ {
+ ret = 0;
+ }
-#ifdef KEEP_PEER_CERT
- FreeX509(&ssl->peerCert);
- InitX509(&ssl->peerCert, 0, ssl->heap);
-#endif
+ FreeDer(&fileDer);
-#ifdef WOLFSSL_QUIC
- wolfSSL_quic_clear(ssl);
-#endif
+ if (dynamic)
+ XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
- return WOLFSSL_SUCCESS;
+ XFCLOSE(file);
}
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+ return ret;
+}
+#endif
-#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_MEMCACHED)
- long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode)
- {
- /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+const WOLFSSL_ObjectInfo wolfssl_object_info[] = {
+#ifndef NO_CERTS
+ /* oidCertExtType */
+ { WC_NID_basic_constraints, BASIC_CA_OID, oidCertExtType,
+ "basicConstraints", "X509v3 Basic Constraints"},
+ { WC_NID_subject_alt_name, ALT_NAMES_OID, oidCertExtType, "subjectAltName",
+ "X509v3 Subject Alternative Name"},
+ { WC_NID_crl_distribution_points, CRL_DIST_OID, oidCertExtType,
+ "crlDistributionPoints", "X509v3 CRL Distribution Points"},
+ { WC_NID_info_access, AUTH_INFO_OID, oidCertExtType, "authorityInfoAccess",
+ "Authority Information Access"},
+ { WC_NID_authority_key_identifier, AUTH_KEY_OID, oidCertExtType,
+ "authorityKeyIdentifier", "X509v3 Authority Key Identifier"},
+ { WC_NID_subject_key_identifier, SUBJ_KEY_OID, oidCertExtType,
+ "subjectKeyIdentifier", "X509v3 Subject Key Identifier"},
+ { WC_NID_key_usage, KEY_USAGE_OID, oidCertExtType, "keyUsage",
+ "X509v3 Key Usage"},
+ { WC_NID_inhibit_any_policy, INHIBIT_ANY_OID, oidCertExtType,
+ "inhibitAnyPolicy", "X509v3 Inhibit Any Policy"},
+ { WC_NID_ext_key_usage, EXT_KEY_USAGE_OID, oidCertExtType,
+ "extendedKeyUsage", "X509v3 Extended Key Usage"},
+ { WC_NID_name_constraints, NAME_CONS_OID, oidCertExtType,
+ "nameConstraints", "X509v3 Name Constraints"},
+ { WC_NID_certificate_policies, CERT_POLICY_OID, oidCertExtType,
+ "certificatePolicies", "X509v3 Certificate Policies"},
- 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");
- }
+ /* oidCertAuthInfoType */
+ { WC_NID_ad_OCSP, AIA_OCSP_OID, oidCertAuthInfoType, "OCSP",
+ "OCSP"},
+ { WC_NID_ad_ca_issuers, AIA_CA_ISSUER_OID, oidCertAuthInfoType,
+ "caIssuers", "CA Issuers"},
- /* SSL_MODE_AUTO_RETRY
- * Should not return -1 with renegotiation on read/write */
+ /* oidCertPolicyType */
+ { WC_NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy",
+ "X509v3 Any Policy"},
- return mode;
- }
+ /* oidCertAltNameType */
+ { WC_NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""},
- long wolfSSL_CTX_clear_mode(WOLFSSL_CTX* ctx, long mode)
- {
- /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */
+ /* oidCertKeyUseType */
+ { WC_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"},
- 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");
- }
+ /* oidCertNameType */
+ { WC_NID_commonName, WC_NAME_COMMON_NAME_OID, oidCertNameType,
+ "CN", "commonName"},
+#if !defined(WOLFSSL_CERT_REQ)
+ { WC_NID_surname, WC_NAME_SURNAME_OID, oidCertNameType, "SN", "surname"},
+#endif
+ { WC_NID_serialNumber, WC_NAME_SERIAL_NUMBER_OID, oidCertNameType,
+ "serialNumber", "serialNumber"},
+ { WC_NID_userId, WC_NID_userId, oidCertNameType, "UID", "userid"},
+ { WC_NID_countryName, WC_NAME_COUNTRY_NAME_OID, oidCertNameType,
+ "C", "countryName"},
+ { WC_NID_localityName, WC_NAME_LOCALITY_NAME_OID, oidCertNameType,
+ "L", "localityName"},
+ { WC_NID_stateOrProvinceName, WC_NAME_STATE_NAME_OID, oidCertNameType,
+ "ST", "stateOrProvinceName"},
+ { WC_NID_streetAddress, WC_NAME_STREET_ADDRESS_OID, oidCertNameType,
+ "street", "streetAddress"},
+ { WC_NID_organizationName, WC_NAME_ORGANIZATION_NAME_OID, oidCertNameType,
+ "O", "organizationName"},
+ { WC_NID_organizationalUnitName, WC_NAME_ORGANIZATION_UNIT_NAME_OID,
+ oidCertNameType, "OU", "organizationalUnitName"},
+ { WC_NID_title, WC_NAME_TITLE_OID, oidCertNameType, "title", "title"},
+ { WC_NID_description, WC_NAME_DESCRIPTION_OID, oidCertNameType,
+ "description", "description"},
+ { WC_NID_emailAddress, WC_NAME_EMAIL_ADDRESS_OID, oidCertNameType,
+ "emailAddress", "emailAddress"},
+ { WC_NID_domainComponent, WC_NAME_DOMAIN_COMPONENT_OID, oidCertNameType,
+ "DC", "domainComponent"},
+ { WC_NID_rfc822Mailbox, WC_NAME_RFC822_MAILBOX_OID, oidCertNameType,
+ "rfc822Mailbox", "rfc822Mailbox"},
+ { WC_NID_favouriteDrink, WC_NAME_FAVOURITE_DRINK_OID, oidCertNameType,
+ "favouriteDrink", "favouriteDrink"},
+ { WC_NID_businessCategory, WC_NAME_BUSINESS_CATEGORY_OID, oidCertNameType,
+ "businessCategory", "businessCategory"},
+ { WC_NID_jurisdictionCountryName, WC_NAME_JURIS_COUNTRY_OID,
+ oidCertNameType, "jurisdictionC", "jurisdictionCountryName"},
+ { WC_NID_jurisdictionStateOrProvinceName, WC_NAME_JURIS_STATE_PROV_OID,
+ oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"},
+ { WC_NID_postalCode, WC_NAME_POSTAL_CODE_OID, oidCertNameType, "postalCode",
+ "postalCode"},
+ { WC_NID_userId, WC_NAME_USER_ID_OID, oidCertNameType, "UID", "userId"},
+ { WC_NID_netscape_cert_type, NETSCAPE_CT_OID, oidCertNameType,
+ "nsCertType", "Netscape Cert Type"},
- /* SSL_MODE_AUTO_RETRY
- * Should not return -1 with renegotiation on read/write */
-
- return 0;
- }
+#if defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_NAME_ALL)
+ { WC_NID_pkcs9_challengePassword, CHALLENGE_PASSWORD_OID,
+ oidCsrAttrType, "challengePassword", "challengePassword"},
+ { WC_NID_pkcs9_contentType, PKCS9_CONTENT_TYPE_OID,
+ oidCsrAttrType, "contentType", "contentType" },
+ { WC_NID_pkcs9_unstructuredName, UNSTRUCTURED_NAME_OID,
+ oidCsrAttrType, "unstructuredName", "unstructuredName" },
+ { WC_NID_name, WC_NAME_NAME_OID, oidCsrAttrType, "name", "name" },
+ { WC_NID_surname, SURNAME_OID,
+ oidCsrAttrType, "surname", "surname" },
+ { WC_NID_givenName, WC_NAME_GIVEN_NAME_OID,
+ oidCsrAttrType, "givenName", "givenName" },
+ { WC_NID_initials, WC_NAME_INITIALIS_OID,
+ oidCsrAttrType, "initials", "initials" },
+ { WC_NID_dnQualifier, DNQUALIFIER_OID,
+ oidCsrAttrType, "dnQualifer", "dnQualifier" },
#endif
+#endif
+#ifdef OPENSSL_EXTRA /* OPENSSL_EXTRA_X509_SMALL only needs the above */
+ /* oidHashType */
+ #ifdef WOLFSSL_MD2
+ { WC_NID_md2, MD2h, oidHashType, "MD2", "md2"},
+ #endif
+ #ifndef NO_MD4
+ { WC_NID_md4, MD4h, oidHashType, "MD4", "md4"},
+ #endif
+ #ifndef NO_MD5
+ { WC_NID_md5, MD5h, oidHashType, "MD5", "md5"},
+ #endif
+ #ifndef NO_SHA
+ { WC_NID_sha1, SHAh, oidHashType, "SHA1", "sha1"},
+ #endif
+ #ifdef WOLFSSL_SHA224
+ { WC_NID_sha224, SHA224h, oidHashType, "SHA224", "sha224"},
+ #endif
+ #ifndef NO_SHA256
+ { WC_NID_sha256, SHA256h, oidHashType, "SHA256", "sha256"},
+ #endif
+ #ifdef WOLFSSL_SHA384
+ { WC_NID_sha384, SHA384h, oidHashType, "SHA384", "sha384"},
+ #endif
+ #ifdef WOLFSSL_SHA512
+ { WC_NID_sha512, SHA512h, oidHashType, "SHA512", "sha512"},
+ #endif
+ #ifdef WOLFSSL_SHA3
+ #ifndef WOLFSSL_NOSHA3_224
+ { WC_NID_sha3_224, SHA3_224h, oidHashType, "SHA3-224", "sha3-224"},
+ #endif
+ #ifndef WOLFSSL_NOSHA3_256
+ { WC_NID_sha3_256, SHA3_256h, oidHashType, "SHA3-256", "sha3-256"},
+ #endif
+ #ifndef WOLFSSL_NOSHA3_384
+ { WC_NID_sha3_384, SHA3_384h, oidHashType, "SHA3-384", "sha3-384"},
+ #endif
+ #ifndef WOLFSSL_NOSHA3_512
+ { WC_NID_sha3_512, SHA3_512h, oidHashType, "SHA3-512", "sha3-512"},
+ #endif
+ #endif /* WOLFSSL_SHA3 */
+ #ifdef WOLFSSL_SM3
+ { WC_NID_sm3, SM3h, oidHashType, "SM3", "sm3"},
+ #endif
+ /* oidSigType */
+ #ifndef NO_DSA
+ #ifndef NO_SHA
+ { WC_NID_dsaWithSHA1, CTC_SHAwDSA, oidSigType,
+ "DSA-SHA1", "dsaWithSHA1"},
+ { WC_NID_dsa_with_SHA256, CTC_SHA256wDSA, oidSigType, "dsa_with_SHA256",
+ "dsa_with_SHA256"},
+ #endif
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ #ifdef WOLFSSL_MD2
+ { WC_NID_md2WithRSAEncryption, CTC_MD2wRSA, oidSigType, "RSA-MD2",
+ "md2WithRSAEncryption"},
+ #endif
+ #ifndef NO_MD5
+ { WC_NID_md5WithRSAEncryption, CTC_MD5wRSA, oidSigType, "RSA-MD5",
+ "md5WithRSAEncryption"},
+ #endif
+ #ifndef NO_SHA
+ { WC_NID_sha1WithRSAEncryption, CTC_SHAwRSA, oidSigType, "RSA-SHA1",
+ "sha1WithRSAEncryption"},
+ #endif
+ #ifdef WOLFSSL_SHA224
+ { WC_NID_sha224WithRSAEncryption, CTC_SHA224wRSA, oidSigType,
+ "RSA-SHA224", "sha224WithRSAEncryption"},
+ #endif
+ #ifndef NO_SHA256
+ { WC_NID_sha256WithRSAEncryption, CTC_SHA256wRSA, oidSigType,
+ "RSA-SHA256", "sha256WithRSAEncryption"},
+ #endif
+ #ifdef WOLFSSL_SHA384
+ { WC_NID_sha384WithRSAEncryption, CTC_SHA384wRSA, oidSigType,
+ "RSA-SHA384", "sha384WithRSAEncryption"},
+ #endif
+ #ifdef WOLFSSL_SHA512
+ { WC_NID_sha512WithRSAEncryption, CTC_SHA512wRSA, oidSigType,
+ "RSA-SHA512", "sha512WithRSAEncryption"},
+ #endif
+ #ifdef WOLFSSL_SHA3
+ #ifndef WOLFSSL_NOSHA3_224
+ { WC_NID_RSA_SHA3_224, CTC_SHA3_224wRSA, oidSigType, "RSA-SHA3-224",
+ "sha3-224WithRSAEncryption"},
+ #endif
+ #ifndef WOLFSSL_NOSHA3_256
+ { WC_NID_RSA_SHA3_256, CTC_SHA3_256wRSA, oidSigType, "RSA-SHA3-256",
+ "sha3-256WithRSAEncryption"},
+ #endif
+ #ifndef WOLFSSL_NOSHA3_384
+ { WC_NID_RSA_SHA3_384, CTC_SHA3_384wRSA, oidSigType, "RSA-SHA3-384",
+ "sha3-384WithRSAEncryption"},
+ #endif
+ #ifndef WOLFSSL_NOSHA3_512
+ { WC_NID_RSA_SHA3_512, CTC_SHA3_512wRSA, oidSigType, "RSA-SHA3-512",
+ "sha3-512WithRSAEncryption"},
+ #endif
+ #endif
+ #ifdef WC_RSA_PSS
+ { WC_NID_rsassaPss, CTC_RSASSAPSS, oidSigType,
+ "RSASSA-PSS", "rsassaPss" },
+ #endif
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ #ifndef NO_SHA
+ { WC_NID_ecdsa_with_SHA1, CTC_SHAwECDSA, oidSigType, "ecdsa-with-SHA1",
+ "shaWithECDSA"},
+ #endif
+ #ifdef WOLFSSL_SHA224
+ { WC_NID_ecdsa_with_SHA224, CTC_SHA224wECDSA, oidSigType,
+ "ecdsa-with-SHA224","sha224WithECDSA"},
+ #endif
+ #ifndef NO_SHA256
+ { WC_NID_ecdsa_with_SHA256, CTC_SHA256wECDSA, oidSigType,
+ "ecdsa-with-SHA256","sha256WithECDSA"},
+ #endif
+ #ifdef WOLFSSL_SHA384
+ { WC_NID_ecdsa_with_SHA384, CTC_SHA384wECDSA, oidSigType,
+ "ecdsa-with-SHA384","sha384WithECDSA"},
+ #endif
+ #ifdef WOLFSSL_SHA512
+ { WC_NID_ecdsa_with_SHA512, CTC_SHA512wECDSA, oidSigType,
+ "ecdsa-with-SHA512","sha512WithECDSA"},
+ #endif
+ #ifdef WOLFSSL_SHA3
+ #ifndef WOLFSSL_NOSHA3_224
+ { WC_NID_ecdsa_with_SHA3_224, CTC_SHA3_224wECDSA, oidSigType,
+ "id-ecdsa-with-SHA3-224", "ecdsa_with_SHA3-224"},
+ #endif
+ #ifndef WOLFSSL_NOSHA3_256
+ { WC_NID_ecdsa_with_SHA3_256, CTC_SHA3_256wECDSA, oidSigType,
+ "id-ecdsa-with-SHA3-256", "ecdsa_with_SHA3-256"},
+ #endif
+ #ifndef WOLFSSL_NOSHA3_384
+ { WC_NID_ecdsa_with_SHA3_384, CTC_SHA3_384wECDSA, oidSigType,
+ "id-ecdsa-with-SHA3-384", "ecdsa_with_SHA3-384"},
+ #endif
+ #ifndef WOLFSSL_NOSHA3_512
+ { WC_NID_ecdsa_with_SHA3_512, CTC_SHA3_512wECDSA, oidSigType,
+ "id-ecdsa-with-SHA3-512", "ecdsa_with_SHA3-512"},
+ #endif
+ #endif
+ #endif /* HAVE_ECC */
-#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;
- }
+ /* oidKeyType */
+ #ifndef NO_DSA
+ { WC_NID_dsa, DSAk, oidKeyType, "DSA", "dsaEncryption"},
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ { WC_NID_rsaEncryption, RSAk, oidKeyType, "rsaEncryption",
+ "rsaEncryption"},
+ #ifdef WC_RSA_PSS
+ { WC_NID_rsassaPss, RSAPSSk, oidKeyType, "RSASSA-PSS", "rsassaPss"},
+ #endif
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ { WC_NID_X9_62_id_ecPublicKey, ECDSAk, oidKeyType, "id-ecPublicKey",
+ "id-ecPublicKey"},
+ #endif /* HAVE_ECC */
+ #ifndef NO_DH
+ { WC_NID_dhKeyAgreement, DHk, oidKeyType, "dhKeyAgreement",
+ "dhKeyAgreement"},
+ #endif
+ #ifdef HAVE_ED448
+ { WC_NID_ED448, ED448k, oidKeyType, "ED448", "ED448"},
+ #endif
+ #ifdef HAVE_ED25519
+ { WC_NID_ED25519, ED25519k, oidKeyType, "ED25519", "ED25519"},
+ #endif
+ #ifdef HAVE_FALCON
+ { CTC_FALCON_LEVEL1, FALCON_LEVEL1k, oidKeyType, "Falcon Level 1",
+ "Falcon Level 1"},
+ { CTC_FALCON_LEVEL5, FALCON_LEVEL5k, oidKeyType, "Falcon Level 5",
+ "Falcon Level 5"},
+ #endif /* HAVE_FALCON */
+ #ifdef HAVE_DILITHIUM
+ #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
+ { 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 /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
+ { CTC_ML_DSA_LEVEL2, ML_DSA_LEVEL2k, oidKeyType,
+ "ML-DSA 44", "ML-DSA 44"},
+ { CTC_ML_DSA_LEVEL3, ML_DSA_LEVEL3k, oidKeyType,
+ "ML-DSA 65", "ML-DSA 65"},
+ { CTC_ML_DSA_LEVEL5, ML_DSA_LEVEL5k, oidKeyType,
+ "ML-DSA 87", "ML-DSA 87"},
+ #endif /* HAVE_DILITHIUM */
+ /* oidCurveType */
+ #ifdef HAVE_ECC
+ { WC_NID_X9_62_prime192v1, ECC_SECP192R1_OID, oidCurveType,
+ "prime192v1", "prime192v1"},
+ { WC_NID_X9_62_prime192v2, ECC_PRIME192V2_OID, oidCurveType,
+ "prime192v2", "prime192v2"},
+ { WC_NID_X9_62_prime192v3, ECC_PRIME192V3_OID, oidCurveType,
+ "prime192v3", "prime192v3"},
+
+ { WC_NID_X9_62_prime239v1, ECC_PRIME239V1_OID, oidCurveType,
+ "prime239v1", "prime239v1"},
+ { WC_NID_X9_62_prime239v2, ECC_PRIME239V2_OID, oidCurveType,
+ "prime239v2", "prime239v2"},
+ { WC_NID_X9_62_prime239v3, ECC_PRIME239V3_OID, oidCurveType,
+ "prime239v3", "prime239v3"},
+
+ { WC_NID_X9_62_prime256v1, ECC_SECP256R1_OID, oidCurveType,
+ "prime256v1", "prime256v1"},
+
+ { WC_NID_secp112r1, ECC_SECP112R1_OID, oidCurveType, "secp112r1",
+ "secp112r1"},
+ { WC_NID_secp112r2, ECC_SECP112R2_OID, oidCurveType, "secp112r2",
+ "secp112r2"},
+
+ { WC_NID_secp128r1, ECC_SECP128R1_OID, oidCurveType, "secp128r1",
+ "secp128r1"},
+ { WC_NID_secp128r2, ECC_SECP128R2_OID, oidCurveType, "secp128r2",
+ "secp128r2"},
+
+ { WC_NID_secp160r1, ECC_SECP160R1_OID, oidCurveType, "secp160r1",
+ "secp160r1"},
+ { WC_NID_secp160r2, ECC_SECP160R2_OID, oidCurveType, "secp160r2",
+ "secp160r2"},
+
+ { WC_NID_secp224r1, ECC_SECP224R1_OID, oidCurveType, "secp224r1",
+ "secp224r1"},
+ { WC_NID_secp384r1, ECC_SECP384R1_OID, oidCurveType, "secp384r1",
+ "secp384r1"},
+ { WC_NID_secp521r1, ECC_SECP521R1_OID, oidCurveType, "secp521r1",
+ "secp521r1"},
+
+ { WC_NID_secp160k1, ECC_SECP160K1_OID, oidCurveType, "secp160k1",
+ "secp160k1"},
+ { WC_NID_secp192k1, ECC_SECP192K1_OID, oidCurveType, "secp192k1",
+ "secp192k1"},
+ { WC_NID_secp224k1, ECC_SECP224K1_OID, oidCurveType, "secp224k1",
+ "secp224k1"},
+ { WC_NID_secp256k1, ECC_SECP256K1_OID, oidCurveType, "secp256k1",
+ "secp256k1"},
+
+ { WC_NID_brainpoolP160r1, ECC_BRAINPOOLP160R1_OID, oidCurveType,
+ "brainpoolP160r1", "brainpoolP160r1"},
+ { WC_NID_brainpoolP192r1, ECC_BRAINPOOLP192R1_OID, oidCurveType,
+ "brainpoolP192r1", "brainpoolP192r1"},
+ { WC_NID_brainpoolP224r1, ECC_BRAINPOOLP224R1_OID, oidCurveType,
+ "brainpoolP224r1", "brainpoolP224r1"},
+ { WC_NID_brainpoolP256r1, ECC_BRAINPOOLP256R1_OID, oidCurveType,
+ "brainpoolP256r1", "brainpoolP256r1"},
+ { WC_NID_brainpoolP320r1, ECC_BRAINPOOLP320R1_OID, oidCurveType,
+ "brainpoolP320r1", "brainpoolP320r1"},
+ { WC_NID_brainpoolP384r1, ECC_BRAINPOOLP384R1_OID, oidCurveType,
+ "brainpoolP384r1", "brainpoolP384r1"},
+ { WC_NID_brainpoolP512r1, ECC_BRAINPOOLP512R1_OID, oidCurveType,
+ "brainpoolP512r1", "brainpoolP512r1"},
+ #ifdef WOLFSSL_SM2
+ { WC_NID_sm2, ECC_SM2P256V1_OID, oidCurveType, "sm2", "sm2"},
+ #endif
+ #endif /* HAVE_ECC */
- /* 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");
+ /* 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
+ { WC_NID_des, DESb, oidBlkType, "DES-CBC", "des-cbc"},
+ { WC_NID_des3, DES3b, oidBlkType, "DES-EDE3-CBC", "des-ede3-cbc"},
+ #endif /* !NO_DES3 */
+ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+ { WC_NID_chacha20_poly1305, WC_NID_chacha20_poly1305, oidBlkType,
+ "ChaCha20-Poly1305", "chacha20-poly1305"},
+ #endif
- if (len > ID_LEN || ssl == NULL || id == NULL) {
- return WOLFSSL_FAILURE;
- }
- XMEMCPY(ssl->sessionCtx, id, len);
- ssl->sessionCtxSz = (byte)len;
+ /* oidOcspType */
+ #ifdef HAVE_OCSP
+ { WC_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_SUCCESS;
- }
-#endif
+ #ifndef NO_PWDBASED
+ /* oidKdfType */
+ { PBKDF2_OID, PBKDF2_OID, oidKdfType, "PBKDFv2", "PBKDF2"},
-#ifdef OPENSSL_EXTRA
+ /* 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
- #ifndef NO_WOLFSSL_STUB
- long wolfSSL_SSL_get_mode(WOLFSSL* ssl)
- {
- /* TODO: */
- (void)ssl;
- WOLFSSL_STUB("SSL_get_mode");
- return 0;
- }
+ /* 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_WOLFSSL_STUB
- long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx)
- {
- /* TODO: */
- (void)ctx;
- WOLFSSL_STUB("SSL_CTX_get_mode");
- return 0;
- }
+ #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" */
+ { WC_NID_id_on_dnsSRV, WOLFSSL_DNS_SRV_SUM, oidCertNameType,
+ WOLFSSL_SN_DNS_SRV, WOLFSSL_LN_DNS_SRV },
- #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");
- }
+ /* "1.3.6.1.4.1.311.20.2.3" */
+ { WC_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" */
+ { WC_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 /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
- 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
- }
+#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 */
- /* 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 */
-
- /* panic and try to clear out nodes */
- wc_ClearErrorNodes();
- }
- return (unsigned long)ret;
- #else
- (void)file;
- (void)line;
+#ifdef OPENSSL_EXTRA
- return 0;
- #endif
- }
+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);
+}
-#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";
+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;
- /* 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";
- }
+ srcLen = XSTRLEN(str);
+ targetBuf = (unsigned char*)XMALLOC(srcLen / 2, NULL, DYNAMIC_TYPE_OPENSSL);
+ if (targetBuf == NULL) {
+ return NULL;
}
-#endif /* DEBUG_WOLFSSL */
+ while (srcIdx < srcLen) {
+ if (str[srcIdx] == ':') {
+ srcIdx++;
+ continue;
+ }
- void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file,
- int line)
- {
- WOLFSSL_ENTER("wolfSSL_ERR_put_error");
+ srcDigitHigh = wolfSSL_OPENSSL_hexchar2int((unsigned char)str[srcIdx++]);
+ srcDigitLow = wolfSSL_OPENSSL_hexchar2int((unsigned char)str[srcIdx++]);
+ if (srcDigitHigh < 0 || srcDigitLow < 0) {
+ WOLFSSL_MSG("Invalid hex character.");
+ XFREE(targetBuf, NULL, DYNAMIC_TYPE_OPENSSL);
+ return NULL;
+ }
- #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;
+ targetBuf[targetIdx++] = (unsigned char)((srcDigitHigh << 4) |
+ srcDigitLow );
}
+ if (len != NULL)
+ *len = targetIdx;
- /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for
- * more flexibility.
- *
- * file output pointer to file where error happened
- * line output to line number of error
- * data output data. Is a string if ERR_TXT_STRING flag is used
- * flags output format of output
- *
- * Returns the error value or 0 if no errors are in the queue
- */
- unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line,
- const char** data, int *flags)
- {
-#ifdef WOLFSSL_HAVE_ERROR_QUEUE
- int ret;
-
- WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data");
+ return targetBuf;
+}
- if (flags != NULL)
- *flags = ERR_TXT_STRING; /* Clear the flags */
+int wolfSSL_OPENSSL_init_ssl(word64 opts, const WOLFSSL_INIT_SETTINGS *settings)
+{
+ (void)opts;
+ (void)settings;
+ return wolfSSL_library_init();
+}
- 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 */
+int wolfSSL_OPENSSL_init_crypto(word64 opts,
+ const WOLFSSL_INIT_SETTINGS* settings)
+{
+ (void)opts;
+ (void)settings;
+ return wolfSSL_library_init();
+}
- /* panic and try to clear out nodes */
- wc_ClearErrorNodes();
- }
+/* 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");
- 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 (ctx == NULL || list == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
}
-#endif /* OPENSSL_EXTRA */
-
-
-#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 (AllocateCtxSuites(ctx) != 0)
+ return WOLFSSL_FAILURE;
- #ifdef WOLFSSL_SMALL_STACK
- cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_DCERT);
- if (cert == NULL)
- return MEMORY_E;
- #endif
+ return SetSuitesHashSigAlgo(ctx->suites, list);
+}
- /* 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
+/* 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");
- return ret;
+ if (ssl == NULL || list == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
}
-#endif /* (KEEP_PEER_CERT & SESSION_CERTS) || (OPENSSL_EXTRA & SESSION_CERTS) */
+ if (AllocateSuites(ssl) != 0)
+ return WOLFSSL_FAILURE;
-#ifdef KEEP_PEER_CERT
- WOLFSSL_ABI
- WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl)
- {
- WOLFSSL_X509* ret = NULL;
- WOLFSSL_ENTER("wolfSSL_get_peer_certificate");
- if (ssl != NULL) {
- if (ssl->peerCert.issuer.sz)
- ret = wolfSSL_X509_dup(&ssl->peerCert);
-#ifdef SESSION_CERTS
- else if (ssl->session->chain.count > 0) {
- if (DecodeToX509(&ssl->peerCert,
- ssl->session->chain.certs[0].buffer,
- ssl->session->chain.certs[0].length) == 0) {
- ret = wolfSSL_X509_dup(&ssl->peerCert);
- }
- }
-#endif
- }
- WOLFSSL_LEAVE("wolfSSL_get_peer_certificate", ret != NULL);
- return ret;
- }
-
-#endif /* KEEP_PEER_CERT */
+ return SetSuitesHashSigAlgo(ssl->suites, list);
+}
-#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)
+static int HashToNid(byte hashAlgo, int* nid)
{
- WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain");
+ int ret = WOLFSSL_SUCCESS;
- if (ssl == NULL)
- return NULL;
+ /* Cast for compiler to check everything is implemented */
+ switch ((enum wc_MACAlgorithm)hashAlgo) {
+ case no_mac:
+ case rmd_mac:
+ *nid = WC_NID_undef;
+ break;
+ case md5_mac:
+ *nid = WC_NID_md5;
+ break;
+ case sha_mac:
+ *nid = WC_NID_sha1;
+ break;
+ case sha224_mac:
+ *nid = WC_NID_sha224;
+ break;
+ case sha256_mac:
+ *nid = WC_NID_sha256;
+ break;
+ case sha384_mac:
+ *nid = WC_NID_sha384;
+ break;
+ case sha512_mac:
+ *nid = WC_NID_sha512;
+ break;
+ case blake2b_mac:
+ *nid = WC_NID_blake2b512;
+ break;
+ case sm3_mac:
+ *nid = WC_NID_sm3;
+ break;
+ default:
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
- /* 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;
+ return ret;
}
-#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)
+static int SaToNid(byte sa, int* nid)
{
- 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)
+ /* Cast for compiler to check everything is implemented */
+ switch ((enum SignatureAlgorithm)sa) {
+ case anonymous_sa_algo:
+ *nid = WC_NID_undef;
+ break;
+ case rsa_sa_algo:
+ *nid = WC_NID_rsaEncryption;
+ break;
+ case dsa_sa_algo:
+ *nid = WC_NID_dsa;
+ break;
+ case ecc_dsa_sa_algo:
+ *nid = WC_NID_X9_62_id_ecPublicKey;
+ break;
+ case rsa_pss_sa_algo:
+ *nid = WC_NID_rsassaPss;
+ break;
+ case ed25519_sa_algo:
+#ifdef HAVE_ED25519
+ *nid = WC_NID_ED25519;
+#else
+ ret = WOLFSSL_FAILURE;
+#endif
+ break;
+ case rsa_pss_pss_algo:
+ *nid = WC_NID_rsassaPss;
+ break;
+ case ed448_sa_algo:
+#ifdef HAVE_ED448
+ *nid = WC_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_ML_DSA_LEVEL2;
+ break;
+ case dilithium_level3_sa_algo:
+ *nid = CTC_ML_DSA_LEVEL3;
+ break;
+ case dilithium_level5_sa_algo:
+ *nid = CTC_ML_DSA_LEVEL5;
+ break;
+ case sm2_sa_algo:
+ *nid = WC_NID_sm2;
+ break;
+ case invalid_sa_algo:
+ case any_sa_algo:
+ default:
+ ret = WOLFSSL_FAILURE;
break;
- x = issuer[i];
- }
- if (i == 0) /* No further chain found */
- return WOLFSSL_FAILURE;
- i--;
- for (; i >= 0; i--) {
- if (push) {
- if (wolfSSL_sk_X509_push(sk, issuer[i]) != WOLFSSL_SUCCESS) {
- wolfSSL_X509_free(issuer[i]);
- ret = WOLFSSL_FATAL_ERROR;
- push = 0; /* Free the rest of the unpushed certs */
- }
- }
- else {
- wolfSSL_X509_free(issuer[i]);
- }
}
return ret;
}
-#endif /* !WOLFSSL_QT */
-/* 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)
+/* This API returns the hash selected. */
+int wolfSSL_get_signature_nid(WOLFSSL *ssl, int* nid)
{
- WOLFSSL_STACK* sk;
- WOLFSSL_X509* x509;
- int i = 0;
- int ret;
-
- WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain");
- if ((ssl == NULL) || (ssl->session->chain.count == 0))
- return NULL;
-
- sk = wolfSSL_sk_X509_new_null();
- i = ssl->session->chain.count-1;
- for (; i >= 0; i--) {
- x509 = wolfSSL_X509_new_ex(ssl->heap);
- if (x509 == NULL) {
- WOLFSSL_MSG("Error Creating X509");
- wolfSSL_sk_X509_pop_free(sk, NULL);
- return NULL;
- }
- ret = DecodeToX509(x509, ssl->session->chain.certs[i].buffer,
- ssl->session->chain.certs[i].length);
-#if !defined(WOLFSSL_QT)
- if (ret == 0 && i == ssl->session->chain.count-1) {
- /* On the last element in the chain try to add the CA chain
- * first if we have one for this cert */
- SSL_CM_WARNING(ssl);
- if (PushCAx509Chain(SSL_CM(ssl), x509, sk)
- == WOLFSSL_FATAL_ERROR) {
- ret = WOLFSSL_FATAL_ERROR;
- }
- }
-#endif
+ WOLFSSL_MSG("wolfSSL_get_signature_nid");
- 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 (ssl == NULL || nid == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
}
- 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;
+ return HashToNid(ssl->options.hashAlgo, nid);
}
-#endif /* SESSION_CERTS && OPENSSL_EXTRA */
-#ifndef NO_CERTS
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-
-/* create a generic wolfSSL stack node
- * returns a new WOLFSSL_STACK structure on success */
-WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap)
+/* This API returns the signature selected. */
+int wolfSSL_get_signature_type_nid(const WOLFSSL* ssl, int* nid)
{
- WOLFSSL_STACK* sk;
- WOLFSSL_ENTER("wolfSSL_sk_new_node");
+ WOLFSSL_MSG("wolfSSL_get_signature_type_nid");
- sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap,
- DYNAMIC_TYPE_OPENSSL);
- if (sk != NULL) {
- XMEMSET(sk, 0, sizeof(*sk));
- sk->heap = heap;
+ if (ssl == NULL || nid == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
}
- return sk;
+ return SaToNid(ssl->options.sigAlgo, nid);
}
-/* free's node but does not free internal data such as in->data.x509 */
-void wolfSSL_sk_free_node(WOLFSSL_STACK* in)
+int wolfSSL_get_peer_signature_nid(WOLFSSL* ssl, int* nid)
{
- if (in != NULL) {
- XFREE(in, in->heap, DYNAMIC_TYPE_OPENSSL);
+ 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);
}
-/* 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)
+int wolfSSL_get_peer_signature_type_nid(const WOLFSSL* ssl, int* nid)
{
- if (stack == NULL || in == NULL) {
- return WOLFSSL_FAILURE;
- }
+ WOLFSSL_MSG("wolfSSL_get_peer_signature_type_nid");
- if (*stack == NULL) {
- in->num = 1;
- *stack = in;
- return WOLFSSL_SUCCESS;
+ if (ssl == NULL || nid == NULL) {
+ WOLFSSL_MSG("Bad function arguments");
+ return WOLFSSL_FAILURE;
}
- in->num = (*stack)->num + 1;
- in->next = *stack;
- *stack = in;
- return WOLFSSL_SUCCESS;
-}
-
-#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;
+ return SaToNid(ssl->options.peerSigAlgo, nid);
}
-#endif /* OPENSSL_ALL || WOLFSSL_QT */
+#ifdef HAVE_ECC
-/* return 1 on success 0 on fail */
-int wolfSSL_sk_push(WOLFSSL_STACK* sk, const void *data)
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, const char *list)
{
- WOLFSSL_STACK* node;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- WOLFSSL_CIPHER ciph;
-#endif
- WOLFSSL_ENTER("wolfSSL_sk_push");
-
- if (!sk) {
+ if (!ctx || !list) {
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 set_curves_list(NULL, ctx, list, 0);
+}
- /* 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");
+int wolfSSL_set1_groups_list(WOLFSSL *ssl, const char *list)
+{
+ if (!ssl || !list) {
return WOLFSSL_FAILURE;
}
- /* push new x509 onto head of stack */
- node->next = sk->next;
- node->type = sk->type;
- sk->next = node;
- sk->num += 1;
+ return set_curves_list(ssl, NULL, list, 0);
+}
+#endif /* WOLFSSL_TLS13 */
-#ifdef OPENSSL_ALL
- node->hash_fn = sk->hash_fn;
- node->hash = sk->hash;
- sk->hash = 0;
-#endif
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
- node->data.cipher = sk->data.cipher;
- sk->data.cipher = *(WOLFSSL_CIPHER*)data;
- if (sk->hash_fn) {
- sk->hash = sk->hash_fn(&sk->data.cipher);
- }
- break;
-#endif
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- /* All other types are pointers */
- node->data.generic = sk->data.generic;
- sk->data.generic = (void*)data;
-#ifdef OPENSSL_ALL
- if (sk->hash_fn) {
- sk->hash = sk->hash_fn(sk->data.generic);
- }
-#endif
- break;
- }
+#endif /* HAVE_ECC */
- return WOLFSSL_SUCCESS;
+#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 */
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
-#ifdef OPENSSL_EXTRA
+#ifdef SESSION_CERTS
-/* returns the node at index "idx", NULL if not found */
-WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx)
+#ifdef WOLFSSL_ALT_CERT_CHAINS
+/* Get peer's alternate certificate chain */
+WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl)
{
- int i;
- WOLFSSL_STACK* ret = NULL;
- WOLFSSL_STACK* current;
+ WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain");
+ if (ssl)
+ return &ssl->session->altChain;
- current = sk;
- for (i = 0; i <= idx && current != NULL; i++) {
- if (i == idx) {
- ret = current;
- break;
- }
- current = current->next;
- }
- return ret;
+ return 0;
}
+#endif /* WOLFSSL_ALT_CERT_CHAINS */
-#endif /* OPENSSL_EXTRA */
+/* 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;
-#ifdef OPENSSL_EXTRA
+ return 0;
+}
-#if defined(OPENSSL_ALL)
-void *wolfSSL_lh_retrieve(WOLFSSL_STACK *sk, void *data)
+/* Get peer's certificate chain total count */
+int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain)
{
- unsigned long hash;
+ WOLFSSL_ENTER("wolfSSL_get_chain_count");
+ if (chain)
+ return chain->count;
- WOLFSSL_ENTER("wolfSSL_lh_retrieve");
+ return 0;
+}
- if (!sk || !data) {
- WOLFSSL_MSG("Bad parameters");
- return NULL;
- }
- if (!sk->hash_fn) {
- WOLFSSL_MSG("No hash function defined");
- return NULL;
- }
+/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */
+int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx)
+{
+ WOLFSSL_ENTER("wolfSSL_get_chain_length");
+ if (chain)
+ return chain->certs[idx].length;
- hash = sk->hash_fn(data);
+ return 0;
+}
- while (sk) {
- /* Calc hash if not done so yet */
- if (!sk->hash) {
- switch (sk->type) {
- case STACK_TYPE_CIPHER:
- sk->hash = sk->hash_fn(&sk->data.cipher);
- break;
- case STACK_TYPE_X509:
- case STACK_TYPE_GEN_NAME:
- case STACK_TYPE_BIO:
- case STACK_TYPE_OBJ:
- case STACK_TYPE_STRING:
- case STACK_TYPE_ACCESS_DESCRIPTION:
- case STACK_TYPE_X509_EXT:
- case STACK_TYPE_X509_REQ_ATTR:
- case STACK_TYPE_NULL:
- case STACK_TYPE_X509_NAME:
- case STACK_TYPE_X509_NAME_ENTRY:
- case STACK_TYPE_CONF_VALUE:
- case STACK_TYPE_X509_INFO:
- case STACK_TYPE_BY_DIR_entry:
- case STACK_TYPE_BY_DIR_hash:
- case STACK_TYPE_X509_OBJ:
- case STACK_TYPE_DIST_POINT:
- case STACK_TYPE_X509_CRL:
- default:
- sk->hash = sk->hash_fn(sk->data.generic);
- break;
- }
- }
- if (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;
- }
- return NULL;
-}
+/* 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;
-#endif /* OPENSSL_ALL */
+ return 0;
+}
-#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)
+/* Get peer's wolfSSL X509 certificate at index (idx) */
+WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx)
{
- if (ssl == NULL) {
- return NULL;
- }
+ int ret = 0;
+ WOLFSSL_X509* x509 = NULL;
+ WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
- if (ssl->buffers.weOwnCert) {
- if (ssl->ourCert == NULL) {
- if (ssl->buffers.certificate == NULL) {
- WOLFSSL_MSG("Certificate buffer not set!");
- return NULL;
+ WOLFSSL_ENTER("wolfSSL_get_chain_X509");
+ if (chain != NULL && idx < MAX_CHAIN_DEPTH) {
+ #ifdef WOLFSSL_SMALL_STACK
+ cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+ DYNAMIC_TYPE_DCERT);
+ if (cert != NULL)
+ #endif
+ {
+ InitDecodedCert(cert, chain->certs[idx].buffer,
+ (word32)chain->certs[idx].length, NULL);
+
+ if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL, NULL)) != 0) {
+ WOLFSSL_MSG("Failed to parse cert");
}
- #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;
+ 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;
+ }
}
- #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;
+
+ FreeDecodedCert(cert);
+ WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
}
}
+ (void)ret;
- return NULL;
+ return x509;
}
-WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx)
-{
- if (ctx) {
- if (ctx->ourCert == NULL) {
- if (ctx->certificate == NULL) {
- WOLFSSL_MSG("Ctx Certificate buffer not set!");
- return NULL;
- }
- #ifndef WOLFSSL_X509_STORE_CERTS
- ctx->ourCert = wolfSSL_X509_d2i_ex(NULL,
- ctx->certificate->buffer,
- ctx->certificate->length, ctx->heap);
- #endif
- ctx->ownOurCert = 1;
- }
- return ctx->ourCert;
- }
- return NULL;
-}
-#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */
-#endif /* NO_CERTS */
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-void wolfSSL_set_connect_state(WOLFSSL* ssl)
+/* Get peer's PEM certificate at index (idx), output to buffer if inLen big
+ enough else return error (-1). If buffer is NULL only calculate
+ outLen. Output length is in *outLen WOLFSSL_SUCCESS on ok */
+int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx,
+ unsigned char* buf, int inLen, int* outLen)
{
- WOLFSSL_ENTER("wolfSSL_set_connect_state");
- if (ssl == NULL) {
- WOLFSSL_MSG("WOLFSSL struct pointer passed in was null");
- return;
- }
+#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;
- #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
+ WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem");
+ if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain))
+ return BAD_FUNC_ARG;
- if (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("Error initializing client side");
+ 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,
+ (word32)chain->certs[idx].length,
+ NULL, &szNeeded) != WC_NO_ERR_TRACE(LENGTH_ONLY_E))
+ return WOLFSSL_FAILURE;
+ *outLen = (int)szNeeded + headerLen + footerLen;
+ return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
}
-}
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+ /* don't even try if inLen too short */
+ if (inLen < headerLen + footerLen + chain->certs[idx].length)
+ return BAD_FUNC_ARG;
-int wolfSSL_get_shutdown(const WOLFSSL* ssl)
-{
- int isShutdown = 0;
+ /* header */
+ if (XMEMCPY(buf, header, (size_t)headerLen) == NULL)
+ return WOLFSSL_FATAL_ERROR;
- WOLFSSL_ENTER("wolfSSL_get_shutdown");
+ i = headerLen;
- 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;
- }
+ /* body */
+ *outLen = inLen; /* input to Base64_Encode */
+ if ( (err = Base64_Encode(chain->certs[idx].buffer,
+ (word32)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, (size_t)footerLen) == NULL)
+ return WOLFSSL_FATAL_ERROR;
+ *outLen += headerLen + footerLen;
- WOLFSSL_LEAVE("wolfSSL_get_shutdown", isShutdown);
- return isShutdown;
+ return WOLFSSL_SUCCESS;
+#else
+ (void)chain;
+ (void)idx;
+ (void)buf;
+ (void)inLen;
+ (void)outLen;
+ return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
}
+#endif /* SESSION_CERTS */
-int wolfSSL_session_reused(WOLFSSL* ssl)
+#ifdef HAVE_FUZZER
+void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx)
{
- 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
+ ssl->fuzzerCb = cbf;
+ ssl->fuzzerCtx = fCtx;
}
- WOLFSSL_LEAVE("wolfSSL_session_reused", resuming);
- return resuming;
}
+#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");
+#ifndef NO_CERTS
+#ifdef HAVE_PK_CALLBACKS
- 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;
+#ifdef HAVE_ECC
+void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb)
+{
+ if (ctx)
+ ctx->EccKeyGenCb = cb;
}
-
-
-WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap)
+void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx)
{
- return wolfSSL_NewSession(heap);
+ if (ssl)
+ ssl->EccKeyGenCtx = ctx;
}
+void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->EccKeyGenCtx;
-WOLFSSL_SESSION* wolfSSL_SESSION_new(void)
+ return NULL;
+}
+void wolfSSL_CTX_SetEccSignCtx(WOLFSSL_CTX* ctx, void *userCtx)
{
- return wolfSSL_SESSION_new_ex(NULL);
+ if (ctx)
+ ctx->EccSignCtx = userCtx;
}
-
-/* add one to session reference count
- * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */
-int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session)
+void* wolfSSL_CTX_GetEccSignCtx(WOLFSSL_CTX* ctx)
{
- 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
+ if (ctx)
+ return ctx->EccSignCtx;
- return WOLFSSL_SUCCESS;
+ return NULL;
}
-/**
- * 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)
+WOLFSSL_ABI
+void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb)
{
-#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;
+ if (ctx)
+ ctx->EccSignCb = cb;
}
-
-/**
- * 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)
+void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx)
{
- return wolfSSL_DupSessionEx(input, output, avoidSysCalls, NULL, NULL, NULL);
+ if (ssl)
+ ssl->EccSignCtx = ctx;
}
-
-WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session)
+void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl)
{
- 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
+ if (ssl)
+ return ssl->EccSignCtx;
- copy = wolfSSL_NewSession(session->heap);
- if (copy != NULL &&
- wolfSSL_DupSession(session, copy, 0) != WOLFSSL_SUCCESS) {
- wolfSSL_FreeSession(NULL, copy);
- copy = NULL;
- }
- return copy;
+ return NULL;
}
-void wolfSSL_FreeSession(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
+void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb)
{
- 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);
- }
+ if (ctx)
+ ctx->EccVerifyCb = cb;
}
-
-/* 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)
+void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx)
{
- session = ClientSessionToSession(session);
- wolfSSL_FreeSession(NULL, session);
+ if (ssl)
+ ssl->EccVerifyCtx = ctx;
}
-
-#ifndef NO_SESSION_CACHE
-int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
+void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl)
{
- 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);
+ if (ssl)
+ return ssl->EccVerifyCtx;
- return error == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
+ return NULL;
}
-#endif
-#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE)
-
-/**
-* set cipher to WOLFSSL_SESSION from WOLFSSL_CIPHER
-* @param session a pointer to WOLFSSL_SESSION structure
-* @param cipher a function pointer to WOLFSSL_CIPHER
-* @return WOLFSSL_SUCCESS on success, otherwise WOLFSSL_FAILURE
-*/
-int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session,
- const WOLFSSL_CIPHER* cipher)
+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)
{
- WOLFSSL_ENTER("wolfSSL_SESSION_set_cipher");
+ if (ssl)
+ return ssl->EccSharedSecretCtx;
- 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;
+ return NULL;
+}
+#endif /* HAVE_ECC */
- WOLFSSL_LEAVE("wolfSSL_SESSION_set_cipher", WOLFSSL_SUCCESS);
- return WOLFSSL_SUCCESS;
+#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;
}
-#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */
+void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->Ed25519SignCtx;
+ return NULL;
+}
-/* helper function that takes in a protocol version struct and returns string */
-static const char* wolfSSL_internal_get_version(const ProtocolVersion* version)
+void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb)
{
- WOLFSSL_ENTER("wolfSSL_get_version");
-
- if (version == NULL) {
- return "Bad arg";
- }
-
- 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";
+ if (ctx)
+ ctx->Ed25519VerifyCb = cb;
}
-
-
-const char* wolfSSL_get_version(const WOLFSSL* ssl)
+void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx)
{
- if (ssl == NULL) {
- WOLFSSL_MSG("Bad argument");
- return "unknown";
- }
-
- return wolfSSL_internal_get_version(&ssl->version);
+ if (ssl)
+ ssl->Ed25519VerifyCtx = ctx;
}
-
-
-/* current library version */
-const char* wolfSSL_lib_version(void)
+void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl)
{
- return LIBWOLFSSL_VERSION_STRING;
+ if (ssl)
+ return ssl->Ed25519VerifyCtx;
+
+ return NULL;
}
+#endif /* HAVE_ED25519 */
-#ifdef OPENSSL_EXTRA
-#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
-const char* wolfSSL_OpenSSL_version(int a)
+#ifdef HAVE_CURVE25519
+void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx,
+ CallbackX25519KeyGen cb)
{
- (void)a;
- return "wolfSSL " LIBWOLFSSL_VERSION_STRING;
+ if (ctx)
+ ctx->X25519KeyGenCb = cb;
}
-#else
-const char* wolfSSL_OpenSSL_version(void)
+void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx)
{
- return "wolfSSL " LIBWOLFSSL_VERSION_STRING;
+ if (ssl)
+ ssl->X25519KeyGenCtx = ctx;
}
-#endif /* WOLFSSL_QT */
-#endif
+void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->X25519KeyGenCtx;
+ return NULL;
+}
-/* current library version in hex */
-word32 wolfSSL_lib_version_hex(void)
+void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx,
+ CallbackX25519SharedSecret cb)
{
- return LIBWOLFSSL_VERSION_HEX;
+ if (ctx)
+ ctx->X25519SharedSecretCb = cb;
}
-
-
-int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl)
+void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx)
{
- WOLFSSL_ENTER("wolfSSL_get_current_cipher_suite");
if (ssl)
- return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite;
- return 0;
+ ssl->X25519SharedSecretCtx = ctx;
}
-
-WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl)
+void* wolfSSL_GetX25519SharedSecretCtx(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;
-}
+ if (ssl)
+ return ssl->X25519SharedSecretCtx;
+ return NULL;
+}
+#endif /* HAVE_CURVE25519 */
-const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher)
+#ifdef HAVE_ED448
+void wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX* ctx, CallbackEd448Sign cb)
{
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_name");
-
- if (cipher == 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
+ if (ctx)
+ ctx->Ed448SignCb = cb;
}
-
-const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher)
+void wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx)
{
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_version");
-
- if (cipher == NULL || cipher->ssl == NULL) {
- return NULL;
- }
-
- return wolfSSL_get_version(cipher->ssl);
+ if (ssl)
+ ssl->Ed448SignCtx = ctx;
}
-
-const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session)
+void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl)
{
- session = ClientSessionToSession(session);
- if (session == NULL) {
- return NULL;
- }
+ if (ssl)
+ return ssl->Ed448SignCtx;
-#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
}
-const char* wolfSSL_get_cipher(WOLFSSL* ssl)
+void wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX* ctx, CallbackEd448Verify cb)
{
- WOLFSSL_ENTER("wolfSSL_get_cipher");
- return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl));
+ if (ctx)
+ ctx->Ed448VerifyCb = cb;
}
-
-/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */
-const char* wolfSSL_get_cipher_name(WOLFSSL* ssl)
+void wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx)
{
- /* get access to cipher_name_idx in internal.c */
- return wolfSSL_get_cipher_name_internal(ssl);
+ if (ssl)
+ ssl->Ed448VerifyCtx = ctx;
}
-
-const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0,
- const byte cipherSuite)
+void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl)
{
- return GetCipherNameInternal(cipherSuite0, cipherSuite);
+ if (ssl)
+ return ssl->Ed448VerifyCtx;
+
+ return NULL;
}
+#endif /* HAVE_ED448 */
-const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0,
- const byte cipherSuite)
+#ifdef HAVE_CURVE448
+void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX* ctx,
+ CallbackX448KeyGen cb)
{
- return GetCipherNameIana(cipherSuite0, cipherSuite);
+ if (ctx)
+ ctx->X448KeyGenCb = cb;
}
-
-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);
+void wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->X448KeyGenCtx = ctx;
}
-
-
-#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
-/* Creates and returns a new WOLFSSL_CIPHER stack. */
-WOLFSSL_STACK* wolfSSL_sk_new_cipher(void)
+void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl)
{
- WOLFSSL_STACK* sk;
- WOLFSSL_ENTER("wolfSSL_sk_new_cipher");
-
- sk = wolfSSL_sk_new_null();
- if (sk == NULL)
- return NULL;
- sk->type = STACK_TYPE_CIPHER;
+ if (ssl)
+ return ssl->X448KeyGenCtx;
- return sk;
+ return NULL;
}
-/* return 1 on success 0 on fail */
-int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk,
- WOLFSSL_CIPHER* cipher)
+void wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX* ctx,
+ CallbackX448SharedSecret cb)
{
- return wolfSSL_sk_push(sk, cipher);
+ if (ctx)
+ ctx->X448SharedSecretCb = cb;
}
-
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk)
+void wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx)
{
- WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop");
- (void)sk;
- return NULL;
+ if (ssl)
+ ssl->X448SharedSecretCtx = ctx;
}
-#endif /* NO_WOLFSSL_STUB */
-#endif /* WOLFSSL_QT || OPENSSL_ALL */
-
-word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher)
+void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl)
{
- word16 cipher_id = 0;
-
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_id");
-
- if (cipher && cipher->ssl) {
- cipher_id = (cipher->ssl->options.cipherSuite0 << 8) |
- cipher->ssl->options.cipherSuite;
- }
+ if (ssl)
+ return ssl->X448SharedSecretCtx;
- return cipher_id;
+ return NULL;
}
+#endif /* HAVE_CURVE448 */
-const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value)
+#ifndef NO_RSA
+void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb)
{
- 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 (ctx)
+ ctx->RsaSignCb = cb;
}
-
-
-#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)
+void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
{
- WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free");
-
- wolfSSL_sk_free(sk);
+ if (ctx)
+ ctx->RsaSignCheckCb = cb;
}
-#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)
+void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx)
{
- const char* str = NULL;
- switch (group) {
- case WOLFSSL_FFDHE_2048:
- str = "FFDHE_2048";
- break;
- case WOLFSSL_FFDHE_3072:
- str = "FFDHE_3072";
- break;
- case WOLFSSL_FFDHE_4096:
- str = "FFDHE_4096";
- break;
- case WOLFSSL_FFDHE_6144:
- str = "FFDHE_6144";
- break;
- case WOLFSSL_FFDHE_8192:
- str = "FFDHE_8192";
- break;
- default:
- break;
- }
- return str;
+ if (ssl)
+ ssl->RsaSignCtx = ctx;
}
-#endif
-/* Return the name of the curve used for key exchange as a printable string.
- *
- * ssl The SSL/TLS object.
- * returns NULL if ECDH was not used, otherwise the name as a string.
- */
-const char* wolfSSL_get_curve_name(WOLFSSL* ssl)
+void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl)
{
- const char* cName = NULL;
-
- WOLFSSL_ENTER("wolfSSL_get_curve_name");
-
- if (ssl == NULL)
- return NULL;
-
-#if defined(WOLFSSL_TLS13) && defined(HAVE_PQC)
- /* Check for post-quantum groups. Return now because we do not want the ECC
- * check to override this result in the case of a hybrid. */
- if (IsAtLeastTLSv1_3(ssl->version)) {
- switch (ssl->namedGroup) {
-#ifdef HAVE_LIBOQS
- case WOLFSSL_KYBER_LEVEL1:
- return "KYBER_LEVEL1";
- case WOLFSSL_KYBER_LEVEL3:
- return "KYBER_LEVEL3";
- case WOLFSSL_KYBER_LEVEL5:
- return "KYBER_LEVEL5";
- case WOLFSSL_P256_KYBER_LEVEL1:
- return "P256_KYBER_LEVEL1";
- case WOLFSSL_P384_KYBER_LEVEL3:
- return "P384_KYBER_LEVEL3";
- case WOLFSSL_P521_KYBER_LEVEL5:
- return "P521_KYBER_LEVEL5";
-#elif defined(HAVE_PQM4)
- case WOLFSSL_KYBER_LEVEL1:
- return "KYBER_LEVEL1";
-#elif defined(WOLFSSL_WC_KYBER)
- #ifdef WOLFSSL_KYBER512
- case WOLFSSL_KYBER_LEVEL1:
- return "KYBER_LEVEL1";
- #endif
- #ifdef WOLFSSL_KYBER768
- case WOLFSSL_KYBER_LEVEL3:
- return "KYBER_LEVEL3";
- #endif
- #ifdef WOLFSSL_KYBER1024
- case WOLFSSL_KYBER_LEVEL5:
- return "KYBER_LEVEL5";
- #endif
-#endif
- }
- }
-
-#endif /* WOLFSSL_TLS13 && HAVE_PQC */
-#ifdef HAVE_FFDHE
- if (ssl->namedGroup != 0) {
- cName = wolfssl_ffdhe_name(ssl->namedGroup);
- }
-#endif
-
-#ifdef HAVE_CURVE25519
- if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) {
- cName = "X25519";
- }
-#endif
+ if (ssl)
+ return ssl->RsaSignCtx;
-#ifdef HAVE_CURVE448
- if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) {
- cName = "X448";
- }
-#endif
+ return NULL;
+}
-#ifdef HAVE_ECC
- if (ssl->ecdhCurveOID != 0 && cName == NULL) {
- cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL,
- NULL));
- }
-#endif
- return cName;
+void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb)
+{
+ if (ctx)
+ ctx->RsaVerifyCb = cb;
}
-#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)
+void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx)
{
- static const struct authnid {
- const char* alg_name;
- const int nid;
- } authnid_tbl[] = {
- {"RSA", NID_auth_rsa},
- {"PSK", NID_auth_psk},
- {"SRP", NID_auth_srp},
- {"ECDSA", NID_auth_ecdsa},
- {"None", NID_auth_null},
- {NULL, NID_undef}
- };
-
- const char* authStr;
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
+ if (ssl)
+ ssl->RsaVerifyCtx = ctx;
+}
+void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->RsaVerifyCtx;
- if (GetCipherSegment(cipher, n) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
+ return NULL;
+}
- authStr = GetCipherAuthStr(n);
+#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;
- if (authStr != NULL) {
- const struct authnid* sa;
- for(sa = authnid_tbl; sa->alg_name != NULL; sa++) {
- if (XSTRCMP(sa->alg_name, authStr) == 0) {
- return sa->nid;
- }
- }
- }
+ return NULL;
+}
- return NID_undef;
+void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb)
+{
+ if (ctx)
+ ctx->RsaPssVerifyCb = cb;
}
-/* return cipher NID corresponding to cipher suite
- * @param cipher a pointer to WOLFSSL_CIPHER
- * return NID if found, NID_undef if not found
- */
-int wolfSSL_CIPHER_get_cipher_nid(const WOLFSSL_CIPHER* cipher)
+void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx)
{
- static const struct ciphernid {
- const char* alg_name;
- const int nid;
- } ciphernid_tbl[] = {
- {"AESGCM(256)", NID_aes_256_gcm},
- {"AESGCM(128)", NID_aes_128_gcm},
- {"AESCCM(128)", NID_aes_128_ccm},
- {"AES(128)", NID_aes_128_cbc},
- {"AES(256)", NID_aes_256_cbc},
- {"CAMELLIA(256)", NID_camellia_256_cbc},
- {"CAMELLIA(128)", NID_camellia_128_cbc},
- {"RC4", NID_rc4},
- {"3DES", NID_des_ede3_cbc},
- {"CHACHA20/POLY1305(256)", NID_chacha20_poly1305},
- {"None", NID_undef},
- {NULL, NID_undef}
- };
+ if (ssl)
+ ssl->RsaPssVerifyCtx = ctx;
+}
+void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->RsaPssVerifyCtx;
- const char* encStr;
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
+ return NULL;
+}
+#endif /* WC_RSA_PSS */
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_cipher_nid");
+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;
- if (GetCipherSegment(cipher, n) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
+ return NULL;
+}
- encStr = GetCipherEncStr(n);
+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;
- if (encStr != NULL) {
- const struct ciphernid* c;
- for(c = ciphernid_tbl; c->alg_name != NULL; c++) {
- if (XSTRCMP(c->alg_name, encStr) == 0) {
- return c->nid;
- }
- }
- }
+ return NULL;
+}
+#endif /* NO_RSA */
- return NID_undef;
+/* callback for premaster secret generation */
+void wolfSSL_CTX_SetGenPreMasterCb(WOLFSSL_CTX* ctx, CallbackGenPreMaster cb)
+{
+ if (ctx)
+ ctx->GenPreMasterCb = cb;
}
-/* 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)
+/* Set premaster secret generation callback context */
+void wolfSSL_SetGenPreMasterCtx(WOLFSSL* ssl, void *ctx)
{
- 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}
- };
+ if (ssl)
+ ssl->GenPreMasterCtx = ctx;
+}
+/* Get premaster secret generation callback context */
+void* wolfSSL_GetGenPreMasterCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->GenPreMasterCtx;
- const char* name;
- const char* macStr;
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
- (void)name;
+ return NULL;
+}
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_digest_nid");
+/* 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;
- if ((name = GetCipherSegment(cipher, n)) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
+ return NULL;
+}
- /* in MD5 case, NID will be NID_md5 */
- if (XSTRSTR(name, "MD5") != NULL) {
- return NID_md5;
- }
+/* callback for extended master secret generation */
+void wolfSSL_CTX_SetGenExtMasterSecretCb(WOLFSSL_CTX* ctx,
+ CallbackGenExtMasterSecret cb)
+{
+ if (ctx)
+ ctx->GenExtMasterCb = cb;
+}
+/* Set extended master secret generation callback context */
+void wolfSSL_SetGenExtMasterSecretCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->GenExtMasterCtx = ctx;
+}
+/* Get extended master secret generation callback context */
+void* wolfSSL_GetGenExtMasterSecretCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->GenExtMasterCtx;
- macStr = GetCipherMacStr(n);
+ return NULL;
+}
- 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 NID_undef;
+/* callback for session key generation */
+void wolfSSL_CTX_SetGenSessionKeyCb(WOLFSSL_CTX* ctx, CallbackGenSessionKey cb)
+{
+ if (ctx)
+ ctx->GenSessionKeyCb = cb;
}
-/* return key exchange NID corresponding to cipher suite
- * @param cipher a pointer to WOLFSSL_CIPHER
- * return NID if found, NID_undef if not found
- */
-int wolfSSL_CIPHER_get_kx_nid(const WOLFSSL_CIPHER* cipher)
+/* Set session key generation callback context */
+void wolfSSL_SetGenSessionKeyCtx(WOLFSSL* ssl, void *ctx)
{
- static const struct kxnid {
- const char* name;
- const int nid;
- } kxnid_table[] = {
- {"ECDHEPSK", NID_kx_ecdhe_psk},
- {"ECDH", NID_kx_ecdhe},
- {"DHEPSK", NID_kx_dhe_psk},
- {"DH", NID_kx_dhe},
- {"RSAPSK", NID_kx_rsa_psk},
- {"SRP", NID_kx_srp},
- {"EDH", NID_kx_dhe},
- {"RSA", NID_kx_rsa},
- {NULL, NID_undef}
- };
-
- const char* keaStr;
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
+ if (ssl)
+ ssl->GenSessionKeyCtx = ctx;
+}
+/* Get session key generation callback context */
+void* wolfSSL_GetGenSessionKeyCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->GenSessionKeyCtx;
- WOLFSSL_ENTER("wolfSSL_CIPHER_get_kx_nid");
+ return NULL;
+}
- if (GetCipherSegment(cipher, n) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
+/* 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;
- /* in TLS 1.3 case, NID will be NID_kx_any */
- if (XSTRCMP(n[0], "TLS13") == 0) {
- return NID_kx_any;
- }
+ return NULL;
+}
- keaStr = GetCipherKeaStr(n);
+/* 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;
- if (keaStr != NULL) {
- const struct kxnid* k;
- for(k = kxnid_table; k->name != NULL; k++) {
- if (XSTRCMP(k->name, keaStr) == 0) {
- return k->nid;
- }
- }
- }
+ return NULL;
+}
+#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;
+}
- return NID_undef;
+/* Set set keys callback context */
+void wolfSSL_SetVerifyMacCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->VerifyMacCtx = ctx;
}
-/* 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)
+/* Get set keys callback context */
+void* wolfSSL_GetVerifyMacCtx(WOLFSSL* ssl)
{
- char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}};
+ if (ssl)
+ return ssl->VerifyMacCtx;
- WOLFSSL_ENTER("wolfSSL_CIPHER_is_aead");
+ return NULL;
+}
+#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */
- if (GetCipherSegment(cipher, n) == NULL) {
- WOLFSSL_MSG("no suitable cipher name found");
- return NID_undef;
- }
+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 */
- return IsCipherAEAD(n);
+#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH)
+void wolfSSL_CTX_SetDhGenerateKeyPair(WOLFSSL_CTX* ctx,
+ CallbackDhGenerateKeyPair cb) {
+ if (ctx)
+ ctx->DhGenerateKeyPairCb = cb;
}
-/* Creates cipher->description based on cipher->offset
- * cipher->offset is set in wolfSSL_get_ciphers_compat when it is added
- * to a stack of ciphers.
- * @param [in] cipher: A cipher from a stack of ciphers.
- * return WOLFSSL_SUCCESS if cipher->description is set, else WOLFSSL_FAILURE
- */
-int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher)
+void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb)
{
- 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 (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;
- if (cipher == NULL)
- return WOLFSSL_FAILURE;
+ return NULL;
+}
+#endif /* HAVE_PK_CALLBACKS && !NO_DH */
- dp = cipher->description;
- if (dp == NULL)
- return WOLFSSL_FAILURE;
+#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_HKDF)
- cipher_names = GetCipherNames();
+void wolfSSL_CTX_SetHKDFExtractCb(WOLFSSL_CTX* ctx, CallbackHKDFExtract cb)
+{
+ if (ctx)
+ ctx->HkdfExtractCb = cb;
+}
- 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;
- }
+void wolfSSL_SetHKDFExtractCtx(WOLFSSL* ssl, void *ctx)
+{
+ if (ssl)
+ ssl->HkdfExtractCtx = ctx;
+}
- /* 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);
+void* wolfSSL_GetHKDFExtractCtx(WOLFSSL* ssl)
+{
+ if (ssl)
+ return ssl->HkdfExtractCtx;
+ return NULL;
+}
+#endif /* HAVE_PK_CALLBACKS && HAVE_HKDF */
- /* 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;
+#ifdef WOLFSSL_HAVE_WOLFSCEP
+ /* Used by autoconf to see if wolfSCEP is available */
+ void wolfSSL_wolfSCEP(void) {}
+#endif
- 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;
- 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;
+#ifdef WOLFSSL_HAVE_CERT_SERVICE
+ /* Used by autoconf to see if cert service is available */
+ void wolfSSL_cert_service(void) {}
+#endif
- 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;
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+ !defined(WOLFCRYPT_ONLY)
- 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;
+ /* 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
+ */
- 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_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id)
+ {
+ return wolfSSL_OBJ_nid2obj_ex(id, NULL);
+ }
- return WOLFSSL_SUCCESS;
-}
-#endif /* OPENSSL_ALL || WOLFSSL_QT */
-static WC_INLINE const char* wolfssl_kea_to_string(int kea)
-{
- const char* keaStr;
+ 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;
- 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;
+#ifdef WOLFSSL_DEBUG_OPENSSL
+ WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj");
#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
+
+ 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 = (word32)id;
+ #else
+ return NULL;
+ #endif
+ }
+
#ifdef HAVE_ECC
- case ecdhe_psk_kea:
- keaStr = "ECDHEPSK";
- break;
- #endif
-#endif
-#ifdef HAVE_ECC
- case ecc_diffie_hellman_kea:
- keaStr = "ECDHE";
- break;
- case ecc_static_diffie_hellman_kea:
- keaStr = "ECDH";
- break;
-#endif
- default:
- keaStr = "unknown";
- break;
- }
+ if (type == 0 && wc_ecc_get_oid((word32)id, &oid, &oidSz) > 0) {
+ type = oidCurveType;
+ }
+ #endif /* HAVE_ECC */
- return keaStr;
-}
+ if (sName != NULL) {
+ if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) {
+ WOLFSSL_MSG("Attempted short name is too large");
+ return NULL;
+ }
+ }
-static WC_INLINE const char* wolfssl_sigalg_to_string(int sig_algo)
-{
- const char* authStr;
+ oid = OidFromId((word32)id, type, &oidSz);
- 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;
- }
+ /* 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 = (int)type;
- return authStr;
-}
+ obj->sName[0] = '\0';
+ if (sName != NULL) {
+ XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName));
+ }
-static WC_INLINE const char* wolfssl_cipher_to_string(int cipher, int key_size)
-{
- const char* encStr;
+ objBuf[0] = ASN_OBJECT_ID; objSz++;
+ objSz += SetLength(oidSz, objBuf + 1);
+ if (oidSz) {
+ XMEMCPY(objBuf + objSz, oid, oidSz);
+ objSz += oidSz;
+ }
- (void)key_size;
+ 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 &= (unsigned char)~WOLFSSL_ASN1_DYNAMIC_DATA;
+ }
+ }
+ XMEMCPY((byte*)obj->obj, objBuf, obj->objSz);
- 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)type;
- return encStr;
-}
+ return obj;
+ }
-static WC_INLINE const char* wolfssl_mac_to_string(int mac)
-{
- const char* macStr;
+ 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;
- 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;
+ for (idx = oid_dict; idx->num != NULL; idx++) {
+ if (!XSTRCMP(oid, idx->num)) {
+ return idx->desc;
+ }
+ }
+ return NULL;
}
- return macStr;
-}
-
-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");
+ static int wolfssl_obj2txt_numeric(char *buf, int bufLen,
+ const WOLFSSL_ASN1_OBJECT *a)
+ {
+ int bufSz;
+ int length;
+ word32 idx = 0;
+ byte tag;
- if (cipher == NULL || in == NULL)
- return NULL;
+ if (GetASNTag(a->obj, &idx, &tag, a->objSz) != 0) {
+ return WOLFSSL_FAILURE;
+ }
-#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
+ if (tag != ASN_OBJECT_ID) {
+ WOLFSSL_MSG("Bad ASN1 Object");
+ return WOLFSSL_FAILURE;
+ }
- /* 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);
+ if (GetLength((const byte*)a->obj, &idx, &length,
+ a->objSz) < 0 || length < 0) {
+ return ASN_PARSE_E;
+ }
- /* 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;
+ if (bufLen < MAX_OID_STRING_SZ) {
+ bufSz = bufLen - 1;
+ }
+ else {
+ bufSz = MAX_OID_STRING_SZ;
+ }
- 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 ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx,
+ (word32)length)) <= 0) {
+ WOLFSSL_MSG("Error decoding OID");
+ 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;
+ buf[bufSz] = '\0';
- 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;
+ return bufSz;
+ }
- 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;
+ /* 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;
- XSTRNCPY(in, " Mac=", len);
- in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen;
- XSTRNCPY(in, macStr, len);
- in[len-1] = '\0';
+ WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt");
- return ret;
-}
+ 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);
+ }
-#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;
-}
+ /* 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
-#ifndef NO_WOLFSSL_STUB
-void wolfSSL_RAND_screen(void)
-{
- WOLFSSL_STUB("RAND_screen");
-}
-#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, (size_t)bufSz);
+ }
+ else if (a->type == WOLFSSL_GEN_DNS || a->type == WOLFSSL_GEN_EMAIL ||
+ a->type == WOLFSSL_GEN_URI) {
+ bufSz = (int)XSTRLEN((const char*)a->obj);
+ XMEMCPY(buf, a->obj, min((word32)bufSz, (word32)bufLen));
+ }
+ else if ((bufSz = wolfssl_obj2txt_numeric(buf, bufLen, a)) > 0) {
+ if ((desc = oid_translate_num_to_str(buf))) {
+ bufSz = (int)XSTRLEN(desc);
+ bufSz = (int)min((word32)bufSz,(word32) bufLen - 1);
+ XMEMCPY(buf, desc, (size_t)bufSz);
+ }
+ }
+ else {
+ bufSz = 0;
+ }
+ buf[bufSz] = '\0';
+ return bufSz;
+ }
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-int wolfSSL_RAND_load_file(const char* fname, long len)
-{
- (void)fname;
- /* wolfCrypt provides enough entropy internally or will report error */
- if (len == -1)
- return 1024;
- else
- return (int)len;
-}
-
+#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 */
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void)
-{
- WOLFSSL_STUB("COMP_zlib");
- return 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");
-#ifndef NO_WOLFSSL_STUB
-WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void)
-{
- WOLFSSL_STUB("COMP_rle");
- return 0;
-}
-#endif
+ if (n == WC_NID_md5) {
+ /* WC_NID_surname == WC_NID_md5 and WC_NID_surname comes before WC_NID_md5 in
+ * wolfssl_object_info. As a result, the loop below will incorrectly
+ * return "SN" instead of "MD5." WC_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;
+ }
-#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;
-}
+#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 WC_NID_undef;
+ return wc_OBJ_sn2nid(sn);
+ }
#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;
-}
-
-
-#endif /* OPENSSL_EXTRA */
-
-#ifdef OPENSSL_EXTRA
-#ifndef NO_CERTS
+ size_t wolfSSL_OBJ_length(const WOLFSSL_ASN1_OBJECT* o)
+ {
+ size_t ret = 0;
+ int err = 0;
+ word32 idx = 0;
+ int len = 0;
-#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);
-}
+ WOLFSSL_ENTER("wolfSSL_OBJ_length");
-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 (o == NULL || o->obj == NULL) {
+ WOLFSSL_MSG("Bad argument.");
+ err = 1;
+ }
- if (key == NULL) {
- return WOLFSSL_FATAL_ERROR;
- }
+ if (err == 0 && GetASNObjectId(o->obj, &idx, &len, o->objSz)) {
+ WOLFSSL_MSG("Error parsing ASN.1 header.");
+ err = 1;
+ }
+ if (err == 0) {
+ ret = (size_t)len;
+ }
- key_type = key->type;
- if ((key_type != EVP_PKEY_EC) && (key_type != EVP_PKEY_RSA)) {
- return WOLFSSL_FATAL_ERROR;
- }
+ WOLFSSL_LEAVE("wolfSSL_OBJ_length", (int)ret);
-#ifndef NO_RSA
- if (key_type == EVP_PKEY_RSA) {
- return wolfSSL_i2d_RSAPublicKey(key->rsa, der);
+ return ret;
}
-#endif
- /* Now that RSA is taken care of, we only need to consider the ECC case. */
+ 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;
-#ifdef HAVE_ECC
+ WOLFSSL_ENTER("wolfSSL_OBJ_get0_data");
- /* 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;
+ if (o == NULL || o->obj == NULL) {
+ WOLFSSL_MSG("Bad argument.");
+ err = 1;
}
- } 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 (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;
}
- }
- if (ret == 0) {
- ret = wc_ecc_init(eccKey);
+ return ret;
}
- 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);
- }
- }
- if (ret == 0) {
- pub_derSz = wc_EccPublicKeyDerSize(eccKey, 0);
- if ((int)pub_derSz <= 0) {
- ret = WOLFSSL_FAILURE;
- }
- }
+ /* 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;
- 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;
+#ifdef WOLFSSL_DEBUG_OPENSSL
+ WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid");
+#endif
+
+ if (o == NULL) {
+ return 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;
+ #ifdef WOLFSSL_QT
+ if (o->grp == oidCertExtType) {
+ /* If nid is an unknown extension, return WC_NID_undef */
+ if (wolfSSL_OBJ_nid2sn(o->nid) == NULL)
+ return WC_NID_undef;
}
- }
+ #endif
- /* 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 (o->nid > 0)
+ return o->nid;
+ if ((ret = GetObjectId(o->obj, &idx, &oid,
+ (word32)o->grp, o->objSz)) < 0) {
+ if (ret == WC_NO_ERR_TRACE(ASN_OBJECT_ID_E)) {
+ /* Put ASN object tag in front and try again */
+ int len = SetObjectId((int)o->objSz, NULL) + (int)o->objSz;
+ byte* buf = (byte*)XMALLOC((size_t)len, NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (!buf) {
+ WOLFSSL_MSG("malloc error");
+ return WOLFSSL_FATAL_ERROR;
+ }
+ idx = (word32)SetObjectId((int)o->objSz, buf);
+ XMEMCPY(buf + idx, o->obj, o->objSz);
+ idx = 0;
+ ret = GetObjectId(buf, &idx, &oid, (word32)o->grp, (word32)len);
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (ret < 0) {
+ WOLFSSL_MSG("Issue getting OID of object");
+ return WOLFSSL_FATAL_ERROR;
+ }
}
-
- if (ret == 0) {
- XMEMCPY(*der, pub_der, pub_derSz);
+ else {
+ WOLFSSL_MSG("Issue getting OID of object");
+ return WOLFSSL_FATAL_ERROR;
}
}
- 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 oid2nid(oid, o->grp);
+ }
-#else
- ret = WOLFSSL_FATAL_ERROR;
-#endif /* HAVE_ECC */
+ /* Return the corresponding NID for the long name
+ * or WC_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 (ret == 0) {
- return pub_derSz;
+ 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 WC_NID_undef;
}
- return ret;
-#else
- return WOLFSSL_FATAL_ERROR;
-#endif /* !NO_RSA || HAVE_ECC */
-}
-#endif /* !NO_ASN && !NO_PWDBASED */
-
-#endif /* !NO_CERTS */
-#endif /* OPENSSL_EXTRA */
+ /* 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 OPENSSL_EXTRA
+ 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;
+ }
+ }
+ }
+ }
-/* 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;
+ 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 WC_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];
- return wolfSSL_X509_VERIFY_PARAM_set1_host(ssl->param, name, 0);
-}
+ XMEMSET(out, 0, sizeof(out));
+ #endif
-/******************************************************************************
-* 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;
+ WOLFSSL_ENTER("wolfSSL_OBJ_txt2nid");
- return wolfSSL_X509_VERIFY_PARAM_set1(ctx->param, vpm);
-}
+ if (s == NULL) {
+ return WC_NID_undef;
+ }
-/******************************************************************************
-* 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;
- }
+ #ifdef WOLFSSL_CERT_EXT
+ ret = EncodePolicyOID(out, &outSz, s, NULL);
+ if (ret == 0) {
+ /* sum OID */
+ sum = wc_oid_sum(out, outSz);
+ }
+ #endif /* WOLFSSL_CERT_EXT */
- return ctx->param;
-}
+ /* 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
-WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl)
-{
- if (ssl == NULL) {
- return NULL;
+ /* 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, (word32)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, (word32)len) == 0) {
+ return wolfssl_object_info[i].nid;
+ }
+ }
+
+ return WC_NID_undef;
}
- return ssl->param;
-}
+#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)
-#endif /* OPENSSL_EXTRA */
+ /* 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 = WC_NID_undef;
+ unsigned int outSz = MAX_OID_SZ;
+ unsigned char out[MAX_OID_SZ];
+ WOLFSSL_ASN1_OBJECT* obj;
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-/* Gets an index to store SSL structure at.
- *
- * Returns positive index on success and negative values on failure
- */
-int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void)
-{
- WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx");
+ WOLFSSL_ENTER("wolfSSL_OBJ_txt2obj");
- /* store SSL at index 0 */
- return 0;
-}
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+ if (s == NULL)
+ return NULL;
-#ifdef OPENSSL_EXTRA
-/* Sets a function callback that will send information about the state of all
- * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed
- * in.
- *
- * ctx WOLFSSL_CTX structure to set callback function in
- * f callback function to use
- */
-void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx,
- void (*f)(const WOLFSSL* ssl, int type, int val))
-{
- WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback");
- if (ctx == NULL) {
- WOLFSSL_MSG("Bad function argument");
- }
- else {
- ctx->CBIS = f;
+ /* If s is numerical value, try to sum oid */
+ ret = EncodePolicyOID(out, &outSz, s, NULL);
+ if (ret == 0 && outSz > 0) {
+ /* If numerical encode succeeded then just
+ * create object from that because sums are
+ * not unique and can cause confusion. */
+ obj = wolfSSL_ASN1_OBJECT_new();
+ if (obj == NULL) {
+ WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
+ return NULL;
+ }
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC;
+ obj->obj = (byte*)XMALLOC(1 + MAX_LENGTH_SZ + outSz, NULL,
+ DYNAMIC_TYPE_ASN1);
+ if (obj->obj == NULL) {
+ wolfSSL_ASN1_OBJECT_free(obj);
+ return NULL;
+ }
+ obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA;
+ i = SetObjectId((int)outSz, (byte*)obj->obj);
+ XMEMCPY((byte*)obj->obj + i, out, outSz);
+ obj->objSz = (word32)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 != WC_NID_undef)
+ return wolfSSL_OBJ_nid2obj(nid);
+
+ return NULL;
}
-}
+#endif
-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");
+ /* 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");
}
- else {
- ssl->CBIS = f;
+
+ #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
+ }
-unsigned long wolfSSL_ERR_peek_error(void)
-{
- WOLFSSL_ENTER("wolfSSL_ERR_peek_error");
+#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE ||
+ HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
- return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL);
-}
+#ifdef OPENSSL_EXTRA
-int wolfSSL_ERR_GET_LIB(unsigned long err)
+/* 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)
{
- unsigned long value;
+ WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
- 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;
+ (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 == -WC_NO_ERR_TRACE(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
}
-/* This function is to find global error values that are the same through out
- * all library version. With wolfSSL having only one set of error codes the
- * return value is pretty straight forward. The only thing needed is all wolfSSL
- * error values are typically negative.
- *
- * Returns the error reason
- */
-int wolfSSL_ERR_GET_REASON(unsigned long err)
-{
- int ret = (int)err;
+#endif /* OPENSSL_EXTRA */
- WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON");
+#ifdef HAVE_EX_DATA_CRYPTO
+CRYPTO_EX_cb_ctx* crypto_ex_cb_ctx_session = NULL;
-#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
+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 WOLFSSL_FATAL_ERROR;
+ 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;
+}
- /* 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;
+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;
}
-
- 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)
+void crypto_ex_cb_setup_new_data(void *new_obj, CRYPTO_EX_cb_ctx* cb_ctx,
+ WOLFSSL_CRYPTO_EX_DATA* ex_data)
{
- WOLFSSL_ENTER("wolfSSL_alert_type_string_long");
-
- return AlertTypeToString(alertID);
+ 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);
+ }
}
-
-const char* wolfSSL_alert_desc_string_long(int alertID)
+int crypto_ex_cb_dup_data(const WOLFSSL_CRYPTO_EX_DATA *in,
+ WOLFSSL_CRYPTO_EX_DATA *out, CRYPTO_EX_cb_ctx* cb_ctx)
{
- WOLFSSL_ENTER("wolfSSL_alert_desc_string_long");
-
- return AlertTypeToString(alertID);
+ 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;
}
-#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}, \
+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);
}
+}
-#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}, \
+/**
+ * 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 WOLFSSL_FATAL_ERROR;
+ 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 WOLFSSL_FATAL_ERROR;
+ return idx;
+}
+#endif /* HAVE_EX_DATA_CRYPTO */
-/* 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)
+#ifdef HAVE_EX_DATA_CRYPTO
+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)
{
- 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
- };
+ WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index");
- enum IOMode {
- SS_READ = 0,
- SS_WRITE,
- SS_NEITHER
- };
+ return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_CTX, idx, arg,
+ new_func, dup_func, free_func);
+}
- enum SslState {
- ss_null_state = 0,
- ss_server_hellorequest,
- ss_server_helloverify,
- ss_server_helloretryrequest,
- ss_server_hello,
- ss_server_certificatestatus,
- ss_server_encryptedextensions,
- ss_server_sessionticket,
- ss_server_certrequest,
- ss_server_cert,
- ss_server_keyexchange,
- ss_server_hellodone,
- ss_server_changecipherspec,
- ss_server_finished,
- ss_server_keyupdate,
- ss_client_hello,
- ss_client_keyexchange,
- ss_client_cert,
- ss_client_changecipherspec,
- ss_client_certverify,
- ss_client_endofearlydata,
- ss_client_finished,
- ss_client_keyupdate,
- ss_handshake_done
- };
+/* Return 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");
- int protocol = 0;
- int cbmode = 0;
- int state = 0;
+ return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL, argValue, arg,
+ cb1, cb2, cb3);
+}
+#endif /* HAVE_EX_DATA_CRYPTO */
- WOLFSSL_ENTER("wolfSSL_state_string_long");
- if (ssl == NULL) {
- WOLFSSL_MSG("Null argument passed in");
- return NULL;
+#ifdef OPENSSL_EXTRA
+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;
+}
- /* 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;
+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 {
- cbmode = SS_NEITHER;
+#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 /* OPENSSL_EXTRA */
- /* Get protocol version */
- switch (ssl->version.major) {
- case SSLv3_MAJOR:
- switch (ssl->version.minor) {
- case SSLv3_MINOR:
- protocol = SSL_V3;
- break;
- case TLSv1_MINOR:
- protocol = TLS_V1;
- break;
- case TLSv1_1_MINOR:
- protocol = TLS_V1_1;
- break;
- case TLSv1_2_MINOR:
- protocol = TLS_V1_2;
- break;
- case TLSv1_3_MINOR:
- protocol = TLS_V1_3;
- break;
- default:
- protocol = UNKNOWN;
- }
- break;
- case DTLS_MAJOR:
- switch (ssl->version.minor) {
- case DTLS_MINOR:
- protocol = DTLS_V1;
- break;
- case DTLSv1_2_MINOR:
- protocol = DTLS_V1_2;
- break;
- case DTLSv1_3_MINOR:
- protocol = DTLS_V1_3;
- break;
- default:
- protocol = UNKNOWN;
- }
- break;
- default:
- protocol = UNKNOWN;
- }
-
- /* accept process */
- if (ssl->cbmode == SSL_CB_MODE_READ) {
- state = ssl->cbtype;
- switch (state) {
- case hello_request:
- state = ss_server_hellorequest;
- break;
- case client_hello:
- state = ss_client_hello;
- break;
- case server_hello:
- state = ss_server_hello;
- break;
- case hello_verify_request:
- state = ss_server_helloverify;
- break;
- case session_ticket:
- state = ss_server_sessionticket;
- break;
- case end_of_early_data:
- state = ss_client_endofearlydata;
- break;
- case hello_retry_request:
- state = ss_server_helloretryrequest;
- break;
- case encrypted_extensions:
- state = ss_server_encryptedextensions;
- break;
- case certificate:
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ss_client_cert;
- else if (ssl->options.side == WOLFSSL_CLIENT_END)
- state = ss_server_cert;
- else {
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- break;
- case server_key_exchange:
- state = ss_server_keyexchange;
- break;
- case certificate_request:
- state = ss_server_certrequest;
- break;
- case server_hello_done:
- state = ss_server_hellodone;
- break;
- case certificate_verify:
- state = ss_client_certverify;
- break;
- case client_key_exchange:
- state = ss_client_keyexchange;
- break;
- case finished:
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ss_client_finished;
- else if (ssl->options.side == WOLFSSL_CLIENT_END)
- state = ss_server_finished;
- else {
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- break;
- case certificate_status:
- state = ss_server_certificatestatus;
- break;
- case key_update:
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ss_client_keyupdate;
- else if (ssl->options.side == WOLFSSL_CLIENT_END)
- state = ss_server_keyupdate;
- else {
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- break;
- case change_cipher_hs:
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ss_client_changecipherspec;
- else if (ssl->options.side == WOLFSSL_CLIENT_END)
- state = ss_server_changecipherspec;
- else {
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- break;
- default:
- WOLFSSL_MSG("Unknown State");
- state = ss_null_state;
- }
- }
- else {
- /* Send process */
- if (ssl->options.side == WOLFSSL_SERVER_END)
- state = ssl->options.serverState;
- else
- state = ssl->options.clientState;
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
- 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;
- }
- }
+/* 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");
- if (protocol == UNKNOWN) {
- WOLFSSL_MSG("Unknown protocol");
- return "";
- }
- else {
- return OUTPUT_STR[state][protocol][cbmode];
- }
+ return wolfSSL_get_ex_data(ssl, 0);
}
-/*
- * Sets default PEM callback password if null is passed into
- * the callback parameter of a PEM_read_bio_* function.
+
+/* Set ex array 0 to have app data
+ *
+ * ssl WOLFSSL struct to set app data in
+ * arg data to be stored
*
- * Returns callback phrase size on success or WOLFSSL_FAILURE otherwise.
+ * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
*/
-int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key)
-{
- (void)w;
- WOLFSSL_ENTER("wolfSSL_PEM_def_callback");
+int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) {
+ WOLFSSL_ENTER("wolfSSL_set_app_data");
- /* 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;
- }
+ return wolfSSL_set_ex_data(ssl, 0, arg);
}
-#endif /* OPENSSL_EXTRA */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-static long wolf_set_options(long old_op, long op)
+int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data)
{
- /* 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");
+ 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;
+}
- if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) {
- WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2");
+#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 */
-#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");
+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;
+}
- if ((op & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) {
- WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2");
- }
-
- if ((op & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) {
- WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1");
- }
-
- if ((op & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) {
- WOLFSSL_MSG("\tSSL_OP_NO_TLSv1");
- }
-
- if ((op & WOLFSSL_OP_NO_SSLv3) == WOLFSSL_OP_NO_SSLv3) {
- WOLFSSL_MSG("\tSSL_OP_NO_SSLv3");
- }
-
- if ((op & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) ==
- WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) {
- WOLFSSL_MSG("\tWOLFSSL_OP_CIPHER_SERVER_PREFERENCE");
- }
-
- if ((op & WOLFSSL_OP_NO_COMPRESSION) == WOLFSSL_OP_NO_COMPRESSION) {
- #ifdef HAVE_LIBZ
- WOLFSSL_MSG("SSL_OP_NO_COMPRESSION");
- #else
- WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in");
- #endif
- }
-
- return old_op | op;
-}
+#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \
+ || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA)
-long wolfSSL_set_options(WOLFSSL* ssl, long op)
+/* returns the enum value associated with handshake state
+ *
+ * ssl the WOLFSSL structure to get state of
+ */
+int wolfSSL_get_state(const WOLFSSL* ssl)
{
- word16 haveRSA = 1;
- word16 havePSK = 0;
- int keySz = 0;
-
- WOLFSSL_ENTER("wolfSSL_set_options");
+ WOLFSSL_ENTER("wolfSSL_get_state");
if (ssl == NULL) {
- return 0;
+ WOLFSSL_MSG("Null argument passed in");
+ return WOLFSSL_FAILURE;
}
- ssl->options.mask = wolf_set_options(ssl->options.mask, op);
+ return ssl->options.handShakeState;
+}
+#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */
- 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;
- }
+#ifdef OPENSSL_EXTRA
+void wolfSSL_certs_clear(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_certs_clear");
- 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;
- }
+ if (ssl == NULL)
+ return;
- 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;
+ /* ctx still owns certificate, certChain, key, dh, and cm */
+ if (ssl->buffers.weOwnCert) {
+ FreeDer(&ssl->buffers.certificate);
+ ssl->buffers.weOwnCert = 0;
}
-
- if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) {
- if (ssl->version.minor == TLSv1_MINOR)
- ssl->version.minor = SSLv3_MINOR;
+ ssl->buffers.certificate = NULL;
+ if (ssl->buffers.weOwnCertChain) {
+ FreeDer(&ssl->buffers.certChain);
+ ssl->buffers.weOwnCertChain = 0;
}
-
- if ((ssl->options.mask & WOLFSSL_OP_NO_COMPRESSION)
- == WOLFSSL_OP_NO_COMPRESSION) {
- #ifdef HAVE_LIBZ
- ssl->options.usingCompression = 0;
+ ssl->buffers.certChain = NULL;
+#ifdef WOLFSSL_TLS13
+ ssl->buffers.certChainCnt = 0;
+#endif
+ if (ssl->buffers.weOwnKey) {
+ FreeDer(&ssl->buffers.key);
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ FreeDer(&ssl->buffers.keyMask);
#endif
+ ssl->buffers.weOwnKey = 0;
}
-
-#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
-
-
- /* 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;
+ ssl->buffers.key = NULL;
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ ssl->buffers.keyMask = NULL;
#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);
+ ssl->buffers.keyType = 0;
+ ssl->buffers.keyId = 0;
+ ssl->buffers.keyLabel = 0;
+ ssl->buffers.keySz = 0;
+ ssl->buffers.keyDevId = 0;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+ if (ssl->buffers.weOwnAltKey) {
+ FreeDer(&ssl->buffers.altKey);
+ #ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ FreeDer(&ssl->buffers.altKeyMask);
+ #endif
+ ssl->buffers.weOwnAltKey = 0;
}
-
- return ssl->options.mask;
+ ssl->buffers.altKey = NULL;
+#ifdef WOLFSSL_BLIND_PRIVATE_KEY
+ ssl->buffers.altKeyMask = NULL;
+#endif
+#endif /* WOLFSSL_DUAL_ALG_CERTS */
}
+#endif
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \
+ || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
-long wolfSSL_get_options(const WOLFSSL* ssl)
-{
- WOLFSSL_ENTER("wolfSSL_get_options");
- if(ssl == NULL)
- return WOLFSSL_FAILURE;
- return ssl->options.mask;
-}
-
-#if defined(HAVE_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 wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt)
{
- long total;
-
- WOLFSSL_ENTER("wolfSSL_clear_num_renegotiations");
- if (s == NULL)
- return 0;
+ WOLFSSL_ENTER("wolfSSL_ctrl");
+ if (ssl == NULL)
+ return BAD_FUNC_ARG;
- total = s->secure_rene_count;
- s->secure_rene_count = 0;
- return total;
+ 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;
}
-
-/* return the number of renegotiations since wolfSSL_new */
-long wolfSSL_total_renegotiations(WOLFSSL *s)
+long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt)
{
- WOLFSSL_ENTER("wolfSSL_total_renegotiations");
- return wolfSSL_num_renegotiations(s);
-}
+#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;
-/* return the number of renegotiations since wolfSSL_new */
-long wolfSSL_num_renegotiations(WOLFSSL* s)
-{
- if (s == NULL) {
- return 0;
+ switch (cmd) {
+ case SSL_CTRL_CHAIN:
+#ifdef SESSION_CERTS
+ {
+ /*
+ * We don't care about opt here because a copy of the certificate is
+ * stored anyway so increasing the reference counter is not necessary.
+ * Just check to make sure that it is set to one of the correct values.
+ */
+ WOLF_STACK_OF(WOLFSSL_X509)* sk = (WOLF_STACK_OF(WOLFSSL_X509)*) pt;
+ WOLFSSL_X509* x509;
+ int i;
+ if (opt != 0 && opt != 1) {
+ ret = WOLFSSL_FAILURE;
+ break;
+ }
+ /* Clear certificate chain */
+ FreeDer(&ctx->certChain);
+ if (sk) {
+ for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) {
+ x509 = wolfSSL_sk_X509_value(sk, i);
+ /* Prevent wolfSSL_CTX_add_extra_chain_cert from freeing cert */
+ if (wolfSSL_X509_up_ref(x509) != 1) {
+ WOLFSSL_MSG("Error increasing reference count");
+ continue;
+ }
+ if (wolfSSL_CTX_add_extra_chain_cert(ctx, x509) !=
+ WOLFSSL_SUCCESS) {
+ WOLFSSL_MSG("Error adding certificate to context");
+ /* Decrease reference count on failure */
+ wolfSSL_X509_free(x509);
+ x509 = NULL;
+ }
+ }
+ }
+ /* 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;
- return s->secure_rene_count;
-}
+#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 = 0;
+ } else {
+ WOLFSSL_MSG("Using Client's Cipher Preference.");
+ ctx->useClientOrder = 1;
+ }
+ #endif /* WOLFSSL_QT */
-/* 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 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);
-#ifdef OPENSSL_EXTRA
+#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
-long wolfSSL_clear_options(WOLFSSL* ssl, long opt)
-{
- WOLFSSL_ENTER("wolfSSL_clear_options");
- if(ssl == NULL)
- return WOLFSSL_FAILURE;
- ssl->options.mask &= ~opt;
- return ssl->options.mask;
+#ifdef HAVE_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;
}
-#ifdef HAVE_PK_CALLBACKS
-long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg)
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void))
{
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
- }
+ (void) ctx;
+ (void) cmd;
+ (void) fp;
+ WOLFSSL_STUB("wolfSSL_CTX_callback_ctrl");
+ return WOLFSSL_FAILURE;
- ssl->loggingCtx = arg;
- return WOLFSSL_SUCCESS;
}
-#endif /* HAVE_PK_CALLBACKS */
+#endif /* NO_WOLFSSL_STUB */
-#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)
+#ifndef NO_WOLFSSL_STUB
+long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx)
{
- return wolfSSL_SESSION_get_id((WOLFSSL_SESSION *)sess, sid_ctx_length);
+ return wolfSSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0L, NULL);
}
-int wolfSSL_SESSION_set1_id(WOLFSSL_SESSION *s,
- const unsigned char *sid, unsigned int sid_len)
+#endif
+
+/* Returns the verifyCallback from the ssl structure if successful.
+Returns NULL otherwise. */
+VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl)
{
- 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);
+ WOLFSSL_ENTER("wolfSSL_get_verify_callback");
+ if (ssl) {
+ return ssl->verifyCallback;
}
- return WOLFSSL_SUCCESS;
+ return NULL;
}
-int wolfSSL_SESSION_set1_id_context(WOLFSSL_SESSION *s,
- const unsigned char *sid_ctx, unsigned int sid_ctx_len)
+#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)
{
- if (s == NULL) {
- return WOLFSSL_FAILURE;
+ 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;
}
- if (sid_ctx_len > ID_LEN) {
- return WOLFSSL_FAILURE;
+ (void)out;
+
+ memSz = wolfSSL_BIO_get_len(bio);
+ if (memSz <= 0) {
+ WOLFSSL_MSG("wolfSSL_BIO_get_len() failure");
+ return NULL;
}
- s->sessionCtxSz = sid_ctx_len;
- if (sid_ctx != s->sessionCtx) {
- XMEMCPY(s->sessionCtx, sid_ctx, sid_ctx_len);
+
+ mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (mem == NULL) {
+ WOLFSSL_MSG("Malloc failure");
+ return NULL;
}
- return WOLFSSL_SUCCESS;
-}
+ if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) {
+ int extraBioMemSz;
+ int derLength;
-#endif
+ /* 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;
+ }
-/*** 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
+ /* Write extra data back into bio object if necessary. */
+ derLength = key->pkey_sz;
+ extraBioMemSz = (memSz - derLength);
+ if (extraBioMemSz > 0) {
+ int i;
+ int j = 0;
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type)
-{
- WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type");
+ extraBioMem = (unsigned char *)XMALLOC((size_t)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;
+ }
- if (s == NULL){
- return BAD_FUNC_ARG;
- }
+ for (i = derLength; i < memSz; i++) {
+ *(extraBioMem + j) = *(mem + i);
+ j++;
+ }
- 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_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 */
-long wolfSSL_get_tlsext_status_type(WOLFSSL *s)
-{
- TLSX* extension;
+#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */
- 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 */
-#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
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
+ defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || \
+ defined(WOLFSSL_QT) || defined(WOLFSSL_WPAS_SMALL)
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg)
+/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure.
+ * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL
+ * on fail */
+WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out,
+ unsigned char** in, long inSz)
{
- (void)s;
- (void)arg;
- WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts");
- return WOLFSSL_FAILURE;
+ WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP");
+ return d2iGenericKey(out, (const unsigned char**)in, inSz, 1);
}
-#endif
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg)
+#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)s;
- (void)arg;
- WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids");
- return WOLFSSL_FAILURE;
+ (void) pid;
+ return;
}
-#endif
-/*** TBD ***/
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg)
+#ifndef NO_FILESYSTEM
+/***TBD ***/
+void wolfSSL_print_all_errors_fp(XFILE fp)
{
- (void)s;
- (void)arg;
- WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids");
- return WOLFSSL_FAILURE;
+ (void)fp;
}
-#endif
+#endif /* !NO_FILESYSTEM */
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl)
+#endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX ||
+ HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH */
+
+/* Note: This is a huge section of API's - through
+ * wolfSSL_X509_OBJECT_get0_X509_CRL */
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
+
+#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)
{
- (void)ssl;
- WOLFSSL_STUB("SSL_get_privatekey");
- return NULL;
+ if (ossl_malloc != NULL)
+ return ossl_malloc(size, NULL, 0);
+ else
+ 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))
+static void OSSL_Free(void *ptr)
{
- (void)ctx;
- (void)dh;
- WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback");
+ if (ossl_free != NULL)
+ ossl_free(ptr, NULL, 0);
}
-#endif
-#ifndef NO_WOLFSSL_STUB
-/*** TBD ***/
-WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
+static void* OSSL_Realloc(void *ptr, size_t size)
{
- WOLFSSL_STUB("SSL_COMP_get_compression_methods");
- return NULL;
+ if (ossl_realloc != NULL)
+ return ossl_realloc(ptr, size, NULL, 0);
+ else
+ return NULL;
}
-#endif
-
+#endif /* USE_WOLFSSL_MEMORY && !WOLFSSL_DEBUG_MEMORY &&
+ * !WOLFSSL_STATIC_MEMORY */
-int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p)
+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_SSL_CIPHER_num");
- if (p == NULL) {
- return WOLFSSL_FATAL_ERROR;
+#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;
}
- return (int)p->num;
+#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
}
-WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(WOLFSSL_STACK* sk, int i)
+int wolfSSL_ERR_load_ERR_strings(void)
{
- WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_value");
- return (WOLFSSL_CIPHER*)wolfSSL_sk_value(sk, i);
+ return WOLFSSL_SUCCESS;
}
-#if !defined(NETOS)
-void ERR_load_SSL_strings(void)
+void wolfSSL_ERR_load_crypto_strings(void)
{
-
+ WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings");
+ /* Do nothing */
+ return;
}
-#endif
-#ifdef HAVE_OCSP
-long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp)
+int wolfSSL_FIPS_mode(void)
{
- if (s == NULL || resp == NULL)
- return 0;
-
- *resp = s->ocspResp;
- return s->ocspRespSz;
+#ifdef HAVE_FIPS
+ return 1;
+#else
+ return 0;
+#endif
}
-long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp,
- int len)
+int wolfSSL_FIPS_mode_set(int r)
{
- if (s == NULL)
+#ifdef HAVE_FIPS
+ if (r == 0) {
+ WOLFSSL_MSG("Cannot disable FIPS at runtime.");
return WOLFSSL_FAILURE;
-
- s->ocspResp = resp;
- s->ocspRespSz = len;
-
+ }
return WOLFSSL_SUCCESS;
+#else
+ if (r == 0) {
+ return WOLFSSL_SUCCESS;
+ }
+ WOLFSSL_MSG("Cannot enable FIPS. This isn't the wolfSSL FIPS code.");
+ return WOLFSSL_FAILURE;
+#endif
}
-#endif /* HAVE_OCSP */
-#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)
+int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits)
{
- if (c == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 ))
- return BAD_FUNC_ARG;
+ int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
+ WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits");
- return wolfSSL_CTX_UseMaxFragment(c, mode);
+ #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;
}
-/**
- * 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)
+
+#ifdef HAVE_SNI
+int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name)
{
- if (s == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 ))
- return BAD_FUNC_ARG;
+ 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;
+}
- return wolfSSL_UseMaxFragment(s, mode);
+#ifndef NO_WOLFSSL_SERVER
+/* May be called by server to get the requested accepted name and by the client
+ * to get the requested name. */
+const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
+{
+ void * serverName = NULL;
+ if (ssl == NULL)
+ return NULL;
+ TLSX_SNI_GetRequest(ssl->extensions, type, &serverName,
+ !wolfSSL_is_server(ssl));
+ return (const char *)serverName;
}
-#endif /* NO_WOLFSSL_CLIENT */
-#endif /* HAVE_MAX_FRAGMENT */
+#endif
-#endif /* OPENSSL_EXTRA */
+#endif /* HAVE_SNI */
-#ifdef WOLFSSL_HAVE_TLS_UNIQUE
-size_t wolfSSL_get_finished(const WOLFSSL *ssl, void *buf, size_t count)
+WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
{
- byte len = 0;
-
- WOLFSSL_ENTER("wolfSSL_get_finished");
+ 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;
- if (!ssl || !buf || count < TLS_FINISHED_SZ) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
+ if (ctx->suites == NULL) {
+ /* suites */
+ if (AllocateCtxSuites(ctx) != 0)
+ return NULL;
+ InitSSL_CTX_Suites(ctx);
}
- 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);
+ wolfSSL_RefWithMutexInc(&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;
}
- return len;
-}
+#else
+ (void)ret;
+#endif
+ if (ssl->ctx != NULL)
+ wolfSSL_CTX_free(ssl->ctx);
+ ssl->ctx = ctx;
-size_t wolfSSL_get_peer_finished(const WOLFSSL *ssl, void *buf, size_t count)
-{
- byte len = 0;
- WOLFSSL_ENTER("wolfSSL_get_peer_finished");
+#ifndef NO_CERTS
+#ifdef WOLFSSL_COPY_CERT
+ /* If WOLFSSL_COPY_CERT defined, always make new copy of cert from ctx */
+ if (ctx->certificate != NULL) {
+ if (ssl->buffers.certificate != NULL) {
+ FreeDer(&ssl->buffers.certificate);
+ ssl->buffers.certificate = NULL;
+ }
+ ret = AllocCopyDer(&ssl->buffers.certificate, ctx->certificate->buffer,
+ ctx->certificate->length, ctx->certificate->type,
+ ctx->certificate->heap);
+ if (ret != 0) {
+ ssl->buffers.weOwnCert = 0;
+ return NULL;
+ }
- if (!ssl || !buf || count < TLS_FINISHED_SZ) {
- WOLFSSL_MSG("Bad parameter");
- return WOLFSSL_FAILURE;
+ ssl->buffers.weOwnCert = 1;
}
+ if (ctx->certChain != NULL) {
+ if (ssl->buffers.certChain != NULL) {
+ FreeDer(&ssl->buffers.certChain);
+ ssl->buffers.certChain = NULL;
+ }
+ ret = AllocCopyDer(&ssl->buffers.certChain, ctx->certChain->buffer,
+ ctx->certChain->length, ctx->certChain->type,
+ ctx->certChain->heap);
+ if (ret != 0) {
+ ssl->buffers.weOwnCertChain = 0;
+ return NULL;
+ }
- 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);
+ ssl->buffers.weOwnCertChain = 1;
}
-
- 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)
-{
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
+#else
+ /* ctx owns certificate, certChain and key */
+ ssl->buffers.certificate = ctx->certificate;
+ ssl->buffers.certChain = ctx->certChain;
+#endif
+#ifdef WOLFSSL_TLS13
+ ssl->buffers.certChainCnt = ctx->certChainCnt;
+#endif
+#ifndef WOLFSSL_BLIND_PRIVATE_KEY
+#ifdef WOLFSSL_COPY_KEY
+ if (ctx->privateKey != NULL) {
+ if (ssl->buffers.key != NULL) {
+ FreeDer(&ssl->buffers.key);
+ ssl->buffers.key = NULL;
+ }
+ ret = AllocCopyDer(&ssl->buffers.key, ctx->privateKey->buffer,
+ ctx->privateKey->length, ctx->privateKey->type,
+ ctx->privateKey->heap);
+ if (ret != 0) {
+ ssl->buffers.weOwnKey = 0;
+ return NULL;
+ }
+ ssl->buffers.weOwnKey = 1;
}
-
- return ssl->peerVerifyRet;
-}
+ else {
+ ssl->buffers.key = ctx->privateKey;
+ }
+#else
+ ssl->buffers.key = ctx->privateKey;
#endif
-
-#ifdef OPENSSL_EXTRA
-
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of accepts attempted by CTX in it's lifetime */
-long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_STUB("wolfSSL_CTX_sess_accept");
- (void)ctx;
- return 0;
-}
+#else
+ if (ctx->privateKey != NULL) {
+ ret = AllocCopyDer(&ssl->buffers.key, ctx->privateKey->buffer,
+ ctx->privateKey->length, ctx->privateKey->type,
+ ctx->privateKey->heap);
+ if (ret != 0) {
+ return NULL;
+ }
+ /* Blind the private key for the SSL with new random mask. */
+ wolfssl_priv_der_blind_toggle(ssl->buffers.key, ctx->privateKeyMask);
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key,
+ &ssl->buffers.keyMask);
+ if (ret != 0) {
+ return NULL;
+ }
+ }
#endif
-
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of connects attempted CTX in it's lifetime */
-long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_STUB("wolfSSL_CTX_sess_connect");
- (void)ctx;
- return 0;
-}
+ ssl->buffers.keyType = ctx->privateKeyType;
+ ssl->buffers.keyId = ctx->privateKeyId;
+ ssl->buffers.keyLabel = ctx->privateKeyLabel;
+ ssl->buffers.keySz = ctx->privateKeySz;
+ ssl->buffers.keyDevId = ctx->privateKeyDevId;
+ /* flags indicating what certs/keys are available */
+ ssl->options.haveRSA = ctx->haveRSA;
+ ssl->options.haveDH = ctx->haveDH;
+ ssl->options.haveECDSAsig = ctx->haveECDSAsig;
+ ssl->options.haveECC = ctx->haveECC;
+ ssl->options.haveStaticECC = ctx->haveStaticECC;
+ ssl->options.haveFalconSig = ctx->haveFalconSig;
+ ssl->options.haveDilithiumSig = ctx->haveDilithiumSig;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+#ifndef WOLFSSL_BLIND_PRIVATE_KEY
+ ssl->buffers.altKey = ctx->altPrivateKey;
+#else
+ if (ctx->altPrivateKey != NULL) {
+ ret = AllocCopyDer(&ssl->buffers.altkey, ctx->altPrivateKey->buffer,
+ ctx->altPrivateKey->length, ctx->altPrivateKey->type,
+ ctx->altPrivateKey->heap);
+ if (ret != 0) {
+ return NULL;
+ }
+ /* Blind the private key for the SSL with new random mask. */
+ wolfssl_priv_der_unblind(ssl->buffers.altKey, ctx->altPrivateKeyMask);
+ ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey,
+ &ssl->buffers.altKeyMask);
+ if (ret != 0) {
+ return NULL;
+ }
+ }
+#endif
+ 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
-#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;
+ return ssl->ctx;
}
-#endif
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of connects completed by CTX in it's lifetime */
-long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx)
+VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx)
{
- WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good");
- (void)ctx;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback");
+ if(ctx)
+ return ctx->verifyCallback;
+ return NULL;
}
-#endif
-
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of renegotiation accepts attempted by CTX */
-long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx)
+#ifdef HAVE_SNI
+/* this is a compatibility function, consider using
+ * wolfSSL_CTX_set_servername_callback */
+int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
+ CallbackSniRecv cb)
{
- WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate");
- (void)ctx;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback");
+ if (ctx) {
+ ctx->sniRecvCb = cb;
+ return WOLFSSL_SUCCESS;
+ }
+ return WOLFSSL_FAILURE;
}
-#endif
+#endif /* HAVE_SNI */
-#ifndef NO_WOLFSSL_STUB
-/* shows the number of renegotiation accepts attempted by CTX */
-long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx)
-{
- WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate");
- (void)ctx;
- return 0;
+#ifndef NO_BIO
+void wolfSSL_ERR_load_BIO_strings(void) {
+ WOLFSSL_ENTER("wolfSSL_ERR_load_BIO_strings");
+ /* do nothing */
}
#endif
-
#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx)
+/* Set THREADID callback, return 1 on success, 0 on error */
+int wolfSSL_THREADID_set_callback(
+ void(*threadid_func)(WOLFSSL_CRYPTO_THREADID*))
{
- WOLFSSL_STUB("wolfSSL_CTX_sess_hits");
- (void)ctx;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_THREADID_set_callback");
+ WOLFSSL_STUB("CRYPTO_THREADID_set_callback");
+ (void)threadid_func;
+ return 1;
}
#endif
-
#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx)
+void wolfSSL_THREADID_set_numeric(void* id, unsigned long val)
{
- WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits");
- (void)ctx;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric");
+ WOLFSSL_STUB("CRYPTO_THREADID_set_numeric");
+ (void)id;
+ (void)val;
+ return;
}
#endif
+#endif /* OPENSSL_ALL || OPENSSL_EXTRA */
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx)
+#ifdef HAVE_SNI
+
+void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb)
{
- WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full");
- (void)ctx;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback");
+ if (ctx)
+ ctx->sniRecvCb = cb;
}
-#endif
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx)
+int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg)
{
- WOLFSSL_STUB("wolfSSL_CTX_sess_misses");
- (void)ctx;
- return 0;
+ WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg");
+ if (ctx) {
+ ctx->sniRecvCbArg = arg;
+ return WOLFSSL_SUCCESS;
+ }
+ return WOLFSSL_FAILURE;
}
-#endif
+#endif /* HAVE_SNI */
-#ifndef NO_WOLFSSL_STUB
-long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx)
+#if defined(OPENSSL_EXTRA)
+
+int wolfSSL_CRYPTO_memcmp(const void *a, const void *b, size_t size)
{
- WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts");
- (void)ctx;
- return 0;
+ if (!a || !b)
+ return 0;
+ return ConstantCompare((const byte*)a, (const byte*)b, (int)size);
}
-#endif
-
-/* Return the total number of sessions */
-long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx)
+unsigned long wolfSSL_ERR_peek_last_error(void)
{
- word32 total = 0;
+ WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error");
- WOLFSSL_ENTER("wolfSSL_CTX_sess_number");
- (void)ctx;
+#ifdef WOLFSSL_HAVE_ERROR_QUEUE
+ {
+ int ret;
-#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");
+ if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) {
+ WOLFSSL_MSG("Issue peeking at error node in queue");
+ return 0;
+ }
+ if (ret == -WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER))
+ return (WOLFSSL_ERR_LIB_PEM << 24) | -WC_NO_ERR_TRACE(WOLFSSL_PEM_R_NO_START_LINE_E);
+ #if defined(WOLFSSL_PYTHON)
+ if (ret == ASN1_R_HEADER_TOO_LONG)
+ return (WOLFSSL_ERR_LIB_ASN1 << 24) | -WC_NO_ERR_TRACE(WOLFSSL_ASN1_R_HEADER_TOO_LONG_E);
+ #endif
+ return (unsigned long)ret;
}
#else
- WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats");
+ return (unsigned long)(0 - NOT_COMPILED_IN);
#endif
-
- return (long)total;
}
+#endif /* OPENSSL_EXTRA */
-#ifndef NO_CERTS
-long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
+int wolfSSL_version(WOLFSSL* ssl)
{
- 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;
+ 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;
+ }
}
-
- 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 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;
}
}
- else {
- long chainSz = 0;
- int idx = 0;
+ return WOLFSSL_FAILURE;
+}
- /* 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;
- }
+WOLFSSL_CTX* wolfSSL_get_SSL_CTX(const WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_get_SSL_CTX");
+ return ssl->ctx;
+}
- /* adding cert to existing chain */
- if (ctx->certChain != NULL && ctx->certChain->length > 0) {
- chainSz += ctx->certChain->length;
- }
- chainSz += OPAQUE24_LEN + derSz;
+#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \
+ defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX)
- chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER);
- if (chain == NULL) {
- WOLFSSL_MSG("Memory Error");
- return WOLFSSL_FAILURE;
- }
+/* 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 (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
+ if (!ssl) {
+ return WOLFSSL_FAILURE;
+ }
- FreeDer(&ctx->certChain);
- ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap);
- if (ret == 0) {
- XMEMCPY(ctx->certChain->buffer, chain, idx);
+ 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
}
- /* 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;
+ WOLFSSL_LEAVE("wolfSSL_get_verify_mode", mode);
+ return mode;
}
-
-long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg)
+int wolfSSL_CTX_get_verify_mode(const WOLFSSL_CTX* ctx)
{
- if (ctx == NULL || ctx->cm == NULL) {
+ int mode = 0;
+ WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode");
+
+ if (!ctx) {
return WOLFSSL_FAILURE;
}
- ctx->cm->ocspIOCtx = arg;
- return WOLFSSL_SUCCESS;
-}
-
-#endif /* !NO_CERTS */
-
-int wolfSSL_get_read_ahead(const WOLFSSL* ssl)
-{
- if (ssl == NULL) {
- 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
}
- return ssl->readAhead;
+ WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode);
+ return mode;
}
+#endif
-int wolfSSL_set_read_ahead(WOLFSSL* ssl, int v)
+#ifdef WOLFSSL_JNI
+
+int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr)
{
- if (ssl == NULL) {
- return WOLFSSL_FAILURE;
+ WOLFSSL_ENTER("wolfSSL_set_jobject");
+ if (ssl != NULL)
+ {
+ ssl->jObjectRef = objPtr;
+ return WOLFSSL_SUCCESS;
}
-
- ssl->readAhead = (byte)v;
-
- return WOLFSSL_SUCCESS;
+ return WOLFSSL_FAILURE;
}
-
-int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx)
+void* wolfSSL_get_jobject(WOLFSSL* ssl)
{
- if (ctx == NULL) {
- return WOLFSSL_FAILURE;
- }
-
- return ctx->readAhead;
+ WOLFSSL_ENTER("wolfSSL_get_jobject");
+ if (ssl != NULL)
+ return ssl->jObjectRef;
+ return NULL;
}
+#endif /* WOLFSSL_JNI */
-int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v)
+
+#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 WOLFSSL_FAILURE;
+ return BAD_FUNC_ARG;
}
- ctx->readAhead = (byte)v;
-
- return WOLFSSL_SUCCESS;
+ return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL,
+ events, maxEvents, flags, eventCount);
}
-
-long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx,
- void* arg)
+int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags)
{
- if (ctx == NULL) {
- return WOLFSSL_FAILURE;
+ int ret, eventCount = 0;
+ WOLF_EVENT* events[1];
+
+ if (ssl == NULL) {
+ return BAD_FUNC_ARG;
}
- ctx->userPRFArg = arg;
- return WOLFSSL_SUCCESS;
+ 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 */
-#endif /* OPENSSL_EXTRA */
+#ifdef OPENSSL_EXTRA
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
-int wolfSSL_sk_num(const WOLFSSL_STACK* sk)
+static int peek_ignore_err(int err)
{
- WOLFSSL_ENTER("wolfSSL_sk_num");
- if (sk == NULL)
- return 0;
- return (int)sk->num;
+ switch(err) {
+ case -WC_NO_ERR_TRACE(WANT_READ):
+ case -WC_NO_ERR_TRACE(WANT_WRITE):
+ case -WC_NO_ERR_TRACE(ZERO_RETURN):
+ case -WOLFSSL_ERROR_ZERO_RETURN:
+ case -WC_NO_ERR_TRACE(SOCKET_PEER_CLOSED_E):
+ case -WC_NO_ERR_TRACE(SOCKET_ERROR_E):
+ return 1;
+ default:
+ return 0;
+ }
}
-void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i)
+unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line,
+ const char **data, int *flags)
{
- WOLFSSL_ENTER("wolfSSL_sk_value");
+ unsigned long err;
- for (; sk != NULL && i > 0; i--)
- sk = sk->next;
- if (sk == NULL)
- return NULL;
+ WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data");
+ err = wc_PeekErrorNodeLineData(file, line, data, flags, peek_ignore_err);
- 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;
- }
+ if (err == -WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER))
+ return (WOLFSSL_ERR_LIB_PEM << 24) | -WC_NO_ERR_TRACE(WOLFSSL_PEM_R_NO_START_LINE_E);
+#ifdef OPENSSL_ALL
+ /* PARSE_ERROR is returned if an HTTP request is detected. */
+ else if (err == -WC_NO_ERR_TRACE(PARSE_ERROR))
+ return (WOLFSSL_ERR_LIB_SSL << 24) | -WC_NO_ERR_TRACE(PARSE_ERROR) /* SSL_R_HTTP_REQUEST */;
+#endif
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON)
+ else if (err == ASN1_R_HEADER_TOO_LONG)
+ return (WOLFSSL_ERR_LIB_ASN1 << 24) | -WC_NO_ERR_TRACE(WOLFSSL_ASN1_R_HEADER_TOO_LONG_E);
+#endif
+ return err;
}
+#endif
-/* copies over data of "in" to "out" */
-static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out)
-{
- if (in == NULL || out == NULL)
- return;
-
- *out = *in;
-}
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \
+ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk)
+#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;
- WOLFSSL_STACK* ret = NULL;
- WOLFSSL_STACK* last = NULL;
-
- WOLFSSL_ENTER("wolfSSL_sk_dup");
-
- while (sk) {
- WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap);
-
- if (!cur) {
- WOLFSSL_MSG("wolfSSL_sk_new_node error");
- goto error;
- }
-
- if (!ret) {
- /* Set first node */
- ret = cur;
- }
-
- if (last) {
- last->next = cur;
- }
-
- XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK));
-
- /* We will allocate new memory for this */
- XMEMSET(&cur->data, 0, sizeof(cur->data));
- cur->next = NULL;
-
- 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;
- }
+ if (ipa == NULL)
+ return NULL;
- sk = sk->next;
- last = cur;
+ if (XSTRSTR(ipa, ":") != NULL) {
+ af = WOLFSSL_IP6;
+ ipaSz = WOLFSSL_IP6_ADDR_LEN;
}
- return ret;
-error:
- if (ret) {
- wolfSSL_sk_GENERAL_NAME_free(ret);
+ buf[WOLFSSL_IP6_ADDR_LEN] = '\0';
+ if (XINET_PTON(af, ipa, (void*)buf) != 1) {
+ WOLFSSL_MSG("Error parsing IP address");
+ return NULL;
}
- return NULL;
-}
-
-
-WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* sk)
-{
- 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;
+ 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;
}
-
- 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;
-}
-/* Free the just the stack structure */
-void wolfSSL_sk_free(WOLFSSL_STACK* sk)
-{
- WOLFSSL_ENTER("wolfSSL_sk_free");
-
- while (sk != NULL) {
- WOLFSSL_STACK* next = sk->next;
- XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
- sk = next;
- }
+ return ret;
}
+#endif /* !WOLFSSL_USER_IO */
-/* Frees each node in the stack and frees the stack.
- */
-void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk,
- void (*f) (void*))
+/* Is the specified cipher suite a fake one used an an extension proxy? */
+static WC_INLINE int SCSV_Check(byte suite0, byte suite)
{
- WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free");
- wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
+ (void)suite0;
+ (void)suite;
+#ifdef HAVE_RENEGOTIATION_INDICATION
+ if (suite0 == CIPHER_BYTE && suite == TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
+ return 1;
+#endif
+ return 0;
}
-/* return 1 on success 0 on fail */
-int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic)
-{
- WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push");
-
- return wolfSSL_sk_push(sk, generic);
-}
-void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk)
+static WC_INLINE int sslCipherMinMaxCheck(const WOLFSSL *ssl, byte suite0,
+ byte suite)
{
- wolfSSL_sk_free(sk);
+ 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;
+ }
}
-/* 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.
+/* returns a pointer to internal cipher suite list. Should not be free'd by
+ * caller.
*/
-void* wolfssl_sk_pop_type(WOLFSSL_STACK* sk, WOLF_STACK_TYPE type)
+WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl)
{
- 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;
- }
+ 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
- /* Decrement count as long as we thought we had nodes. */
- if (sk->num > 0) {
- sk->num -= 1;
- }
- }
+ WOLFSSL_ENTER("wolfSSL_get_ciphers_compat");
+ if (ssl == NULL)
+ return NULL;
- return data;
-}
+ suites = WOLFSSL_SUITES(ssl);
+ if (suites == NULL)
+ return NULL;
-/* Free all nodes in a stack including the pushed objects */
-void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk,
- wolfSSL_sk_freefunc func)
-{
- WOLFSSL_ENTER("wolfSSL_sk_pop_free");
+ /* check if stack needs populated */
+ if (ssl->suitesStack == NULL) {
+ int i;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ int j;
- if (sk == NULL) {
- /* pop_free can be called with NULL, do not print bad argument */
- return;
- }
- #if defined(WOLFSSL_QT)
- /* In Qt v15.5, it calls OPENSSL_sk_free(xxx, OPENSSL_sk_free).
- * By using OPENSSL_sk_free for free causes access violation.
- * Therefore, switching free func to wolfSSL_ACCESS_DESCRIPTION_free
- * is needed even the func isn't NULL.
- */
- if (sk->type == STACK_TYPE_ACCESS_DESCRIPTION) {
- func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
- }
- #endif
- if (func == NULL) {
- switch(sk->type) {
- case STACK_TYPE_ACCESS_DESCRIPTION:
- #if defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free;
- #endif
- break;
- case STACK_TYPE_X509:
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_free;
- break;
- case STACK_TYPE_X509_OBJ:
- #ifdef OPENSSL_ALL
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_OBJECT_free;
- #endif
- break;
- case STACK_TYPE_OBJ:
- func = (wolfSSL_sk_freefunc)wolfSSL_ASN1_OBJECT_free;
- break;
- case STACK_TYPE_DIST_POINT:
- #ifdef OPENSSL_EXTRA
- func = (wolfSSL_sk_freefunc)wolfSSL_DIST_POINT_free;
- #endif
- break;
- case STACK_TYPE_GEN_NAME:
- func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_NAME_free;
- break;
- case STACK_TYPE_STRING:
- #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
- defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_WOLFSSL_STRING_free;
- #endif
- break;
- case STACK_TYPE_X509_NAME:
- #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
- && !defined(WOLFCRYPT_ONLY)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_free;
- #endif
- break;
- case STACK_TYPE_X509_NAME_ENTRY:
- #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
- && !defined(WOLFCRYPT_ONLY)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_ENTRY_free;
- #endif
- break;
- case STACK_TYPE_X509_EXT:
- #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_EXTENSION_free;
- #endif
- break;
- case STACK_TYPE_X509_REQ_ATTR:
- #if defined(OPENSSL_ALL) && \
- (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ))
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_ATTRIBUTE_free;
- #endif
- break;
- case STACK_TYPE_CONF_VALUE:
- #if defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509V3_conf_free;
- #endif
- break;
- case STACK_TYPE_X509_INFO:
- #if defined(OPENSSL_ALL)
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_INFO_free;
- #endif
- break;
- case STACK_TYPE_BIO:
-#if !defined(NO_BIO) && defined(OPENSSL_EXTRA)
- func = (wolfSSL_sk_freefunc)wolfSSL_BIO_vfree;
-#endif
- break;
- case STACK_TYPE_BY_DIR_entry:
-#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
- func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_entry_free;
-#endif
- break;
- case STACK_TYPE_BY_DIR_hash:
-#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
- func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_HASH_free;
-#endif
- break;
- case STACK_TYPE_X509_CRL:
-#if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL))
- func = (wolfSSL_sk_freefunc)wolfSSL_X509_CRL_free;
+ /* 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
- break;
- case STACK_TYPE_CIPHER:
- case STACK_TYPE_NULL:
- default:
- break;
- }
- }
+ 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;
+ }
- while (sk != NULL) {
- WOLFSSL_STACK* next = sk->next;
+ add = wolfSSL_sk_new_node(ssl->heap);
+ if (add != NULL) {
+ add->type = STACK_TYPE_CIPHER;
+ add->data.cipher.cipherSuite0 = suites->suites[i];
+ add->data.cipher.cipherSuite = suites->suites[i+1];
+ add->data.cipher.ssl = ssl;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ for (j = 0; j < cipherSz; j++) {
+ if (cipher_names[j].cipherSuite0 ==
+ add->data.cipher.cipherSuite0 &&
+ cipher_names[j].cipherSuite ==
+ add->data.cipher.cipherSuite) {
+ add->data.cipher.offset = (unsigned long)j;
+ break;
+ }
+ }
+#endif
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ /* in_stack is checked in wolfSSL_CIPHER_description */
+ add->data.cipher.in_stack = 1;
+ #endif
- if (func != NULL) {
- if (sk->type != STACK_TYPE_CIPHER)
- func(sk->data.generic);
+ add->next = ret;
+ if (ret != NULL) {
+ add->num = ret->num + 1;
+ }
+ else {
+ add->num = 1;
+ }
+ ret = add;
+ }
}
- XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL);
- sk = next;
+ ((WOLFSSL*)ssl)->suitesStack = ret;
}
+ return ssl->suitesStack;
}
-
-/* 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)
+#endif /* OPENSSL_EXTRA || OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+#ifdef OPENSSL_ALL
+/* returned pointer is to an internal element in WOLFSSL struct and should not
+ * be free'd. It gets free'd when the WOLFSSL struct is free'd. */
+WOLF_STACK_OF(WOLFSSL_CIPHER)* wolfSSL_get_client_ciphers(WOLFSSL* ssl)
{
- WOLFSSL_STACK* sk;
+ WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL;
+ const CipherSuiteInfo* cipher_names = GetCipherNames();
+ int cipherSz = GetCipherNamesSize();
+ const Suites* suites;
- /* 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");
+ WOLFSSL_ENTER("wolfSSL_get_client_ciphers");
+
+ if (ssl == NULL) {
+ return NULL;
}
- else {
- /* Clear node and set type. */
- XMEMSET(sk, 0, sizeof(WOLFSSL_STACK));
- sk->type = type;
+
+ /* return NULL if is client side */
+ if (wolfSSL_is_server(ssl) == 0) {
+ return NULL;
}
- return sk;
-}
+ suites = ssl->clSuites;
+ if (suites == NULL) {
+ WOLFSSL_MSG("No client suites stored");
+ }
+ else if (ssl->clSuitesStack != NULL) {
+ ret = ssl->clSuitesStack;
+ }
+ else { /* generate cipher suites stack if not already done */
+ int i;
+ int j;
-/* Creates and returns a new null stack. */
-WOLFSSL_STACK* wolfSSL_sk_new_null(void)
-{
- WOLFSSL_ENTER("wolfSSL_sk_new_null");
+ ret = wolfSSL_sk_new_node(ssl->heap);
+ if (ret != NULL) {
+ ret->type = STACK_TYPE_CIPHER;
- return wolfssl_sk_new_type(STACK_TYPE_NULL);
-}
+ /* higher priority of cipher suite will be on top of stack */
+ for (i = suites->suiteSz - 2; i >= 0; i -= 2) {
+ WOLFSSL_CIPHER cipher;
-int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk)
-{
- if (sk == NULL)
- return 0;
- return (int)sk->num;
-}
+ /* 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;
+ }
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+ cipher.cipherSuite0 = suites->suites[i];
+ cipher.cipherSuite = suites->suites[i+1];
+ cipher.ssl = ssl;
+ for (j = 0; j < cipherSz; j++) {
+ if (cipher_names[j].cipherSuite0 ==
+ cipher.cipherSuite0 &&
+ cipher_names[j].cipherSuite ==
+ cipher.cipherSuite) {
+ cipher.offset = (unsigned long)j;
+ break;
+ }
+ }
-#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;
+ /* in_stack is checked in wolfSSL_CIPHER_description */
+ cipher.in_stack = 1;
-#ifdef HAVE_EXT_CACHE
- ctx->get_sess_cb = f;
-#else
- (void)f;
-#endif
+ if (wolfSSL_sk_CIPHER_push(ret, &cipher) <= 0) {
+ WOLFSSL_MSG("Error pushing client cipher onto stack");
+ wolfSSL_sk_CIPHER_free(ret);
+ ret = NULL;
+ break;
+ }
+ }
+ }
+ ssl->clSuitesStack = ret;
+ }
+ return ret;
}
+#endif /* OPENSSL_ALL */
-void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx,
- int (*f)(WOLFSSL*, WOLFSSL_SESSION*))
+#if defined(OPENSSL_EXTRA) || 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;
+ return 0;
-#ifdef HAVE_EXT_CACHE
- ctx->new_sess_cb = f;
-#else
- (void)f;
-#endif
+ return ctx->timeout;
}
-void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*,
- WOLFSSL_SESSION*))
+
+/* returns the time in seconds of the current timeout */
+long wolfSSL_get_timeout(WOLFSSL* ssl)
{
- if (ctx == NULL)
- return;
+ WOLFSSL_ENTER("wolfSSL_get_timeout");
-#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
- ctx->rem_sess_cb = f;
-#else
- (void)f;
-#endif
+ 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)
-/*
- *
- * 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)
+#ifdef HAVE_ECC
+int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh)
{
- int size = 0;
-#ifdef HAVE_EXT_CACHE
- int idx = 0;
-#ifdef SESSION_CERTS
- int i;
-#endif
-
- WOLFSSL_ENTER("wolfSSL_i2d_SSL_SESSION");
+ WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh");
- sess = ClientSessionToSession(sess);
- if (sess == NULL) {
+ if (ctx == NULL || ecdh == 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;
+ ctx->ecdhCurveOID = (word32)ecdh->group->curve_oid;
+
+ return WOLFSSL_SUCCESS;
+}
#endif
+#ifndef NO_BIO
+WOLFSSL_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;
- if (p != NULL) {
- unsigned char *data;
+ return s->biord;
+}
+WOLFSSL_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;
- 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;
+ return s->biowr;
+}
+#endif /* !NO_BIO */
+
+#ifndef NO_TLS
+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
- 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;
+ 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);
+}
+#endif /* !NO_TLS */
- (void)sess;
- (void)p;
-#ifdef HAVE_EXT_CACHE
- (void)idx;
+#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 size;
+ return !wolfSSL_is_init_finished(ssl);
}
-
-/* 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)
+int wolfSSL_SSL_in_before(const WOLFSSL *ssl)
{
- 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 */
+ WOLFSSL_ENTER("wolfSSL_SSL_in_before");
- (void)p;
- (void)i;
- (void)ret;
- (void)sess;
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
-#ifdef HAVE_EXT_CACHE
- if (p == NULL || *p == NULL)
- return NULL;
+ return ssl->options.handShakeState == NULL_STATE;
+}
- s = wolfSSL_SESSION_new();
- if (s == NULL)
- return NULL;
+int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl)
+{
+ WOLFSSL_ENTER("wolfSSL_SSL_in_connect_init");
- idx = 0;
- data = (byte*)*p;
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
- /* side | bornOn | timeout | sessionID len */
- if (i < OPAQUE8_LEN + OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) {
- ret = BUFFER_ERROR;
- goto end;
+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
+ return ssl->options.connectState > CONNECT_BEGIN &&
+ ssl->options.connectState < SECOND_REPLY_DONE;
}
- 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;
+ return ssl->options.acceptState > ACCEPT_BEGIN &&
+ ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE;
+}
- /* altSessionID */
- if (s->haveAltSessionID) {
- if (i - idx < ID_LEN) {
- ret = BUFFER_ERROR;
- goto end;
- }
- XMEMCPY(s->altSessionID, data + idx, ID_LEN); idx += ID_LEN;
- }
+#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
-#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;
+/* 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];
+ WC_DECLARE_VAR(evpCtx, WOLFSSL_EVP_CIPHER_CTX, 1, 0);
+ WOLFSSL_HMAC_CTX hmacCtx;
+ unsigned int mdSz = 0;
+ int len = 0;
+ int ret = WOLFSSL_TICKET_RET_FATAL;
+ int res;
+ int totalSz = 0;
- /* 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++];
+ (void)ctx;
- /* 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;
+ 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_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;
+#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
- 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;
+ /* 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");
+ WC_FREE_VAR_EX(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return WOLFSSL_TICKET_RET_FATAL;
}
-#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;
+ 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;
}
- 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;
+ if (wolfSSL_HMAC_size(&hmacCtx) > WOLFSSL_TICKET_MAC_SZ) {
+ WOLFSSL_MSG("Ticket cipher MAC size 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;
+ 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;
- }
- 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;
+ /* 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;
- *p += idx;
+ /* 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 && (sess == NULL || *sess != s)) {
- wolfSSL_FreeSession(NULL, s);
- s = NULL;
- }
-#endif /* HAVE_EXT_CACHE */
- return s;
+
+ (void)wc_HmacFree(&hmacCtx.hmac);
+ (void)wolfSSL_EVP_CIPHER_CTX_cleanup(evpCtx);
+
+ WC_FREE_VAR_EX(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
}
-/* Check if there is a session ticket associated with this WOLFSSL_SESSION.
- *
- * sess - pointer to WOLFSSL_SESSION struct
+/* Set the callback to use when encrypting/decrypting tickets.
*
- * Returns 1 if has session ticket, otherwise 0 */
-int wolfSSL_SESSION_has_ticket(const WOLFSSL_SESSION* sess)
+ * 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)
{
- 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;
+
+ /* Set the ticket encryption callback to be a wrapper around OpenSSL
+ * callback.
+ */
+ ctx->ticketEncCb = wolfSSL_TicketKeyCb;
+ ctx->ticketEncWrapCb = cb;
+
+ return WOLFSSL_SUCCESS;
}
-unsigned long wolfSSL_SESSION_get_ticket_lifetime_hint(
- const WOLFSSL_SESSION* sess)
+#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)
{
- WOLFSSL_ENTER("wolfSSL_SESSION_get_ticket_lifetime_hint");
- sess = ClientSessionToSession(sess);
- if (sess) {
- return sess->timeout;
+ if (ctx == NULL || keys == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ if (keylen != WOLFSSL_TICKET_KEYS_SZ) {
+ return WOLFSSL_FAILURE;
}
- 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;
+ 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;
}
-long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t)
+/* Deserialize the session ticket encryption keys.
+ *
+ * @param [in] ctx SSL/TLS context object.
+ * @param [in] keys Session ticket keys.
+ * @param [in] keylen Length of data.
+ * @return WOLFSSL_SUCCESS on success.
+ * @return WOLFSSL_FAILURE when ctx is NULL, keys is NULL or keylen is not the
+ * correct length.
+ */
+long wolfSSL_CTX_set_tlsext_ticket_keys(WOLFSSL_CTX *ctx,
+ const void *keys_vp, int keylen)
{
- word32 tmptime;
-
- ses = ClientSessionToSession(ses);
- if (ses == NULL || t < 0) {
- return BAD_FUNC_ARG;
+ const byte* keys = (const byte*)keys_vp;
+ if (ctx == NULL || keys == NULL) {
+ return WOLFSSL_FAILURE;
+ }
+ if (keylen != WOLFSSL_TICKET_KEYS_SZ) {
+ return WOLFSSL_FAILURE;
}
- tmptime = t & 0xFFFFFFFF;
- ses->timeout = tmptime;
+ 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
-long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess)
+#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)
{
- long bornOn = 0;
- WOLFSSL_ENTER("wolfSSL_SESSION_get_time");
- sess = ClientSessionToSession(sess);
- if (sess)
- bornOn = sess->bornOn;
- return bornOn;
+ *response = ssl->ocspCsrResp[0].buffer;
+ return ssl->ocspCsrResp[0].length;
}
-long wolfSSL_SESSION_set_time(WOLFSSL_SESSION *ses, long t)
+/* Not an OpenSSL API. */
+char* wolfSSL_get_ocsp_url(WOLFSSL* ssl)
{
-
- ses = ClientSessionToSession(ses);
- if (ses == NULL || t < 0) {
- return 0;
- }
- ses->bornOn = (word32)t;
- return t;
+ return ssl->url;
}
-#endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */
-
-#ifdef OPENSSL_EXTRA
-
-#if defined(HAVE_EX_DATA) && !defined(NO_FILESYSTEM)
-int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname)
+/* Not an OpenSSL API. */
+int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url)
{
- int ret = WOLFSSL_FATAL_ERROR;
+ if (ssl == NULL)
+ return WOLFSSL_FAILURE;
- 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;
+ ssl->url = url;
+ return WOLFSSL_SUCCESS;
+}
+#endif /* OCSP */
+#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
- file = XFOPEN(fname, "rb");
- if (file == XBADFILE)
- return WOLFSSL_BAD_FILE;
+#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 (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 ((producedDate == NULL) || (producedDateFormat == NULL))
+ return BAD_FUNC_ARG;
- if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
- WOLFSSL_MSG("cmp_peer_cert_to_file size error");
- XFCLOSE(file);
- return WOLFSSL_BAD_FILE;
- }
+ if (XSTRLEN((char *)ssl->ocspProducedDate) >= producedDate_space)
+ return BUFFER_E;
- if (sz > (long)sizeof(staticBuffer)) {
- WOLFSSL_MSG("Getting dynamic buffer");
- myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
- dynamic = 1;
- }
+ XSTRNCPY((char *)producedDate, (const char *)ssl->ocspProducedDate,
+ producedDate_space);
+ *producedDateFormat = ssl->ocspProducedDateFormat;
- 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;
- }
+ return 0;
+}
- FreeDer(&fileDer);
+int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) {
+ int idx = 0;
- if (dynamic)
- XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE);
+ if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) &&
+ (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME))
+ return BAD_FUNC_ARG;
- XFCLOSE(file);
- }
+ if (produced_tm == NULL)
+ return BAD_FUNC_ARG;
- return ret;
+ if (ExtractDate(ssl->ocspProducedDate,
+ (unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx))
+ return 0;
+ else
+ return ASN_PARSE_E;
}
#endif
-#endif /* OPENSSL_EXTRA */
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-const WOLFSSL_ObjectInfo wolfssl_object_info[] = {
-#ifndef NO_CERTS
- /* oidCertExtType */
- { NID_basic_constraints, BASIC_CA_OID, oidCertExtType, "basicConstraints",
- "X509v3 Basic Constraints"},
- { NID_subject_alt_name, ALT_NAMES_OID, oidCertExtType, "subjectAltName",
- "X509v3 Subject Alternative Name"},
- { NID_crl_distribution_points, CRL_DIST_OID, oidCertExtType, "crlDistributionPoints",
- "X509v3 CRL Distribution Points"},
- { NID_info_access, AUTH_INFO_OID, oidCertExtType, "authorityInfoAccess",
- "Authority Information Access"},
- { NID_authority_key_identifier, AUTH_KEY_OID, oidCertExtType,
- "authorityKeyIdentifier", "X509v3 Authority Key Identifier"},
- { NID_subject_key_identifier, SUBJ_KEY_OID, oidCertExtType,
- "subjectKeyIdentifier", "X509v3 Subject Key Identifier"},
- { NID_key_usage, KEY_USAGE_OID, oidCertExtType, "keyUsage",
- "X509v3 Key Usage"},
- { NID_inhibit_any_policy, INHIBIT_ANY_OID, oidCertExtType,
- "inhibitAnyPolicy", "X509v3 Inhibit Any Policy"},
- { NID_ext_key_usage, EXT_KEY_USAGE_OID, oidCertExtType,
- "extendedKeyUsage", "X509v3 Extended Key Usage"},
- { NID_name_constraints, NAME_CONS_OID, oidCertExtType,
- "nameConstraints", "X509v3 Name Constraints"},
- { NID_certificate_policies, CERT_POLICY_OID, oidCertExtType,
- "certificatePolicies", "X509v3 Certificate Policies"},
- /* oidCertAuthInfoType */
- { NID_ad_OCSP, AIA_OCSP_OID, oidCertAuthInfoType, "OCSP",
- "OCSP"},
- { NID_ad_ca_issuers, AIA_CA_ISSUER_OID, oidCertAuthInfoType,
- "caIssuers", "CA Issuers"},
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+int wolfSSL_CTX_get_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb* cb)
+{
+ if (ctx == NULL || ctx->cm == NULL || cb == NULL)
+ return WOLFSSL_FAILURE;
- /* oidCertPolicyType */
- { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy",
- "X509v3 Any Policy"},
-
- /* oidCertAltNameType */
- { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""},
-
- /* oidCertKeyUseType */
- { NID_anyExtendedKeyUsage, EKU_ANY_OID, oidCertKeyUseType,
- "anyExtendedKeyUsage", "Any Extended Key Usage"},
- { EKU_SERVER_AUTH_OID, EKU_SERVER_AUTH_OID, oidCertKeyUseType,
- "serverAuth", "TLS Web Server Authentication"},
- { EKU_CLIENT_AUTH_OID, EKU_CLIENT_AUTH_OID, oidCertKeyUseType,
- "clientAuth", "TLS Web Client Authentication"},
- { EKU_OCSP_SIGN_OID, EKU_OCSP_SIGN_OID, oidCertKeyUseType,
- "OCSPSigning", "OCSP Signing"},
-
- /* oidCertNameType */
- { NID_commonName, NID_commonName, oidCertNameType, "CN", "commonName"},
-#if !defined(WOLFSSL_CERT_REQ)
- { NID_surname, NID_surname, oidCertNameType, "SN", "surname"},
-#endif
- { NID_serialNumber, NID_serialNumber, oidCertNameType, "serialNumber",
- "serialNumber"},
- { NID_userId, NID_userId, oidCertNameType, "UID", "userid"},
- { NID_countryName, NID_countryName, oidCertNameType, "C", "countryName"},
- { NID_localityName, NID_localityName, oidCertNameType, "L", "localityName"},
- { NID_stateOrProvinceName, NID_stateOrProvinceName, oidCertNameType, "ST",
- "stateOrProvinceName"},
- { NID_streetAddress, NID_streetAddress, oidCertNameType, "street",
- "streetAddress"},
- { NID_organizationName, NID_organizationName, oidCertNameType, "O",
- "organizationName"},
- { NID_organizationalUnitName, NID_organizationalUnitName, oidCertNameType,
- "OU", "organizationalUnitName"},
- { NID_emailAddress, NID_emailAddress, oidCertNameType, "emailAddress",
- "emailAddress"},
- { NID_domainComponent, NID_domainComponent, oidCertNameType, "DC",
- "domainComponent"},
- { NID_favouriteDrink, NID_favouriteDrink, oidCertNameType, "favouriteDrink",
- "favouriteDrink"},
- { NID_businessCategory, NID_businessCategory, oidCertNameType, "businessCategory",
- "businessCategory"},
- { NID_jurisdictionCountryName, NID_jurisdictionCountryName, oidCertNameType, "jurisdictionC",
- "jurisdictionCountryName"},
- { NID_jurisdictionStateOrProvinceName, NID_jurisdictionStateOrProvinceName,
- oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"},
- { NID_postalCode, NID_postalCode, oidCertNameType, "postalCode", "postalCode"},
- { NID_userId, NID_userId, oidCertNameType, "UID", "userId"},
+#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+ if (ctx->cm->ocsp_stapling == NULL)
+ return WOLFSSL_FAILURE;
-#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
+ *cb = ctx->cm->ocsp_stapling->statusCb;
+#else
+ (void)cb;
+ *cb = NULL;
#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"},
+ return WOLFSSL_SUCCESS;
- { 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"},
+int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb cb)
+{
+ if (ctx == NULL || ctx->cm == NULL)
+ return WOLFSSL_FAILURE;
- { NID_secp112r1, ECC_SECP112R1_OID, oidCurveType, "secp112r1", "secp112r1"},
- { NID_secp112r2, ECC_SECP112R2_OID, oidCurveType, "secp112r2", "secp112r2"},
+#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);
- { NID_secp128r1, ECC_SECP128R1_OID, oidCurveType, "secp128r1", "secp128r1"},
- { NID_secp128r2, ECC_SECP128R2_OID, oidCurveType, "secp128r2", "secp128r2"},
+ if (ctx->cm->ocsp_stapling == NULL)
+ return WOLFSSL_FAILURE;
- { NID_secp160r1, ECC_SECP160R1_OID, oidCurveType, "secp160r1", "secp160r1"},
- { NID_secp160r2, ECC_SECP160R2_OID, oidCurveType, "secp160r2", "secp160r2"},
+ ctx->cm->ocsp_stapling->statusCb = cb;
+#else
+ (void)cb;
+#endif
- { NID_secp224r1, ECC_SECP224R1_OID, oidCurveType, "secp224r1", "secp224r1"},
- { NID_secp384r1, ECC_SECP384R1_OID, oidCurveType, "secp384r1", "secp384r1"},
- { NID_secp521r1, ECC_SECP521R1_OID, oidCurveType, "secp521r1", "secp521r1"},
+ return WOLFSSL_SUCCESS;
+}
- { 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"},
+long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg)
+{
+ if (ctx == NULL || ctx->cm == NULL)
+ return WOLFSSL_FAILURE;
- { 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 !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);
- #ifdef WOLFSSL_SM2
- { NID_sm2, ECC_SM2P256V1_OID, oidCurveType, "sm2", "sm2"},
- #endif
- #endif /* HAVE_ECC */
+ if (ctx->cm->ocsp_stapling == NULL)
+ return WOLFSSL_FAILURE;
- /* 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
+ ctx->cm->ocsp_stapling->statusCbArg = arg;
+#else
+ (void)arg;
+#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 */
+ return WOLFSSL_SUCCESS;
+}
- #ifndef NO_PWDBASED
- /* oidKdfType */
- { PBKDF2_OID, PBKDF2_OID, oidKdfType, "PBKDFv2", "PBKDF2"},
+long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *ssl, unsigned char **resp)
+{
+ if (ssl == NULL || resp == NULL)
+ return 0;
- /* 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
+ *resp = ssl->ocspCsrResp[0].buffer;
+ return (long)ssl->ocspCsrResp[0].length;
+}
- /* 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
+long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *ssl, unsigned char *resp,
+ int len)
+{
+ return wolfSSL_set_tlsext_status_ocsp_resp_multi(ssl, resp, len, 0);
+}
- #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 },
+int wolfSSL_set_tlsext_status_ocsp_resp_multi(WOLFSSL* ssl, unsigned char *resp,
+ int len, word32 idx)
+{
+ if (ssl == NULL || idx >= XELEM_CNT(ssl->ocspCsrResp) || len < 0)
+ return WOLFSSL_FAILURE;
+ if (!((resp == NULL) ^ (len > 0)))
+ return WOLFSSL_FAILURE;
- /* "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 },
+ XFREE(ssl->ocspCsrResp[idx].buffer, NULL, 0);
+ ssl->ocspCsrResp[idx].buffer = resp;
+ ssl->ocspCsrResp[idx].length = (word32)len;
- /* "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 */
-};
+ return WOLFSSL_SUCCESS;
+}
-#define WOLFSSL_OBJECT_INFO_SZ \
- (sizeof(wolfssl_object_info) / sizeof(*wolfssl_object_info))
-const size_t wolfssl_object_info_sz = WOLFSSL_OBJECT_INFO_SZ;
+void wolfSSL_CTX_set_ocsp_status_verify_cb(WOLFSSL_CTX* ctx,
+ ocspVerifyStatusCb cb, void* cbArg)
+{
+ if (ctx != NULL) {
+ ctx->ocspStatusVerifyCb = cb;
+ ctx->ocspStatusVerifyCbArg = cbArg;
+ }
+}
#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)
+#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)
{
- WOLFSSL_MSG("wolfSSL_OPENSSL_free");
-
- XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL);
-}
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
-
-#ifdef OPENSSL_EXTRA
+ word32 idx;
+ word32 length;
+ WOLFSSL_STACK* node;
+ WOLFSSL_STACK* last = NULL;
-void *wolfSSL_OPENSSL_malloc(size_t a)
-{
- return (void *)XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL);
-}
+ if (ctx == NULL || chain == NULL) {
+ chain = NULL;
+ return WOLFSSL_FAILURE;
+ }
+ if (ctx->x509Chain != NULL) {
+ *chain = ctx->x509Chain;
+ return WOLFSSL_SUCCESS;
+ }
-int wolfSSL_OPENSSL_hexchar2int(unsigned char c)
-{
- /* 'char' is unsigned on some platforms. */
- return (int)(signed char)HexCharToByte((char)c);
-}
+ /* If there are no chains then success! */
+ *chain = NULL;
+ if (ctx->certChain == NULL || ctx->certChain->length == 0) {
+ return WOLFSSL_SUCCESS;
+ }
-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;
+ /* 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;
- srcLen = XSTRLEN(str);
- targetBuf = (unsigned char*)XMALLOC(srcLen / 2, NULL, DYNAMIC_TYPE_OPENSSL);
- if (targetBuf == NULL) {
- return NULL;
- }
+ /* 3 byte length | X509 DER data */
+ ato24(ctx->certChain->buffer + idx, &length);
+ idx += 3;
- while (srcIdx < srcLen) {
- if (str[srcIdx] == ':') {
- srcIdx++;
- continue;
+ /* Create a new X509 from DER encoded data. */
+ node->data.x509 = wolfSSL_X509_d2i_ex(NULL,
+ ctx->certChain->buffer + idx, (int)length, ctx->heap);
+ if (node->data.x509 == NULL) {
+ XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL);
+ /* Return as much of the chain as we created. */
+ ctx->x509Chain = *chain;
+ return WOLFSSL_FAILURE;
}
+ idx += length;
- 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;
+ /* Add object to the end of the stack. */
+ if (last == NULL) {
+ node->num = 1;
+ *chain = node;
+ }
+ else {
+ (*chain)->num++;
+ last->next = node;
}
- targetBuf[targetIdx++] = (unsigned char)((srcDigitHigh << 4) | srcDigitLow);
+ last = node;
}
- 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();
-}
+ ctx->x509Chain = *chain;
-int wolfSSL_OPENSSL_init_crypto(word64 opts, const OPENSSL_INIT_SETTINGS* settings)
-{
- (void)opts;
- (void)settings;
- return wolfSSL_library_init();
+ return WOLFSSL_SUCCESS;
}
-#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 wolfSSL_CTX_get0_chain_certs(WOLFSSL_CTX *ctx,
+ WOLF_STACK_OF(WOLFSSL_X509) **sk)
{
- 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");
+ WOLFSSL_ENTER("wolfSSL_CTX_get0_chain_certs");
+ if (ctx == NULL || sk == NULL) {
+ WOLFSSL_MSG("Bad parameter");
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 */
+ /* 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);
+}
- ret = wc_EncryptedInfoGet(info, info->name);
- if (ret != 0) {
- WOLFSSL_MSG("unsupported cipher");
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
- #endif
+#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;
}
-
- /* 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);
+ *sk = ssl->ourCertChain;
+ return WOLFSSL_SUCCESS;
+}
#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;
+void wolfSSL_WOLFSSL_STRING_free(WOLFSSL_STRING s)
+{
+ WOLFSSL_ENTER("wolfSSL_WOLFSSL_STRING_free");
- /* 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;
- }
+ XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL);
+}
- /* 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);
+#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
- idx = (word32)XSTRLEN((char*)*cipherInfo);
- cipherInfoSz -= idx;
- ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz);
+#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 = 0;
-#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;
+ if (ssl != NULL && data != NULL && len != NULL) {
+ TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen);
+ *len = nameLen;
}
-
- 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)
+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)
{
- byte* buf = NULL;
- int sz = 0;
+ unsigned int i, j;
+ byte lenIn, lenClient;
- (void)heap;
+ if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL)
+ return WOLFSSL_NPN_UNSUPPORTED;
- if (key == NULL) {
- WOLFSSL_MSG("Bad parameters");
- return WOLFSSL_FAILURE;
- }
+ for (i = 0; i < inLen; i += lenIn) {
+ lenIn = in[i++];
+ for (j = 0; j < clientLen; j += lenClient) {
+ lenClient = clientNames[j++];
- 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;
+ if (lenIn != lenClient)
+ continue;
+
+ if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) {
+ *out = (unsigned char *)(in + i);
+ *outLen = lenIn;
+ return WOLFSSL_NPN_NEGOTIATED;
}
- 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;
+ *out = (unsigned char *)clientNames + 1;
+ *outLen = clientNames[0];
+ return WOLFSSL_NPN_NO_OVERLAP;
}
-#endif
-#ifndef NO_BIO
-static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key)
+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)
{
- 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);
+ if (ssl != NULL) {
+ ssl->alpnSelect = cb;
+ ssl->alpnSelectArg = arg;
}
-
- 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)
+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)
{
- int ret;
-
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PUBKEY");
-
- if ((bio == NULL) || (key == NULL)) {
- ret = WOLFSSL_FAILURE;
+ if (ctx != NULL) {
+ ctx->alpnSelect = cb;
+ ctx->alpnSelectArg = arg;
}
- 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)
+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)
{
- byte* keyDer;
- int type;
+ (void)s;
+ (void)cb;
+ (void)arg;
+ WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb");
+}
- (void)cipher;
- (void)passwd;
- (void)len;
+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 */
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey");
+#endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */
- if (bio == NULL || key == NULL) {
- WOLFSSL_MSG("Bad Function Arguments");
- return WOLFSSL_FAILURE;
+#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL)
+int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, word16 curve_id)
+{
+ int ret = 0;
+
+ WOLFSSL_ENTER("wolfSSL_curve_is_disabled");
+ WOLFSSL_MSG_EX("wolfSSL_curve_is_disabled checking for %d", curve_id);
+
+ /* (curve_id >= WOLFSSL_FFDHE_START) - DH parameters are never disabled. */
+ if (curve_id < WOLFSSL_FFDHE_START) {
+ if (curve_id > WOLFSSL_ECC_MAX_AVAIL) {
+ WOLFSSL_MSG("Curve id out of supported range");
+ /* Disabled if not in valid range. */
+ ret = 1;
+ }
+ else if (curve_id >= 32) {
+ /* 0 is for invalid and 1-14 aren't used otherwise. */
+ ret = (ssl->disabledCurves & (1U << (curve_id - 32))) != 0;
+ }
+ else {
+ ret = (ssl->disabledCurves & (1U << curve_id)) != 0;
+ }
}
- keyDer = (byte*)key->pkey.ptr;
+ WOLFSSL_LEAVE("wolfSSL_curve_is_disabled", ret);
+ return ret;
+}
- switch (key->type) {
-#ifndef NO_RSA
- case EVP_PKEY_RSA:
- type = PRIVATEKEY_TYPE;
- break;
-#endif
+#if (defined(HAVE_ECC) || \
+ defined(HAVE_CURVE25519) || defined(HAVE_CURVE448))
+#define CURVE_NAME(c) XSTR_SIZEOF((c)), (c)
-#ifndef NO_DSA
- case EVP_PKEY_DSA:
- type = DSA_PRIVATEKEY_TYPE;
- break;
+const WOLF_EC_NIST_NAME kNistCurves[] = {
+#ifdef HAVE_ECC
+ {CURVE_NAME("P-160"), WC_NID_secp160r1, WOLFSSL_ECC_SECP160R1},
+ {CURVE_NAME("P-160-2"), WC_NID_secp160r2, WOLFSSL_ECC_SECP160R2},
+ {CURVE_NAME("P-192"), WC_NID_X9_62_prime192v1, WOLFSSL_ECC_SECP192R1},
+ {CURVE_NAME("P-224"), WC_NID_secp224r1, WOLFSSL_ECC_SECP224R1},
+ {CURVE_NAME("P-256"), WC_NID_X9_62_prime256v1, WOLFSSL_ECC_SECP256R1},
+ {CURVE_NAME("P-384"), WC_NID_secp384r1, WOLFSSL_ECC_SECP384R1},
+ {CURVE_NAME("P-521"), WC_NID_secp521r1, WOLFSSL_ECC_SECP521R1},
+ {CURVE_NAME("K-160"), WC_NID_secp160k1, WOLFSSL_ECC_SECP160K1},
+ {CURVE_NAME("K-192"), WC_NID_secp192k1, WOLFSSL_ECC_SECP192K1},
+ {CURVE_NAME("K-224"), WC_NID_secp224k1, WOLFSSL_ECC_SECP224R1},
+ {CURVE_NAME("K-256"), WC_NID_secp256k1, WOLFSSL_ECC_SECP256K1},
+ {CURVE_NAME("B-256"), WC_NID_brainpoolP256r1,
+ WOLFSSL_ECC_BRAINPOOLP256R1},
+ {CURVE_NAME("B-384"), WC_NID_brainpoolP384r1,
+ WOLFSSL_ECC_BRAINPOOLP384R1},
+ {CURVE_NAME("B-512"), WC_NID_brainpoolP512r1,
+ WOLFSSL_ECC_BRAINPOOLP512R1},
+#endif
+#ifdef HAVE_CURVE25519
+ {CURVE_NAME("X25519"), WC_NID_X25519, WOLFSSL_ECC_X25519},
+#endif
+#ifdef HAVE_CURVE448
+ {CURVE_NAME("X448"), WC_NID_X448, WOLFSSL_ECC_X448},
+#endif
+#ifdef WOLFSSL_HAVE_MLKEM
+#ifndef WOLFSSL_NO_ML_KEM
+ {CURVE_NAME("ML_KEM_512"), WOLFSSL_ML_KEM_512, WOLFSSL_ML_KEM_512},
+ {CURVE_NAME("ML_KEM_768"), WOLFSSL_ML_KEM_768, WOLFSSL_ML_KEM_768},
+ {CURVE_NAME("ML_KEM_1024"), WOLFSSL_ML_KEM_1024, WOLFSSL_ML_KEM_1024},
+#if (defined(WOLFSSL_WC_MLKEM) || defined(HAVE_LIBOQS)) && defined(HAVE_ECC)
+ {CURVE_NAME("SecP256r1MLKEM512"), WOLFSSL_SECP256R1MLKEM512,
+ WOLFSSL_SECP256R1MLKEM512},
+ {CURVE_NAME("SecP384r1MLKEM768"), WOLFSSL_SECP384R1MLKEM768,
+ WOLFSSL_SECP384R1MLKEM768},
+ {CURVE_NAME("SecP256r1MLKEM768"), WOLFSSL_SECP256R1MLKEM768,
+ WOLFSSL_SECP256R1MLKEM768},
+ {CURVE_NAME("SecP521r1MLKEM1024"), WOLFSSL_SECP521R1MLKEM1024,
+ WOLFSSL_SECP521R1MLKEM1024},
+ {CURVE_NAME("SecP384r1MLKEM1024"), WOLFSSL_SECP384R1MLKEM1024,
+ WOLFSSL_SECP384R1MLKEM1024},
+ {CURVE_NAME("X25519MLKEM512"), WOLFSSL_X25519MLKEM512,
+ WOLFSSL_X25519MLKEM512},
+ {CURVE_NAME("X448MLKEM768"), WOLFSSL_X448MLKEM768,
+ WOLFSSL_X448MLKEM768},
+ {CURVE_NAME("X25519MLKEM768"), WOLFSSL_X25519MLKEM768,
+ WOLFSSL_X25519MLKEM768},
+#endif
+#endif /* !WOLFSSL_NO_ML_KEM */
+#ifdef WOLFSSL_MLKEM_KYBER
+ {CURVE_NAME("KYBER_LEVEL1"), WOLFSSL_KYBER_LEVEL1, WOLFSSL_KYBER_LEVEL1},
+ {CURVE_NAME("KYBER_LEVEL3"), WOLFSSL_KYBER_LEVEL3, WOLFSSL_KYBER_LEVEL3},
+ {CURVE_NAME("KYBER_LEVEL5"), WOLFSSL_KYBER_LEVEL5, WOLFSSL_KYBER_LEVEL5},
+#if (defined(WOLFSSL_WC_MLKEM) || defined(HAVE_LIBOQS)) && defined(HAVE_ECC)
+ {CURVE_NAME("P256_KYBER_LEVEL1"), WOLFSSL_P256_KYBER_LEVEL1,
+ WOLFSSL_P256_KYBER_LEVEL1},
+ {CURVE_NAME("P384_KYBER_LEVEL3"), WOLFSSL_P384_KYBER_LEVEL3,
+ WOLFSSL_P384_KYBER_LEVEL3},
+ {CURVE_NAME("P256_KYBER_LEVEL3"), WOLFSSL_P256_KYBER_LEVEL3,
+ WOLFSSL_P256_KYBER_LEVEL3},
+ {CURVE_NAME("P521_KYBER_LEVEL5"), WOLFSSL_P521_KYBER_LEVEL5,
+ WOLFSSL_P521_KYBER_LEVEL5},
+ {CURVE_NAME("X25519_KYBER_LEVEL1"), WOLFSSL_X25519_KYBER_LEVEL1,
+ WOLFSSL_X25519_KYBER_LEVEL1},
+ {CURVE_NAME("X448_KYBER_LEVEL3"), WOLFSSL_X448_KYBER_LEVEL3,
+ WOLFSSL_X448_KYBER_LEVEL3},
+ {CURVE_NAME("X25519_KYBER_LEVEL3"), WOLFSSL_X25519_KYBER_LEVEL3,
+ WOLFSSL_X25519_KYBER_LEVEL3},
+#endif
+#endif /* WOLFSSL_MLKEM_KYBER */
+#endif /* WOLFSSL_HAVE_MLKEM */
+#ifdef WOLFSSL_SM2
+ {CURVE_NAME("SM2"), WC_NID_sm2, WOLFSSL_ECC_SM2P256V1},
#endif
-
#ifdef HAVE_ECC
- case EVP_PKEY_EC:
- type = ECC_PRIVATEKEY_TYPE;
- break;
+ /* Alternative curve names */
+ {CURVE_NAME("prime256v1"), WC_NID_X9_62_prime256v1, WOLFSSL_ECC_SECP256R1},
+ {CURVE_NAME("secp256r1"), WC_NID_X9_62_prime256v1, WOLFSSL_ECC_SECP256R1},
+ {CURVE_NAME("secp384r1"), WC_NID_secp384r1, WOLFSSL_ECC_SECP384R1},
+ {CURVE_NAME("secp521r1"), WC_NID_secp521r1, WOLFSSL_ECC_SECP521R1},
+#endif
+#ifdef WOLFSSL_SM2
+ {CURVE_NAME("sm2p256v1"), WC_NID_sm2, WOLFSSL_ECC_SM2P256V1},
#endif
+ {0, NULL, 0, 0},
+};
-#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
- case EVP_PKEY_DH:
- type = DH_PRIVATEKEY_TYPE;
- break;
+int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names,
+ byte curves_only)
+{
+ int idx, start = 0, len, i, ret = WOLFSSL_FAILURE;
+ word16 curve;
+ word32 disabled;
+ char name[MAX_CURVE_NAME_SZ];
+ byte groups_len = 0;
+#ifdef WOLFSSL_SMALL_STACK
+ void *heap = ssl? ssl->heap : ctx ? ctx->heap : NULL;
+ int *groups;
+#else
+ int groups[WOLFSSL_MAX_GROUP_COUNT];
#endif
+ const WOLF_EC_NIST_NAME* nist_name;
- default:
- WOLFSSL_MSG("Unknown Key type!");
- type = PRIVATEKEY_TYPE;
+ WC_ALLOC_VAR_EX(groups, int, WOLFSSL_MAX_GROUP_COUNT, heap,
+ DYNAMIC_TYPE_TMP_BUFFER,
+ {
+ ret=MEMORY_E;
+ goto leave;
+ });
+
+ 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, (size_t)len);
+ name[len] = 0;
+ curve = WOLFSSL_NAMED_GROUP_INVALID;
+
+ for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
+ if (len == nist_name->name_len &&
+ XSTRNCMP(name, nist_name->name, (size_t)len) == 0) {
+ curve = nist_name->curve;
+ break;
+ }
+ }
+
+ if (curve == WOLFSSL_NAMED_GROUP_INVALID) {
+ #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && defined(HAVE_ECC)
+ 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((int)eccSet->oidSum);
+ #else
+ WOLFSSL_MSG("API not present to search farther using name");
+ goto leave;
+ #endif
+ }
+
+ if ((curves_only && curve >= WOLFSSL_ECC_MAX_AVAIL) ||
+ curve == WOLFSSL_NAMED_GROUP_INVALID) {
+ 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 >= 64) {
+ WC_DO_NOTHING;
+ }
+ else if (curve >= 32) {
+ /* 0 is for invalid and 1-14 aren't used otherwise. */
+ disabled &= ~(1U << (curve - 32));
+ }
+ else {
+ disabled &= ~(1U << curve);
+ }
+ #if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_TLS)
+ #if !defined(WOLFSSL_OLD_SET_CURVES_LIST)
+ /* using the wolfSSL API to set the groups, this will populate
+ * (ssl|ctx)->groups and reset any TLSX_SUPPORTED_GROUPS.
+ * The order in (ssl|ctx)->groups will then be respected
+ * when TLSX_KEY_SHARE needs to be established */
+ if ((ssl && wolfSSL_set_groups(ssl, groups, groups_len)
+ != WOLFSSL_SUCCESS)
+ || (ctx && wolfSSL_CTX_set_groups(ctx, groups, groups_len)
+ != WOLFSSL_SUCCESS)) {
+ WOLFSSL_MSG("Unable to set supported curve");
+ goto leave;
+ }
+ #elif !defined(NO_WOLFSSL_CLIENT)
+ /* set the supported curve so client TLS extension contains only the
+ * desired curves */
+ if ((ssl && wolfSSL_UseSupportedCurve(ssl, curve) != WOLFSSL_SUCCESS)
+ || (ctx && wolfSSL_CTX_UseSupportedCurve(ctx, curve)
+ != WOLFSSL_SUCCESS)) {
+ WOLFSSL_MSG("Unable to set supported curve");
+ goto leave;
+ }
+ #endif
+ #endif /* HAVE_SUPPORTED_CURVES && !NO_TLS */
}
- return der_write_to_bio_as_pem(keyDer, key->pkey_sz, bio, type);
+ if (ssl != NULL)
+ ssl->disabledCurves = disabled;
+ else if (ctx != NULL)
+ ctx->disabledCurves = disabled;
+ ret = WOLFSSL_SUCCESS;
+
+leave:
+#ifdef WOLFSSL_SMALL_STACK
+ if (groups)
+ XFREE((void*)groups, heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return ret;
}
-#endif /* !NO_BIO */
-/* Colon separated list of + algorithms.
- * Replaces list in context.
- */
-int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, const char* list)
+int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names)
{
- WOLFSSL_MSG("wolfSSL_CTX_set1_sigalg_list");
-
- if (ctx == NULL || list == NULL) {
- WOLFSSL_MSG("Bad function arguments");
+ WOLFSSL_ENTER("wolfSSL_CTX_set1_curves_list");
+ if (ctx == NULL || names == NULL) {
+ WOLFSSL_MSG("ctx or names was NULL");
return WOLFSSL_FAILURE;
}
+ return set_curves_list(NULL, ctx, names, 1);
+}
- if (AllocateCtxSuites(ctx) != 0)
+int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names)
+{
+ WOLFSSL_ENTER("wolfSSL_set1_curves_list");
+ if (ssl == NULL || names == NULL) {
+ WOLFSSL_MSG("ssl or names was NULL");
return WOLFSSL_FAILURE;
-
- return SetSuitesHashSigAlgo(ctx->suites, list);
+ }
+ return set_curves_list(ssl, NULL, names, 1);
}
+#endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) */
+#endif /* OPENSSL_EXTRA || HAVE_CURL */
-/* Colon separated list of + algorithms.
- * Replaces list in SSL.
+
+#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_set1_sigalgs_list(WOLFSSL* ssl, const char* list)
+int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb)
{
- WOLFSSL_MSG("wolfSSL_set1_sigalg_list");
-
- if (ssl == NULL || list == NULL) {
- WOLFSSL_MSG("Bad function arguments");
+ WOLFSSL_ENTER("wolfSSL_CTX_set_msg_callback");
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Null ctx passed in");
return WOLFSSL_FAILURE;
}
- if (AllocateSuites(ssl) != 0)
- return WOLFSSL_FAILURE;
-
- return SetSuitesHashSigAlgo(ssl->suites, list);
+ ctx->protoMsgCb = cb;
+ return WOLFSSL_SUCCESS;
}
-static int HashToNid(byte hashAlgo, int* nid)
+
+/* 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)
{
- int ret = WOLFSSL_SUCCESS;
+ WOLFSSL_ENTER("wolfSSL_set_msg_callback");
- /* 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");
+ if (ssl == NULL) {
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;
+ if (cb != NULL) {
+ ssl->toInfoOn = 1;
}
- return SaToNid(ssl->options.sigAlgo, nid);
+ ssl->protoMsgCb = cb;
+ return WOLFSSL_SUCCESS;
}
-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");
+/* set the user argument to pass to the msg callback when called
+ * return WOLFSSL_SUCCESS on success */
+int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg)
+{
+ WOLFSSL_ENTER("wolfSSL_CTX_set_msg_callback_arg");
+ if (ctx == NULL) {
+ WOLFSSL_MSG("Null WOLFSSL_CTX passed in");
return WOLFSSL_FAILURE;
}
- return HashToNid(ssl->options.peerHashAlgo, nid);
+ ctx->protoMsgCtx = arg;
+ return WOLFSSL_SUCCESS;
}
-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");
+int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg)
+{
+ WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg");
+ if (ssl == NULL)
return WOLFSSL_FAILURE;
- }
- return SaToNid(ssl->options.peerSigAlgo, nid);
+ ssl->protoMsgCtx = arg;
+ return WOLFSSL_SUCCESS;
}
-#ifdef HAVE_ECC
-
-#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
-static int populate_groups(int* groups, int max_count, const char *list)
+void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file,
+ int line)
{
- const char *end;
- int count = 0;
- const WOLF_EC_NIST_NAME* nist_name;
-
- if (!groups || !list) {
- return -1;
- }
+ void *ret;
+ (void)file;
+ (void)line;
- for (end = list; ; list = ++end) {
- int len;
+ if (data == NULL || siz >= INT_MAX)
+ return NULL;
- 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;
+ ret = wolfSSL_OPENSSL_malloc(siz);
+ if (ret == NULL) {
+ return NULL;
}
-
- return count;
+ return XMEMCPY(ret, data, siz);
}
-int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, const char *list)
+void wolfSSL_OPENSSL_cleanse(void *ptr, size_t len)
{
- int groups[WOLFSSL_MAX_GROUP_COUNT];
- int count = 0;
+ if (ptr)
+ ForceZero(ptr, (word32)len);
+}
- if (!ctx || !list) {
- return WOLFSSL_FAILURE;
+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 ((count = populate_groups(groups,
- WOLFSSL_MAX_GROUP_COUNT, list)) == -1) {
+ 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 wolfSSL_CTX_set1_groups(ctx, groups, count);
+#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
}
-int wolfSSL_set1_groups_list(WOLFSSL *ssl, const char *list)
+
+#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)
{
- int groups[WOLFSSL_MAX_GROUP_COUNT];
- int count = 0;
+ char* pt = NULL;
+ unsigned int ptIdx;
+ unsigned int sz;
+ unsigned int idx = 0;
+ int alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
+ int ret;
- if (!ssl || !list) {
+ 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
}
- if ((count = populate_groups(groups,
- WOLFSSL_MAX_GROUP_COUNT, list)) == -1) {
+ /* Replacing leading number with trailing ',' and adding '\0'. */
+ pt = (char*)XMALLOC(p_len + 1, ssl->heap, DYNAMIC_TYPE_OPENSSL);
+ if (pt == 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
}
- return wolfSSL_set1_groups(ssl, groups, count);
-}
-#endif /* WOLFSSL_TLS13 */
-
-#endif /* HAVE_ECC */
+ ptIdx = 0;
+ /* convert into comma separated list */
+ while (idx < p_len - 1) {
+ unsigned int i;
-#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;
+ sz = p[idx++];
+ if (idx + sz > p_len) {
+ WOLFSSL_MSG("Bad list format");
+ XFREE(pt, ssl->heap, DYNAMIC_TYPE_OPENSSL);
+ #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
}
- else {
- /* Default to RSA if format is not set */
- type = EVP_PKEY_RSA;
+ if (sz > 0) {
+ for (i = 0; i < sz; i++) {
+ pt[ptIdx++] = p[idx++];
+ }
+ if (idx < p_len - 1) {
+ pt[ptIdx++] = ',';
+ }
}
+ }
+ pt[ptIdx++] = '\0';
- /* 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);
+ /* clears out all current ALPN extensions set */
+ TLSX_Remove(&ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL, ssl->heap);
- return pkey;
+ ret = wolfSSL_UseALPN(ssl, pt, ptIdx, (byte)alpn_opt);
+ XFREE(pt, ssl->heap, DYNAMIC_TYPE_OPENSSL);
+#if defined(WOLFSSL_ERROR_CODE_OPENSSL)
+ /* 0 on success in OpenSSL, non-0 on failure in OpenSSL
+ * the function reverses the return value convention.
+ */
+ if (ret != WOLFSSL_SUCCESS)
+ return 1;
+ return 0;
+#else
+ if (ret != WOLFSSL_SUCCESS)
+ return WOLFSSL_FAILURE;
+ return WOLFSSL_SUCCESS;
+#endif
}
+#endif /* !NO_BIO */
+#endif /* HAVE_ALPN */
+#endif /* OPENSSL_EXTRA */
-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 defined(OPENSSL_EXTRA)
- if (bio == NULL)
- return pkey;
+#ifndef NO_BIO
+#define WOLFSSL_BIO_INCLUDED
+#include "src/bio.c"
+#endif
- if (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE, &keyFormat, &der)
- >= 0) {
- const unsigned char* ptr = der->buffer;
+word32 nid2oid(int nid, int grp)
+{
+ /* get OID type */
+ switch (grp) {
+ /* oidHashType */
+ case oidHashType:
+ switch (nid) {
+ #ifdef WOLFSSL_MD2
+ case WC_NID_md2:
+ return MD2h;
+ #endif
+ #ifndef NO_MD5
+ case WC_NID_md5:
+ return MD5h;
+ #endif
+ #ifndef NO_SHA
+ case WC_NID_sha1:
+ return SHAh;
+ #endif
+ case WC_NID_sha224:
+ return SHA224h;
+ #ifndef NO_SHA256
+ case WC_NID_sha256:
+ return SHA256h;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case WC_NID_sha384:
+ return SHA384h;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case WC_NID_sha512:
+ return SHA512h;
+ #endif
+ #ifndef WOLFSSL_NOSHA3_224
+ case WC_NID_sha3_224:
+ return SHA3_224h;
+ #endif
+ #ifndef WOLFSSL_NOSHA3_256
+ case WC_NID_sha3_256:
+ return SHA3_256h;
+ #endif
+ #ifndef WOLFSSL_NOSHA3_384
+ case WC_NID_sha3_384:
+ return SHA3_384h;
+ #endif
+ #ifndef WOLFSSL_NOSHA3_512
+ case WC_NID_sha3_512:
+ return SHA3_512h;
+ #endif
+ }
+ break;
- /* handle case where reuse is attempted */
- if (key != NULL && *key != NULL)
- pkey = *key;
+ /* oidSigType */
+ case oidSigType:
+ switch (nid) {
+ #ifndef NO_DSA
+ case WC_NID_dsaWithSHA1:
+ return CTC_SHAwDSA;
+ case WC_NID_dsa_with_SHA256:
+ return CTC_SHA256wDSA;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ case WC_NID_md2WithRSAEncryption:
+ return CTC_MD2wRSA;
+ case WC_NID_md5WithRSAEncryption:
+ return CTC_MD5wRSA;
+ case WC_NID_sha1WithRSAEncryption:
+ return CTC_SHAwRSA;
+ case WC_NID_sha224WithRSAEncryption:
+ return CTC_SHA224wRSA;
+ case WC_NID_sha256WithRSAEncryption:
+ return CTC_SHA256wRSA;
+ case WC_NID_sha384WithRSAEncryption:
+ return CTC_SHA384wRSA;
+ case WC_NID_sha512WithRSAEncryption:
+ return CTC_SHA512wRSA;
+ #ifdef WOLFSSL_SHA3
+ case WC_NID_RSA_SHA3_224:
+ return CTC_SHA3_224wRSA;
+ case WC_NID_RSA_SHA3_256:
+ return CTC_SHA3_256wRSA;
+ case WC_NID_RSA_SHA3_384:
+ return CTC_SHA3_384wRSA;
+ case WC_NID_RSA_SHA3_512:
+ return CTC_SHA3_512wRSA;
+ #endif
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ case WC_NID_ecdsa_with_SHA1:
+ return CTC_SHAwECDSA;
+ case WC_NID_ecdsa_with_SHA224:
+ return CTC_SHA224wECDSA;
+ case WC_NID_ecdsa_with_SHA256:
+ return CTC_SHA256wECDSA;
+ case WC_NID_ecdsa_with_SHA384:
+ return CTC_SHA384wECDSA;
+ case WC_NID_ecdsa_with_SHA512:
+ return CTC_SHA512wECDSA;
+ #ifdef WOLFSSL_SHA3
+ case WC_NID_ecdsa_with_SHA3_224:
+ return CTC_SHA3_224wECDSA;
+ case WC_NID_ecdsa_with_SHA3_256:
+ return CTC_SHA3_256wECDSA;
+ case WC_NID_ecdsa_with_SHA3_384:
+ return CTC_SHA3_384wECDSA;
+ case WC_NID_ecdsa_with_SHA3_512:
+ return CTC_SHA3_512wECDSA;
+ #endif
+ #endif /* HAVE_ECC */
+ }
+ break;
- wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length);
- if (pkey == NULL) {
- WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
- }
- }
+ /* oidKeyType */
+ case oidKeyType:
+ switch (nid) {
+ #ifndef NO_DSA
+ case WC_NID_dsa:
+ return DSAk;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ case WC_NID_rsaEncryption:
+ return RSAk;
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ case WC_NID_X9_62_id_ecPublicKey:
+ return ECDSAk;
+ #endif /* HAVE_ECC */
+ }
+ break;
- FreeDer(&der);
- if (key != NULL && pkey != NULL)
- *key = pkey;
+ #ifdef HAVE_ECC
+ case oidCurveType:
+ switch (nid) {
+ case WC_NID_X9_62_prime192v1:
+ return ECC_SECP192R1_OID;
+ case WC_NID_X9_62_prime192v2:
+ return ECC_PRIME192V2_OID;
+ case WC_NID_X9_62_prime192v3:
+ return ECC_PRIME192V3_OID;
+ case WC_NID_X9_62_prime239v1:
+ return ECC_PRIME239V1_OID;
+ case WC_NID_X9_62_prime239v2:
+ return ECC_PRIME239V2_OID;
+ case WC_NID_X9_62_prime239v3:
+ return ECC_PRIME239V3_OID;
+ case WC_NID_X9_62_prime256v1:
+ return ECC_SECP256R1_OID;
+ case WC_NID_secp112r1:
+ return ECC_SECP112R1_OID;
+ case WC_NID_secp112r2:
+ return ECC_SECP112R2_OID;
+ case WC_NID_secp128r1:
+ return ECC_SECP128R1_OID;
+ case WC_NID_secp128r2:
+ return ECC_SECP128R2_OID;
+ case WC_NID_secp160r1:
+ return ECC_SECP160R1_OID;
+ case WC_NID_secp160r2:
+ return ECC_SECP160R2_OID;
+ case WC_NID_secp224r1:
+ return ECC_SECP224R1_OID;
+ case WC_NID_secp384r1:
+ return ECC_SECP384R1_OID;
+ case WC_NID_secp521r1:
+ return ECC_SECP521R1_OID;
+ case WC_NID_secp160k1:
+ return ECC_SECP160K1_OID;
+ case WC_NID_secp192k1:
+ return ECC_SECP192K1_OID;
+ case WC_NID_secp224k1:
+ return ECC_SECP224K1_OID;
+ case WC_NID_secp256k1:
+ return ECC_SECP256K1_OID;
+ case WC_NID_brainpoolP160r1:
+ return ECC_BRAINPOOLP160R1_OID;
+ case WC_NID_brainpoolP192r1:
+ return ECC_BRAINPOOLP192R1_OID;
+ case WC_NID_brainpoolP224r1:
+ return ECC_BRAINPOOLP224R1_OID;
+ case WC_NID_brainpoolP256r1:
+ return ECC_BRAINPOOLP256R1_OID;
+ case WC_NID_brainpoolP320r1:
+ return ECC_BRAINPOOLP320R1_OID;
+ case WC_NID_brainpoolP384r1:
+ return ECC_BRAINPOOLP384R1_OID;
+ case WC_NID_brainpoolP512r1:
+ return ECC_BRAINPOOLP512R1_OID;
+ }
+ break;
+ #endif /* HAVE_ECC */
- WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PUBKEY", 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 WC_NID_des:
+ return DESb;
+ case WC_NID_des3:
+ return DES3b;
+ #endif
+ }
+ break;
- return pkey;
-}
-#endif /* !NO_BIO */
+ #ifdef HAVE_OCSP
+ case oidOcspType:
+ switch (nid) {
+ case WC_NID_id_pkix_OCSP_basic:
+ return OCSP_BASIC_OID;
+ case OCSP_NONCE_OID:
+ return OCSP_NONCE_OID;
+ }
+ break;
+ #endif /* HAVE_OCSP */
-#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;
+ /* oidCertExtType */
+ case oidCertExtType:
+ switch (nid) {
+ case WC_NID_basic_constraints:
+ return BASIC_CA_OID;
+ case WC_NID_subject_alt_name:
+ return ALT_NAMES_OID;
+ case WC_NID_crl_distribution_points:
+ return CRL_DIST_OID;
+ case WC_NID_info_access:
+ return AUTH_INFO_OID;
+ case WC_NID_authority_key_identifier:
+ return AUTH_KEY_OID;
+ case WC_NID_subject_key_identifier:
+ return SUBJ_KEY_OID;
+ case WC_NID_inhibit_any_policy:
+ return INHIBIT_ANY_OID;
+ case WC_NID_key_usage:
+ return KEY_USAGE_OID;
+ case WC_NID_name_constraints:
+ return NAME_CONS_OID;
+ case WC_NID_certificate_policies:
+ return CERT_POLICY_OID;
+ case WC_NID_ext_key_usage:
+ return EXT_KEY_USAGE_OID;
+ }
+ break;
- WOLFSSL_ENTER("wolfSSL_PEM_read_PUBKEY");
+ /* oidCertAuthInfoType */
+ case oidCertAuthInfoType:
+ switch (nid) {
+ case WC_NID_ad_OCSP:
+ return AIA_OCSP_OID;
+ case WC_NID_ad_ca_issuers:
+ return AIA_CA_ISSUER_OID;
+ }
+ break;
- if ((pem_read_file_key(fp, cb, pass, PUBLICKEY_TYPE, &keyFormat, &der)
- >= 0) && (der != NULL)) {
- const unsigned char* ptr = der->buffer;
+ /* oidCertPolicyType */
+ case oidCertPolicyType:
+ switch (nid) {
+ case WC_NID_any_policy:
+ return CP_ANY_OID;
+ }
+ break;
- /* handle case where reuse is attempted */
- if ((key != NULL) && (*key != NULL)) {
- pkey = *key;
- }
+ /* oidCertAltNameType */
+ case oidCertAltNameType:
+ switch (nid) {
+ case WC_NID_hw_name_oid:
+ return HW_NAME_OID;
+ }
+ break;
- if ((wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length) == NULL) ||
- (pkey == NULL)) {
- WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY");
- pkey = NULL;
- }
- }
+ /* oidCertKeyUseType */
+ case oidCertKeyUseType:
+ switch (nid) {
+ case WC_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;
- FreeDer(&der);
+ /* oidKdfType */
+ case oidKdfType:
+ switch (nid) {
+ case PBKDF2_OID:
+ return PBKDF2_OID;
+ }
+ break;
- if ((key != NULL) && (pkey != NULL)) {
- *key = pkey;
- }
-
- WOLFSSL_LEAVE("wolfSSL_PEM_read_PUBKEY", 0);
-
- return pkey;
-}
-#endif /* NO_FILESYSTEM */
-#endif /* OPENSSL_EXTRA */
+ /* 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;
-#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 */
+ /* oidKeyWrapType */
+ case oidKeyWrapType:
+ switch (nid) {
+ #ifdef WOLFSSL_AES_128
+ case AES128_WRAP:
+ return AES128_WRAP;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192_WRAP:
+ return AES192_WRAP;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256_WRAP:
+ return AES256_WRAP;
+ #endif
+ }
+ break;
+ /* oidCmsKeyAgreeType */
+ case oidCmsKeyAgreeType:
+ switch (nid) {
+ #ifndef NO_SHA
+ case dhSinglePass_stdDH_sha1kdf_scheme:
+ return dhSinglePass_stdDH_sha1kdf_scheme;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case dhSinglePass_stdDH_sha224kdf_scheme:
+ return dhSinglePass_stdDH_sha224kdf_scheme;
+ #endif
+ #ifndef NO_SHA256
+ case dhSinglePass_stdDH_sha256kdf_scheme:
+ return dhSinglePass_stdDH_sha256kdf_scheme;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case dhSinglePass_stdDH_sha384kdf_scheme:
+ return dhSinglePass_stdDH_sha384kdf_scheme;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case dhSinglePass_stdDH_sha512kdf_scheme:
+ return dhSinglePass_stdDH_sha512kdf_scheme;
+ #endif
+ }
+ break;
-#ifdef SESSION_CERTS
+ /* oidCmsKeyAgreeType */
+ #ifdef WOLFSSL_CERT_REQ
+ case oidCsrAttrType:
+ switch (nid) {
+ case WC_NID_pkcs9_contentType:
+ return PKCS9_CONTENT_TYPE_OID;
+ case WC_NID_pkcs9_challengePassword:
+ return CHALLENGE_PASSWORD_OID;
+ case WC_NID_serialNumber:
+ return SERIAL_NUMBER_OID;
+ case WC_NID_userId:
+ return USER_ID_OID;
+ case WC_NID_surname:
+ return SURNAME_OID;
+ }
+ break;
+ #endif
-#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;
+ default:
+ WOLFSSL_MSG("NID not in table");
+ /* MSVC warns without the cast */
+ return (word32)-1;
+ }
- return 0;
+ /* MSVC warns without the cast */
+ return (word32)-1;
}
-#endif /* WOLFSSL_ALT_CERT_CHAINS */
-
-/* Get peer's certificate chain */
-WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl)
+int oid2nid(word32 oid, int grp)
{
- WOLFSSL_ENTER("wolfSSL_get_peer_chain");
- if (ssl)
- return &ssl->session->chain;
+ size_t i;
+ /* get OID type */
+ switch (grp) {
+ /* oidHashType */
+ case oidHashType:
+ switch (oid) {
+ #ifdef WOLFSSL_MD2
+ case MD2h:
+ return WC_NID_md2;
+ #endif
+ #ifndef NO_MD5
+ case MD5h:
+ return WC_NID_md5;
+ #endif
+ #ifndef NO_SHA
+ case SHAh:
+ return WC_NID_sha1;
+ #endif
+ case SHA224h:
+ return WC_NID_sha224;
+ #ifndef NO_SHA256
+ case SHA256h:
+ return WC_NID_sha256;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case SHA384h:
+ return WC_NID_sha384;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case SHA512h:
+ return WC_NID_sha512;
+ #endif
+ }
+ break;
- return 0;
-}
+ /* oidSigType */
+ case oidSigType:
+ switch (oid) {
+ #ifndef NO_DSA
+ case CTC_SHAwDSA:
+ return WC_NID_dsaWithSHA1;
+ case CTC_SHA256wDSA:
+ return WC_NID_dsa_with_SHA256;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ case CTC_MD2wRSA:
+ return WC_NID_md2WithRSAEncryption;
+ case CTC_MD5wRSA:
+ return WC_NID_md5WithRSAEncryption;
+ case CTC_SHAwRSA:
+ return WC_NID_sha1WithRSAEncryption;
+ case CTC_SHA224wRSA:
+ return WC_NID_sha224WithRSAEncryption;
+ case CTC_SHA256wRSA:
+ return WC_NID_sha256WithRSAEncryption;
+ case CTC_SHA384wRSA:
+ return WC_NID_sha384WithRSAEncryption;
+ case CTC_SHA512wRSA:
+ return WC_NID_sha512WithRSAEncryption;
+ #ifdef WOLFSSL_SHA3
+ case CTC_SHA3_224wRSA:
+ return WC_NID_RSA_SHA3_224;
+ case CTC_SHA3_256wRSA:
+ return WC_NID_RSA_SHA3_256;
+ case CTC_SHA3_384wRSA:
+ return WC_NID_RSA_SHA3_384;
+ case CTC_SHA3_512wRSA:
+ return WC_NID_RSA_SHA3_512;
+ #endif
+ #ifdef WC_RSA_PSS
+ case CTC_RSASSAPSS:
+ return WC_NID_rsassaPss;
+ #endif
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ case CTC_SHAwECDSA:
+ return WC_NID_ecdsa_with_SHA1;
+ case CTC_SHA224wECDSA:
+ return WC_NID_ecdsa_with_SHA224;
+ case CTC_SHA256wECDSA:
+ return WC_NID_ecdsa_with_SHA256;
+ case CTC_SHA384wECDSA:
+ return WC_NID_ecdsa_with_SHA384;
+ case CTC_SHA512wECDSA:
+ return WC_NID_ecdsa_with_SHA512;
+ #ifdef WOLFSSL_SHA3
+ case CTC_SHA3_224wECDSA:
+ return WC_NID_ecdsa_with_SHA3_224;
+ case CTC_SHA3_256wECDSA:
+ return WC_NID_ecdsa_with_SHA3_256;
+ case CTC_SHA3_384wECDSA:
+ return WC_NID_ecdsa_with_SHA3_384;
+ case CTC_SHA3_512wECDSA:
+ return WC_NID_ecdsa_with_SHA3_512;
+ #endif
+ #endif /* HAVE_ECC */
+ }
+ break;
+ /* oidKeyType */
+ case oidKeyType:
+ switch (oid) {
+ #ifndef NO_DSA
+ case DSAk:
+ return WC_NID_dsa;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ case RSAk:
+ return WC_NID_rsaEncryption;
+ #ifdef WC_RSA_PSS
+ case RSAPSSk:
+ return WC_NID_rsassaPss;
+ #endif
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ return WC_NID_X9_62_id_ecPublicKey;
+ #endif /* HAVE_ECC */
+ }
+ break;
-/* 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;
-}
+ #ifdef HAVE_ECC
+ case oidCurveType:
+ switch (oid) {
+ case ECC_SECP192R1_OID:
+ return WC_NID_X9_62_prime192v1;
+ case ECC_PRIME192V2_OID:
+ return WC_NID_X9_62_prime192v2;
+ case ECC_PRIME192V3_OID:
+ return WC_NID_X9_62_prime192v3;
+ case ECC_PRIME239V1_OID:
+ return WC_NID_X9_62_prime239v1;
+ case ECC_PRIME239V2_OID:
+ return WC_NID_X9_62_prime239v2;
+ case ECC_PRIME239V3_OID:
+ return WC_NID_X9_62_prime239v3;
+ case ECC_SECP256R1_OID:
+ return WC_NID_X9_62_prime256v1;
+ case ECC_SECP112R1_OID:
+ return WC_NID_secp112r1;
+ case ECC_SECP112R2_OID:
+ return WC_NID_secp112r2;
+ case ECC_SECP128R1_OID:
+ return WC_NID_secp128r1;
+ case ECC_SECP128R2_OID:
+ return WC_NID_secp128r2;
+ case ECC_SECP160R1_OID:
+ return WC_NID_secp160r1;
+ case ECC_SECP160R2_OID:
+ return WC_NID_secp160r2;
+ case ECC_SECP224R1_OID:
+ return WC_NID_secp224r1;
+ case ECC_SECP384R1_OID:
+ return WC_NID_secp384r1;
+ case ECC_SECP521R1_OID:
+ return WC_NID_secp521r1;
+ case ECC_SECP160K1_OID:
+ return WC_NID_secp160k1;
+ case ECC_SECP192K1_OID:
+ return WC_NID_secp192k1;
+ case ECC_SECP224K1_OID:
+ return WC_NID_secp224k1;
+ case ECC_SECP256K1_OID:
+ return WC_NID_secp256k1;
+ case ECC_BRAINPOOLP160R1_OID:
+ return WC_NID_brainpoolP160r1;
+ case ECC_BRAINPOOLP192R1_OID:
+ return WC_NID_brainpoolP192r1;
+ case ECC_BRAINPOOLP224R1_OID:
+ return WC_NID_brainpoolP224r1;
+ case ECC_BRAINPOOLP256R1_OID:
+ return WC_NID_brainpoolP256r1;
+ case ECC_BRAINPOOLP320R1_OID:
+ return WC_NID_brainpoolP320r1;
+ case ECC_BRAINPOOLP384R1_OID:
+ return WC_NID_brainpoolP384r1;
+ case ECC_BRAINPOOLP512R1_OID:
+ return WC_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 WC_NID_des;
+ case DES3b:
+ return WC_NID_des3;
+ #endif
+ }
+ break;
-/* 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