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 " + * "