From 638297a18a0d7bd9b067cf70de7d25d3ebb8f773 Mon Sep 17 00:00:00 2001 From: gojimmypi Date: Sun, 6 Apr 2025 13:01:22 +0200 Subject: [PATCH] Move Arduino examples, add GitHub workflow --- .github/ISSUE_TEMPLATE/bug_report.yaml | 60 ++ .github/ISSUE_TEMPLATE/other.yaml | 30 + .github/workflows/arduino.yml | 170 ++++ .gitignore | 6 + Arduino/README.md | 228 +++++ Arduino/sketches/README.md | 73 ++ Arduino/sketches/template/README.md | 34 + Arduino/sketches/template/template.adeps | 21 + Arduino/sketches/template/template.ino | 143 +++ Arduino/sketches/template/template.sln | 32 + Arduino/sketches/template/template.vgdbproj | 264 +++++ Arduino/sketches/template/wolfssl_helper.c | 52 + Arduino/sketches/template/wolfssl_helper.h | 37 + .../wolfssl_library/src/wolfssl_library.cpp | 42 + .../wolfssl_library/wolfssl_library.h | 46 + Arduino/sketches/wolfssl_AES_CTR/README.md | 34 + .../wolfssl_AES_CTR/wolfssl_AES_CTR.adeps | 21 + .../wolfssl_AES_CTR/wolfssl_AES_CTR.ino | 268 ++++++ .../wolfssl_AES_CTR/wolfssl_AES_CTR.sln | 22 + .../wolfssl_AES_CTR/wolfssl_AES_CTR.vgdbproj | 249 +++++ Arduino/sketches/wolfssl_client/README.md | 28 + .../wolfssl_client/wolfssl_client.ino | 903 ++++++++++++++++++ Arduino/sketches/wolfssl_server/README.md | 140 +++ .../wolfssl_server/wolfssl_server.ino | 847 ++++++++++++++++ Arduino/sketches/wolfssl_version/README.md | 3 + .../wolfssl_version/wolfssl_version.ino | 74 ++ 26 files changed, 3827 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yaml create mode 100644 .github/ISSUE_TEMPLATE/other.yaml create mode 100644 .github/workflows/arduino.yml create mode 100644 Arduino/README.md create mode 100644 Arduino/sketches/README.md create mode 100644 Arduino/sketches/template/README.md create mode 100644 Arduino/sketches/template/template.adeps create mode 100644 Arduino/sketches/template/template.ino create mode 100644 Arduino/sketches/template/template.sln create mode 100644 Arduino/sketches/template/template.vgdbproj create mode 100644 Arduino/sketches/template/wolfssl_helper.c create mode 100644 Arduino/sketches/template/wolfssl_helper.h create mode 100644 Arduino/sketches/template/wolfssl_library/src/wolfssl_library.cpp create mode 100644 Arduino/sketches/template/wolfssl_library/wolfssl_library.h create mode 100644 Arduino/sketches/wolfssl_AES_CTR/README.md create mode 100644 Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.adeps create mode 100644 Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.ino create mode 100644 Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.sln create mode 100644 Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.vgdbproj create mode 100644 Arduino/sketches/wolfssl_client/README.md create mode 100644 Arduino/sketches/wolfssl_client/wolfssl_client.ino create mode 100644 Arduino/sketches/wolfssl_server/README.md create mode 100644 Arduino/sketches/wolfssl_server/wolfssl_server.ino create mode 100644 Arduino/sketches/wolfssl_version/README.md create mode 100644 Arduino/sketches/wolfssl_version/wolfssl_version.ino diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 00000000..51384aad --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,60 @@ +name: Bug Report +description: File a bug report +title: "[Bug]: " +labels: ["bug", "triage"] +body: + - type: markdown + attributes: + value: > + Thanks for reporting a bug. If you would prefer a private method, + or if this is a vulnerability report please email support@wolfssl.com + instead. This is publicly viewable and not appropriate for vulnerability + reports. + - type: input + id: contact + attributes: + label: Contact Details + description: How can we get in touch with you if we need more info? + placeholder: ex. email@example.com + validations: + required: false + - type: input + id: version + attributes: + label: Version + description: What version were you using? + validations: + required: true + - type: textarea + id: details + attributes: + label: Description + description: | + Describe the issue in detail + Please include: + * Specific `./configure` options or `user_settings.h` + * Target and build environment + placeholder: | + Blinded by the light! + Code runs too fast. It's gone plaid! + ... + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Reproduction steps + description: If possible please give instructions on how to reproduce. + placeholder: | + 1. `./configure --enable-42` + 2. `make question` + 3. + ... + validations: + required: false + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell diff --git a/.github/ISSUE_TEMPLATE/other.yaml b/.github/ISSUE_TEMPLATE/other.yaml new file mode 100644 index 00000000..a10a56bd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other.yaml @@ -0,0 +1,30 @@ +name: General Issue +description: Request support with an issue +labels: ["triage"] +body: + - type: markdown + attributes: + value: > + Thanks for reporting an issue. If you would prefer a private method, + or if this is a vulnerability report please email support@wolfssl.com + instead. This is publicly viewable and not appropriate for vulnerability + reports. + - type: input + id: version + attributes: + label: Version + description: What version were you using? + validations: + required: true + - type: textarea + id: details + attributes: + label: Description + description: | + Describe the issue in detail. + Please include specific configuration options or user_settings.h + placeholder: | + `./configure --enable-world-domination` fails + ... + validations: + required: true diff --git a/.github/workflows/arduino.yml b/.github/workflows/arduino.yml new file mode 100644 index 00000000..153d6061 --- /dev/null +++ b/.github/workflows/arduino.yml @@ -0,0 +1,170 @@ +name: Arduino CI Build + +# See https://github.com/wolfSSL/Arduino-wolfSSL + +# TODO remove '*' om push/ branches, and uncomment github.repository_owner == 'wolfssl' + +# START OF COMMON SECTION +on: + push: + branches: [ '*', 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +# END OF COMMON SECTION + +jobs: + build: + # if: github.repository_owner == 'wolfssl' + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Install Arduino CLI + run: | + curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh + echo "$(pwd)/bin" >> $GITHUB_PATH + + - name: Setup Arduino CLI + run: | + arduino-cli config init + arduino-cli core update-index + arduino-cli config add board_manager.additional_urls https://www.pjrc.com/teensy/package_teensy_index.json + arduino-cli core update-index + arduino-cli config add board_manager.additional_urls https://arduino.esp8266.com/stable/package_esp8266com_index.json + arduino-cli core update-index + 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 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 "wolfSSL" # Install wolfSSL library from Arduino + + # Install current wolfSSL as an Arduino library: + - name: Shallow clone wolfssl + run: | + git clone --depth 1 https://github.com/wolfSSL/wolfssl.git + echo "Checking Arduino library directories..." + + - name: Install wolfSSL Arduino library + run: | + pushd wolfssl/IDE/ARDUINO + + # Set default ARDUINO_ROOT. TODO: once script is updated, this should be removed. + export ARDUINO_ROOT="$HOME/Arduino/libraries" + + bash wolfssl-arduino.sh INSTALL # Install wolfSSL library + popd + + # This will fail with Arduino published wolfSSL v5.7.6 and older + # See https://github.com/wolfSSL/wolfssl/pull/8514 + # Pending: "arduino:sam:arduino_due_x" + - name: Compile Arduino Sketches for various boards + run: | + set +e + SUCCESS=true + for BOARD in "arduino:avr:uno" "esp32:esp32:esp32" "arduino:avr:mega" "arduino:avr:nano" "arduino:samd:arduino_zero_native" "esp8266:esp8266:generic" "teensy:avr:teensy40"; do + echo "Compiling for $BOARD" + for EXAMPLE in $(find Arduino/sketches -mindepth 1 -maxdepth 1 -type d); do + + # skip known no-wifi SAMD boards + if [[ "$BOARD" =~ "arduino:samd:arduino_zero_native" && ( "$EXAMPLE" =~ "wolfssl_server" || "$EXAMPLE" =~ "wolfssl_client" || "$EXAMPLE" =~ "test" ) ]]; then + echo "Skipping $EXAMPLE for $BOARD (No WiFi support)" + continue + fi + + # skip known no-wifi AVR boards + if [[ "$BOARD" =~ ^arduino:avr:(uno|mega|nano)$ ]] && \ + ( [[ "$EXAMPLE" =~ "wolfssl_server" ]] || \ + [[ "$EXAMPLE" =~ "wolfssl_client" ]] || \ + [[ "$EXAMPLE" =~ "test" ]] ); then + echo "Skipping $EXAMPLE for $BOARD (No WiFi support)" + continue + fi + + # skip known no-wifi teensy AVR boards + if [[ "$BOARD" =~ ^teensy:avr:(teensy40)$ ]] && \ + ( [[ "$EXAMPLE" =~ "wolfssl_server" ]] || \ + [[ "$EXAMPLE" =~ "wolfssl_client" ]] || \ + [[ "$EXAMPLE" =~ "test" ]] ); then + echo "Skipping $EXAMPLE for $BOARD (needs ethernet update)" + continue + fi + + # skip examples other than template and version for known tiny memory boards + if [[ "$BOARD" =~ ( "arduino:avr:uno"|"arduino:avr:nano" ) && ( "$EXAMPLE" != "template" ) && ( "$EXAMPLE" != "wolfssl_version" ) ]]; then + echo "Skipping $EXAMPLE for $BOARD (memory limited)" + continue + fi + + # TODO: new template known to fail. Fixed in https://github.com/wolfSSL/wolfssl/pull/8514 + if [[ "$EXAMPLE" =~ "Arduino/sketches/template" ]]; then + echo "Skipping $EXAMPLE for $BOARD (needs code update. see wolfssl/pull/8514)" + continue + fi + + # TODO: new wolfssl_AES_CTR known to fail. Fixed in https://github.com/wolfSSL/wolfssl/pull/8514 + if [[ "$EXAMPLE" =~ "Arduino/sketches/wolfssl_AES_CTR" ]]; then + echo "Skipping $EXAMPLE for $BOARD (needs updated user_settings.h - see wolfssl/pull/8514)" + continue + fi + + # TODO skip Compiling Arduino/sketches/wolfssl_version for arduino:avr:mega + if [[ "$BOARD" =~ "arduino:avr:mega" && "$EXAMPLE" =~ "Arduino/sketches/wolfssl_version" ]]; then + echo "Skipping $EXAMPLE for $BOARD (needs updated code - see wolfssl/pull/8514)" + continue + fi + + # TODO skip Compiling Arduino/sketches/wolfssl_version for arduino:avr:uno + if [[ "$BOARD" =~ ^arduino:avr:(uno|mega|nano)$ ]] && \ + ( [[ "$EXAMPLE" =~ "wolfssl_version" ]] ); then + echo "Skipping $EXAMPLE for $BOARD (fixed in see wolfssl/pull/8514)" + continue + fi + + if [[ "$BOARD" =~ "arduino:avr:uno" && "$EXAMPLE" =~ "Arduino/sketches/wolfssl_version" ]]; then + echo "Skipping $EXAMPLE for $BOARD (needs updated code - see wolfssl/pull/8514)" + continue + fi + + # TODO skip ESP8266 + if [[ "$BOARD" =~ "esp8266:esp8266:generic" ]]; then + echo "Skipping $EXAMPLE for $BOARD (needs testing)" + continue + fi + + # If otherwise not excluded, compile this $EXAMPLE for this $BOARD + echo "Compiling $EXAMPLE for $BOARD" + arduino-cli compile --fqbn $BOARD "$EXAMPLE" + EXIT_CODE=$? + if [ "$EXIT_CODE" -ne 0 ]; then + echo "❌ Compilation failed for $EXAMPLE on $BOARD (Exit code: $EXIT_CODE)" + SUCCESS=false + else + echo "✅ Compilation succeeded for $EXAMPLE on $BOARD" + fi + done + done + + if [ "$SUCCESS" = true ]; then + echo "✅ All sketches compiled successfully!" + else + echo "❌ One or more sketches failed to compile." + exit 1 + fi + + - name: Upload Compilation Artifacts + uses: actions/upload-artifact@v4 + with: + name: compiled-sketch + path: Arduino/sketches/template/build/* diff --git a/.gitignore b/.gitignore index 57c2644d..863d4bde 100644 --- a/.gitignore +++ b/.gitignore @@ -369,3 +369,9 @@ tpm/evp_tpm # MacOS .DS_Store + +# Arduino exclusions +/Arduino/**/*.bak +/Arduino/**/Output/* +/Arduino/**/TraceReports/* +/Arduino/**/.visualgdb/* diff --git a/Arduino/README.md b/Arduino/README.md new file mode 100644 index 00000000..efcfca77 --- /dev/null +++ b/Arduino/README.md @@ -0,0 +1,228 @@ +# wolfSSL with Arduino + +The published [wolfssl](https://github.com/wolfSSL/wolfssl) +library source for Arduino is found in [Arduino-wolfSSL](https://github.com/wolfSSL/Arduino-wolfSSL). + +See the [example sketches](./sketches/README.md): + +Bare-bones templates: + +- [sketches/wolfssl_version](./sketches/wolfssl_version/README.md) single file. +- [sketches/template](./sketches/template/README.md) multiple file example. + +Functional examples: +- [sketches/wolfssl_AES_CTR](./sketches/wolfssl_AES_CTR/README.md) AES CTR Encrypt / decrypt. +- [sketches/wolfssl_client](./sketches/wolfssl_client/README.md) TLS Client. +- [sketches/wolfssl_server](./sketches/wolfssl_server/README.md) TLS Server. + +Both the `template` and `wolfssl_AES_CTR` examples include VisualGDB project files. + +When publishing a new version to the Arduino Registry, be sure to edit `WOLFSSL_VERSION_ARUINO_SUFFIX` in the `wolfssl-arduino.sh` script. + +## Getting Started + +See [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 `config.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. + +## Boards + +Many of the supported boards are natively built-in to the [Arduino IDE Board Manager](https://docs.arduino.cc/software/ide-v2/tutorials/ide-v2-board-manager/) +and by adding [additional cores](https://docs.arduino.cc/learn/starting-guide/cores/) as needed. + +STM32 Support can be added by including this link in the "Additional Boards Managers URLs" field +from [stm32duino/Arduino_Core_STM32](https://github.com/stm32duino/Arduino_Core_STM32?tab=readme-ov-file#getting-started). + +``` +https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json +``` + +## Using wolfSSL from the Arduino IDE + +The Official wolfSSL: https://github.com/wolfSSL/arduino-wolfSSL See [PR #1](https://github.com/wolfSSL/Arduino-wolfSSL/pull/1). + +This option will allow wolfSSL to be installed directly using the native Arduino tools. + +## Manually Reformatting wolfSSL as a Compatible Arduino Library + +Use [this](https://github.com/wolfSSL/wolfssl/blob/master/IDE/ARDUINO/wolfssl-arduino.sh) shell script that will re-organize the wolfSSL library to be +compatible with [Arduino Library Specification](https://arduino.github.io/arduino-cli/0.35/library-specification/) +for projects that use Arduino IDE 1.5.0 or newer. + +The Arduino IDE requires a library's source files to be in the library's root directory with a +header file in the name of the library. This script moves all `src/` files to the `IDE/ARDUINO/wolfSSL/src` +directory and creates a stub header file called `wolfssl.h` inside that directory. + +### Step 1: + +A local [wolfssl](https://github.com/wolfSSL/wolfssl) core library proper is needed. + +Examples below assume the `wolfssl` is cloned to `wolfssl-$USER`: + +```bash +cd /mnt/c/workspace +git clone https://github.com/wolfSSL/wolfssl wolfssl-$USER +``` + +or for Windows: + +```dos +cd c:\workspace +git clone https://github.com/wolfSSL/wolfssl wolfssl-%USERNAME% + +``` + +To configure wolfSSL with Arduino, enter ONE of the following 4 commands +from within the `wolfssl/IDE/ARDUINO` directory: + +1. `./wolfssl-arduino.sh` + - Creates an Arduino Library directory structure in the local `wolfSSL` directory of `IDE/ARDUINO`. + - You can add your own `user_settings.h`, or copy/rename the [default](https://github.com/wolfSSL/wolfssl/blob/master/examples/configs/user_settings_arduino.h). + +2. `./wolfssl-arduino.sh INSTALL` (The most common option) + - Creates an Arduino Library in the local `wolfSSL` directory + - Moves that directory to the Arduino library directory: + - `$HOME/Arduino/libraries` for most bash environments + - `/mnt/c/Users/$USER/Documents/Arduino/libraries` (for WSL) + - Adds the [default](https://github.com/wolfSSL/wolfssl/blob/master/examples/configs/user_settings_arduino.h) as `user_settings.h`. + - The wolfSSL library is now available from the Arduino IDE. + +3. `./wolfssl-arduino.sh INSTALL /path/to/repository` (Used to update [arduino-wolfSSL](https://github.com/wolfSSL/arduino-wolfSSL)) + - Creates an Arduino Library in `wolfSSL` directory + - Copies that directory contents to the specified `/path/to/repository` + - Adds the [default](https://github.com/wolfSSL/wolfssl/blob/master/examples/configs/user_settings_arduino.h) as `user_settings.h`. + +4. `./wolfssl-arduino.sh INSTALL /path/to/any/other/directory` + - Creates an Arduino Library in `wolfSSL` directory + - Copies that directory contents to the specified `/path/to/any/other/directory` + +### Step 2: + +Edit `/wolfSSL/src/user_settings.h` +If building for Intel Galileo platform add: `#define INTEL_GALILEO`. +Add any other custom settings. For a good start see the examples in wolfssl root +"[/examples/configs/user_settings_*.h](https://github.com/wolfssl/wolfssl/tree/master/examples/configs)" + +### Step 3: + +If you experience any issues with custom `user_settings.h` see the wolfssl +porting guide here for more assistance: https://www.wolfssl.com/docs/porting-guide/ + +If you have any issues contact support@wolfssl.com for help. + +# Including wolfSSL in Arduino Libraries (for Arduino version 2.0 or greater) + +1. In the Arduino IDE: + +The wolfSSL library should automatically be detected when found in the `libraries` +directory. + + - In `Sketch -> Include Library` choose wolfSSL for new sketches. + +##### wolfSSL Examples + +Open an [example Arduino sketch](./sketches/README.md) for wolfSSL: + + - [template](./sketches/template/README.md): `sketches/template/template.ino` + + - [wolfssl_AES_CTR](./wolfssl_AES_CTR/README.md): `sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.ino` + + - wolfSSL [Client INO sketch](./sketches/wolfssl_client/README.md): `sketches/wolfssl_client/wolfssl_client.ino` + + - wolfSSL [Server INO sketch](./sketches/wolfssl_server/README.md): `sketches/wolfssl_server/wolfssl_server.ino` + + - [wolfssl_version](./wolfssl_version/README.md): `sketches/wolfssl_version/wolfssl_version.ino` + +#### Script Examples + +Refresh the local Windows Arduino wolfSSL library from GitHub repository directory using WSL: + +Don't forget to edit `WOLFSSL_VERSION_ARUINO_SUFFIX`! + +```bash +# Change to the wolfSSL Arduino IDE directory +cd /mnt/c/workspace/wolfssl-$USER/IDE/ARDUINO + +# remove current Arduino wolfSSL library +rm -rf /mnt/c/Users/$USER/Documents/Arduino/libraries/wolfssl + +# Install wolfSSL as an Arduino library +./wolfssl-arduino.sh INSTALL +``` + +Publish wolfSSL from WSL to a `Arduino-wolfSSL-$USER` repository. + +```bash +cd /mnt/c/workspace/wolfssl-$USER/IDE/ARDUINO +rm -rf /mnt/c/Users/$USER/Documents/Arduino/libraries/wolfSSL +rm -rf /mnt/c/workspace/wolfssl-$USER/IDE/ARDUINO/wolfSSL +./wolfssl-arduino.sh INSTALL /mnt/c/workspace/Arduino-wolfSSL-$USER/ +``` + +Publish wolfSSL from WSL to default Windows local library. + +```bash +cd /mnt/c/workspace/wolfssl-$USER/IDE/ARDUINO +rm -rf /mnt/c/Users/$USER/Documents/Arduino/libraries/wolfSSL +rm -rf /mnt/c/workspace/wolfssl-arduino/IDE/ARDUINO/wolfSSL +./wolfssl-arduino.sh INSTALL +``` + +Test the TLS server by running a local command-line client. + +```bash +cd /mnt/c/workspace/wolfssl-$USER +./examples/client/client -h 192.168.1.43 -p 11111 -v 3 +``` + +Build wolfSSL to include wolfSSH support to an alternate development directory. + +```bash +cd /mnt/c/workspace/wolfssl-$USER +./configure --prefix=/mnt/c/workspace/wolfssh-$USER/wolfssl_install --enable-ssh +make +make install + +``` + +Build wolfSSH with wolfSSL not installed to default directory. + +```bash +cd /mnt/c/workspace/wolfssh-$USER +./configure --with-wolfssl=/mnt/c/workspace/wolfssh-$USER/wolfssl_install +make +./examples/client/client -u jill -h 192.168.1.34 -p 22222 -P upthehill +``` + +Test the current wolfSSL. + +```bash +cd /mnt/c/workspace/wolfssl-arduino +git status +./autogen.sh +./configure --enable-all +make clean +make && make test +``` + +Build and run `testwolfcrypt`. + +```bash +./autogen.sh +./configure --enable-all +make clean && make && ./wolfcrypt/test/testwolfcrypt +``` diff --git a/Arduino/sketches/README.md b/Arduino/sketches/README.md new file mode 100644 index 00000000..5fc0004e --- /dev/null +++ b/Arduino/sketches/README.md @@ -0,0 +1,73 @@ +# wolfSSL Arduino Examples + +There are currently five example Arduino sketches: + +* [template](./template/README.md): Reference template wolfSSL example, including optional VisualGDB project files. +* [wolfssl_AES_CTR](./wolfssl_AES_CTR/README.md): Basic AES CTR Encryption / Decryption example. +* [wolfssl_client](./wolfssl_client/README.md): Basic TLS listening client. +* [wolfssl_server](./wolfssl_server/README.md): Basic TLS server. +* [wolfssl_version](./wolfssl_version/README.md): Bare-bones wolfSSL example. + +Examples have been most recently confirmed operational on the +[Arduino IDE](https://www.arduino.cc/en/software) 2.2.1. + +For examples on other platforms, see the [IDE directory](https://github.com/wolfssl/wolfssl/tree/master/IDE). +Additional wolfssl examples can be found at [wolfSSL/wolfssl-examples](https://github.com/wolfSSL/wolfssl-examples/). + +## Using wolfSSL + +The typical include will look something like this: + +``` +#include + + /* 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 typically included in wolfssl.h, but here as a reminder: */ +#include + +/* Any other wolfSSL includes follow:* +#include +``` + +## Configuring wolfSSL + +See the `user_settings.h` in the Arduino library `wolfssl/src` directory. For Windows users this is typically: + +``` +C:\Users\%USERNAME%\Documents\Arduino\libraries\wolfssl\src +``` + +WARNING: Changes to the library `user_settings.h` file will be lost when upgrading wolfSSL using the Arduino IDE. + +## Troubleshooting + +If compile problems are encountered, for example: + +``` +ctags: cannot open temporary file : File exists +exit status 1 + +Compilation error: exit status 1 +``` + +Try deleting the Arduino cache directory: + +``` +C:\Users\%USERNAME%\AppData\Local\arduino\sketches +``` + +For VisualGDB users, delete the project `.vs`, `Output`, and `TraceReports` directories. + +## More Information + +For more details, see [IDE/ARDUINO/README.md](https://github.com/wolfSSL/wolfssl/blob/master/IDE/ARDUINO/README.md) diff --git a/Arduino/sketches/template/README.md b/Arduino/sketches/template/README.md new file mode 100644 index 00000000..5ce0cbf5 --- /dev/null +++ b/Arduino/sketches/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/Arduino/sketches/template/template.adeps b/Arduino/sketches/template/template.adeps new file mode 100644 index 00000000..ad537471 --- /dev/null +++ b/Arduino/sketches/template/template.adeps @@ -0,0 +1,21 @@ + + + + + Platform + + teensy + avr + 1.59.0 + + + + Library + + wolfSSL Inc. + wolfssl + 5.7.6 + + + + \ No newline at end of file diff --git a/Arduino/sketches/template/template.ino b/Arduino/sketches/template/template.ino new file mode 100644 index 00000000..89989769 --- /dev/null +++ b/Arduino/sketches/template/template.ino @@ -0,0 +1,143 @@ +/* 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 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 + +/* 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/Arduino/sketches/template/template.sln b/Arduino/sketches/template/template.sln new file mode 100644 index 00000000..f77943fd --- /dev/null +++ b/Arduino/sketches/template/template.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35728.132 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{803FD0C6-D64E-4E16-9DC3-1DAEC859A3D2}") = "template", "template.vgdbproj", "{DB43C533-4CE4-4470-90D2-87277C378CF8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Project Files", "Project Files", "{0BF06CD4-E54C-4212-BC24-278E0285C62B}" + ProjectSection(SolutionItems) = preProject + ..\README.md = ..\README.md + ..\..\wolfssl-arduino.sh = ..\..\wolfssl-arduino.sh + wolfssl_helper.c = wolfssl_helper.c + wolfssl_helper.h = wolfssl_helper.h + wolfssl_library\src\wolfssl_library.cpp = wolfssl_library\src\wolfssl_library.cpp + wolfssl_library\wolfssl_library.h = wolfssl_library\wolfssl_library.h + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Teensy_4 1 = Debug|Teensy_4 1 + Release|Teensy_4 1 = Release|Teensy_4 1 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DB43C533-4CE4-4470-90D2-87277C378CF8}.Debug|Teensy_4 1.ActiveCfg = Debug|Teensy_4 1 + {DB43C533-4CE4-4470-90D2-87277C378CF8}.Debug|Teensy_4 1.Build.0 = Debug|Teensy_4 1 + {DB43C533-4CE4-4470-90D2-87277C378CF8}.Release|Teensy_4 1.ActiveCfg = Release|Teensy_4 1 + {DB43C533-4CE4-4470-90D2-87277C378CF8}.Release|Teensy_4 1.Build.0 = Release|Teensy_4 1 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Arduino/sketches/template/template.vgdbproj b/Arduino/sketches/template/template.vgdbproj new file mode 100644 index 00000000..d9bebfef --- /dev/null +++ b/Arduino/sketches/template/template.vgdbproj @@ -0,0 +1,264 @@ + + + + + + Unknown + + true + + db43c533-4ce4-4470-90d2-87277c378cf8 + true + true + template + ../template.ino + + + + ../template.ino + + + + + + + + false + Output\$(PlatformName.defuse)\$(ConfigurationName.defuse) + false + + + + -Wl,-q + + true + + + + + + + + + + + + + Default + + + + COM102 + + 115200 + 8 + None + One + None + + + 0 + false + false + false + ASCII + + + 255 + 0 + 0 + 0 + + + 255 + 169 + 169 + 169 + + + 255 + 211 + 211 + 211 + + + 255 + 144 + 238 + 144 + + + 255 + 169 + 169 + 169 + + + + 16 + true + true + true + true + 0 + + LF + false + true + true + + + + true + + + + + True + + true + true + + Enabled + true + true + true + + true + + + + false + + + + + Teensy_4 1 + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + main + true + false + false + true + 0 + 0 + false + 0 + true + false + true + + + com.sysprogs.arm.openocd + + -f interface/ftdi/tigard.cfg -f target/imxrt.cfg -c "adapter speed 3000" + + + + false + + 131072 + Enabled + + set remotetimeout 60 + target extended-remote :$$SYS:GDB_PORT$$ + load + + false + 0 + 0 + false + + 5000 + + + true + Auto + 0 + false + false + true + false + false + + _estack + 0 + false + + + true + false + 0 + false + Size + NonBlocking + true + false + 255 + true + false + 4096 + false + + + + false + false + false + + + true + + + teensy:avr:teensy41 + COM102 + + + + usb + serial + + + speed + 600 + + + opt + o2std + + + keys + en-us + + + + Sketch + + + + + \ No newline at end of file diff --git a/Arduino/sketches/template/wolfssl_helper.c b/Arduino/sketches/template/wolfssl_helper.c new file mode 100644 index 00000000..f4eeb573 --- /dev/null +++ b/Arduino/sketches/template/wolfssl_helper.c @@ -0,0 +1,52 @@ +/* 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 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 +/* settings.h is typically included in wolfssl.h, but here as a reminder: */ +#include +#include + +#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/Arduino/sketches/template/wolfssl_helper.h b/Arduino/sketches/template/wolfssl_helper.h new file mode 100644 index 00000000..844f0223 --- /dev/null +++ b/Arduino/sketches/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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef _WOLFSSL_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/Arduino/sketches/template/wolfssl_library/src/wolfssl_library.cpp b/Arduino/sketches/template/wolfssl_library/src/wolfssl_library.cpp new file mode 100644 index 00000000..e4d9685f --- /dev/null +++ b/Arduino/sketches/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/Arduino/sketches/template/wolfssl_library/wolfssl_library.h b/Arduino/sketches/template/wolfssl_library/wolfssl_library.h new file mode 100644 index 00000000..98f5dfd7 --- /dev/null +++ b/Arduino/sketches/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/Arduino/sketches/wolfssl_AES_CTR/README.md b/Arduino/sketches/wolfssl_AES_CTR/README.md new file mode 100644 index 00000000..c9b26d65 --- /dev/null +++ b/Arduino/sketches/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/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.adeps b/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.adeps new file mode 100644 index 00000000..ad537471 --- /dev/null +++ b/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.adeps @@ -0,0 +1,21 @@ + + + + + Platform + + teensy + avr + 1.59.0 + + + + Library + + wolfSSL Inc. + wolfssl + 5.7.6 + + + + \ No newline at end of file diff --git a/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.ino b/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.ino new file mode 100644 index 00000000..31ef7973 --- /dev/null +++ b/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.ino @@ -0,0 +1,268 @@ +/* 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 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 + */ + +/* +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 +#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/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.sln b/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.sln new file mode 100644 index 00000000..fe45cbc8 --- /dev/null +++ b/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35728.132 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{803FD0C6-D64E-4E16-9DC3-1DAEC859A3D2}") = "wolfssl_AES_CTR", "wolfssl_AES_CTR.vgdbproj", "{86FF6ABD-3C7F-446C-B2CE-93E488EA77D9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Teensy_4 1 = Debug|Teensy_4 1 + Release|Teensy_4 1 = Release|Teensy_4 1 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {86FF6ABD-3C7F-446C-B2CE-93E488EA77D9}.Debug|Teensy_4 1.ActiveCfg = Debug|Teensy_4 1 + {86FF6ABD-3C7F-446C-B2CE-93E488EA77D9}.Debug|Teensy_4 1.Build.0 = Debug|Teensy_4 1 + {86FF6ABD-3C7F-446C-B2CE-93E488EA77D9}.Release|Teensy_4 1.ActiveCfg = Release|Teensy_4 1 + {86FF6ABD-3C7F-446C-B2CE-93E488EA77D9}.Release|Teensy_4 1.Build.0 = Release|Teensy_4 1 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.vgdbproj b/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.vgdbproj new file mode 100644 index 00000000..ec44b67d --- /dev/null +++ b/Arduino/sketches/wolfssl_AES_CTR/wolfssl_AES_CTR.vgdbproj @@ -0,0 +1,249 @@ + + + + + + Unknown + + true + + 86ff6abd-3c7f-446c-b2ce-93e488ea77d9 + true + true + wolfssl_AES_CTR + ../wolfssl_AES_CTR.ino + + + + ../wolfssl_AES_CTR.ino + + + + + + + + false + Output\$(PlatformName.defuse)\$(ConfigurationName.defuse) + false + + + -Wl,-q + + true + + + + + + + + + + + + + Default + + + + COM102 + + 115200 + 8 + None + One + None + + + 0 + false + false + false + ASCII + + + 255 + 0 + 0 + 0 + + + 255 + 169 + 169 + 169 + + + 255 + 211 + 211 + 211 + + + 255 + 144 + 238 + 144 + + + 255 + 169 + 169 + 169 + + + + 16 + true + true + true + true + 0 + + LF + false + true + true + + + + true + + + + + Unknown + + true + true + true + + + + false + + + + + Teensy_4 1 + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + main + true + false + false + true + 0 + false + 0 + true + false + true + + + com.sysprogs.arm.openocd + + -f interface/ftdi/tigard.cfg -f target/imxrt.cfg -c "adapter speed 3000" + + + + false + + 131072 + Enabled + + set remotetimeout 60 + target extended-remote :$$SYS:GDB_PORT$$ + load + + false + 0 + 0 + false + + 5000 + + + true + Auto + 0 + false + false + true + false + false + + _estack + 0 + false + + + true + false + 0 + false + Size + NonBlocking + true + false + 255 + true + false + 4096 + false + + true + + + teensy:avr:teensy41 + COM102 + + + + usb + serial + + + speed + 600 + + + opt + o2std + + + keys + en-us + + + + Sketch + + + + + diff --git a/Arduino/sketches/wolfssl_client/README.md b/Arduino/sketches/wolfssl_client/README.md new file mode 100644 index 00000000..3068931c --- /dev/null +++ b/Arduino/sketches/wolfssl_client/README.md @@ -0,0 +1,28 @@ +# Arduino Basic TLS Listening Client + +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) +- [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/Arduino/sketches/wolfssl_client/wolfssl_client.ino b/Arduino/sketches/wolfssl_client/wolfssl_client.ino new file mode 100644 index 00000000..31a21f15 --- /dev/null +++ b/Arduino/sketches/wolfssl_client/wolfssl_client.ino @@ -0,0 +1,903 @@ +/* wolfssl_client.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 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 + */ + +/* +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" */ + +/* 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 + +/* 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 + +/* 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_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(USING_WIFI) + #define USING_WIFI + #include + #include + #ifdef USE_NTP_LIB + WiFiUDP ntpUDP; + #endif + WiFiClient client; + +/* TODO +#elif defined(OTHER_BOARD) +*/ +#else + #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_TLS_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; +static int lng_index PROGMEM = 0; /* 0 = English */ + +#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; +} + +/*****************************************************************************/ +/* EthernetSend() to send a message string. */ +/*****************************************************************************/ +int EthernetSend(WOLFSSL* ssl, char* message, int sz, void* ctx) { + int sent = 0; + (void)ssl; + (void)ctx; + + sent = client.write((byte*)message, sz); + return sent; +} + +/*****************************************************************************/ +/* EthernetReceive() to receive a reply string. */ +/*****************************************************************************/ +int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx) { + int ret = 0; + (void)ssl; + (void)ctx; + + while (client.available() > 0 && ret < sz) { + reply[ret++] = client.read(); + } + return ret; +} + +/*****************************************************************************/ +/* 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) + wolfSSL_Debugging_ON(); + Serial.println(F("wolfSSL Debugging is On!")); +#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 + + 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!"); + + method = wolfSSLv23_client_method(); + 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; + + 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 TLS Client Example Startup.")); + + /* define DEBUG_WOLFSSL in wolfSSL user_settings.h for diagnostics */ +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif + + /* 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(); + + /* Initialize wolfSSL using callback functions. */ + wolfSSL_SetIOSend(ctx, EthernetSend); + wolfSSL_SetIORecv(ctx, EthernetReceive); + + 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 */ + +/*****************************************************************************/ +/* 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; +} + +/*****************************************************************************/ +/*****************************************************************************/ +/* Arduino loop() */ +/*****************************************************************************/ +/*****************************************************************************/ +void loop() { + char reply[80]; + char msg[32] = "hello wolfssl!"; + const char* cipherName; + int retry_shutdown = SHUTDOWN_DELAY_MS; /* max try, once per millisecond */ + int total_input = 0; + int msgSz = 0; + int input = 0; + int ret = 0; + int err = 0; + msgSz = (int)strlen(msg); + Serial.println(F("")); + Serial.println(F("Starting Arduino loop() ...")); + + if (reconnect) { + reconnect--; + /* WiFi client returns true if connection succeeds, false if not. */ + /* Wired client returns int (1,-1,-2,-3,-4) for connection status. */ + Serial.print(F("Connecting to ")); + Serial.print(host); + Serial.print(F(":")); + Serial.println(port); + /* can also use: IPAddress server(192,168,1,37); */ + Serial.println(F("Here we go...")); + ret = client.connect(host, port); + Serial.println(F("Ok, checking...")); + if (ret > 0) { + Serial.println(F("Connected!")); + + /* initialize wolfSSL */ + ret = wolfSSL_Init(); + error_check(ret, false, F("calling wolfSSL_Init") ); + + /* create secure connection object. see setup for ctx certs. */ + Serial.println(F("Calling ssl = wolfSSL_new(ctx)")); + ssl = wolfSSL_new(ctx); + error_check_ssl(ssl, 0, true, F("Create WOLFSSL object from ctx")); + + Serial.print(F("Connecting to wolfSSL TLS Secure Server...")); + do { + err = 0; /* reset error */ + Serial.println(F("wolfSSL_connect ...")); + ret = wolfSSL_connect(ssl); + Serial.print("wolfSSL_connect return result ="); + Serial.println(ret); + 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); + + 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); + + /* see test.h + * TODO: test.h needs a little bit of Arduino work for these: + showPeerEx(ssl, lng_index); + showPeerPEM(ssl); + */ + + Serial.print(F("Sending secure message to server: ")); + Serial.println(msg); + ret = wolfSSL_write(ssl, msg, msgSz); + if (ret == msgSz) { + Serial.print(F("Waiting for Server response...")); + + while (!client.available()) { + /* wait for data */ + delay(1); /* 1 ms delay */ + } + + Serial.print(F("Reading response..")); + /* read data */ + do { + ret = wolfSSL_read(ssl, reply, sizeof(reply) - 1); + if (ret < 0) { + error_check_ssl(ssl, ret, false, + F("during TLS Read")); + } + else { + Serial.print(PROGRESS_DOT); + } + } while (err == WC_PENDING_E); + Serial.println(); + + Serial.println(); + Serial.println(reply); /* typically: I hear you fa shizzle! */ + Serial.println(); + + } /* wolfSSL_write message size matched */ + else { + error_check_ssl(ssl, ret, false, + F("during TLS Write")); + } /* any wolfSSL_write message size mismatch is an error */ + + Serial.print(F("Shutting down..")); + do { + delay(1); + Serial.print(PROGRESS_DOT); + retry_shutdown--; + ret = wolfSSL_shutdown(ssl); + } while ( (ret == WOLFSSL_SHUTDOWN_NOT_DONE) + && (retry_shutdown > 0) + ); /* There may be pending data, so wait until done. */ + Serial.println(); + + if (retry_shutdown <= 0) { + /* if wolfSSL_free is called before properly shutting down the + * ssl object, undesired results may occur. */ + Serial.println(F("Warning! Shutdown did not properly complete.")); + } + + wolfSSL_free(ssl); + client.stop(); + Serial.println(F("Connection complete.")); + if (REPEAT_CONNECTION) { + reconnect = RECONNECT_ATTEMPTS; + } + else { + reconnect = 0; + } + } /* client.connect(host, port) */ + else { + Serial.println(F("Problem sending message. Trying to reconnect...")); + } + } + delay(1000); + if ((reconnect > 0) && (REPEAT_CONNECTION)) { + Serial.println(F("Arduino loop repeating...")); + Serial.println(); + } + else { + printf("wow"); + Serial.println(F("Done!")); + while(1) { + /* wait forever */ + } + } + +#if defined(MEMORY_STRESS_TEST) + if (mem_ctr < MEMORY_STRESS_ITERATIONS) { + /* reminder: mem_ctr == 0 is MEMORY_STRESS_INITIAL allocation */ + mem_ctr++; + Serial.print(F("Memory stress increment: ")); + Serial.print(mem_ctr); + Serial.print(F(". Allocating addition memory (bytes): ")); + Serial.println(MEMORY_STRESS_BLOCK_SIZE); + memory_stress[mem_ctr] = (char*)malloc(MEMORY_STRESS_BLOCK_SIZE); + show_memory(); + } +#endif +} /* Arduino loop repeats */ diff --git a/Arduino/sketches/wolfssl_server/README.md b/Arduino/sketches/wolfssl_server/README.md new file mode 100644 index 00000000..e961d711 --- /dev/null +++ b/Arduino/sketches/wolfssl_server/README.md @@ -0,0 +1,140 @@ +# Arduino Basic TLS Server + +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) +- [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.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/Arduino/sketches/wolfssl_server/wolfssl_server.ino b/Arduino/sketches/wolfssl_server/wolfssl_server.ino new file mode 100644 index 00000000..ba315e19 --- /dev/null +++ b/Arduino/sketches/wolfssl_server/wolfssl_server.ino @@ -0,0 +1,847 @@ +/* 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 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 + */ + +/* +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" */ + +/* set REPEAT_CONNECTION to a non-zero value to continually run the example. */ +#define REPEAT_CONNECTION 1 + +/* Edit this with your other TLS host server address to connect to: */ +/* #define WOLFSSL_TLS_SERVER_HOST "192.168.1.34" */ + +/* 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 + +/* 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 + +/* 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 + 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_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(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 + #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 + + +/* we expect our IP address from DHCP */ + +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; +static int lng_index PROGMEM = 0; /* 0 = English */ + +#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; +} + +/*****************************************************************************/ +/* EthernetSend() to send a message string. */ +/*****************************************************************************/ +int EthernetSend(WOLFSSL* ssl, char* message, int sz, void* ctx) { + int sent = 0; + (void)ssl; + (void)ctx; + + sent = client.write((byte*)message, sz); + return sent; +} + +/*****************************************************************************/ +/* EthernetReceive() to receive a reply string. */ +/*****************************************************************************/ +int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx) { + int ret = 0; + (void)ssl; + (void)ctx; + + while (client.available() > 0 && ret < sz) { + reply[ret++] = client.read(); + } + return ret; +} + +/*****************************************************************************/ +/* 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) + wolfSSL_Debugging_ON(); + Serial.println(F("wolfSSL Debugging is On!")); +#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 + + 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!"); + + method = wolfSSLv23_server_method(); + if (method == NULL) { + Serial.println(F("unable to get wolfssl server 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; + + Serial.println(F("Initializing certificates...")); + show_memory(); + + /* Use built-in validation, No verification callback function: */ + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + + /* Certificate */ + 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(); + } + + 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 TLS Server Example Startup.")); + + /* define DEBUG_WOLFSSL in wolfSSL user_settings.h for diagnostics */ +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif + + /* 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(); + + /* Initialize wolfSSL using callback functions. */ + 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 + + /* 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; +} + +/*****************************************************************************/ +/*****************************************************************************/ +/* Arduino loop() */ +/*****************************************************************************/ +/*****************************************************************************/ +void loop() { + char errBuf[80] = "(no error"; + char reply[80] = "(no reply)"; + const char msg[] = "I hear you fa shizzle!"; + const char* cipherName; + int input = 0; + int replySz = 0; + int retry_shutdown = SHUTDOWN_DELAY_MS; /* max try, once per millisecond */ + int ret = 0; + IPAddress broadcast_address(255, 255, 255, 255); + + /* Listen for incoming client requests. */ + client = server.available(); + if (client) { + Serial.println("Have Client"); + while (!client.connected()) { + /* wait for the client to actually connect */ + delay(10); + } + Serial.print("Client connected from remote IP: "); + Serial.println(client.remoteIP()); + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + Serial.println("Unable to allocate SSL object"); + fail_wait(); + } + + ret = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + ret = wolfSSL_get_error(ssl, 0); + wolfSSL_ERR_error_string(ret, errBuf); + Serial.print("TLS Accept Error: "); + Serial.println(errBuf); + } + + cipherName = wolfSSL_get_cipher(ssl); + Serial.print("SSL cipher suite is "); + Serial.println(cipherName); + + Serial.print("Server Read: "); + while (!client.available()) { + /* wait for data */ + } + + /* read data */ + while (wolfSSL_pending(ssl)) { + input = wolfSSL_read(ssl, reply, sizeof(reply) - 1); + if (input < 0) { + ret = wolfSSL_get_error(ssl, 0); + wolfSSL_ERR_error_string(ret, errBuf); + Serial.print("TLS Read Error: "); + Serial.println(errBuf); + break; + } + else if (input > 0) { + replySz = input; + reply[input] = '\0'; + Serial.print(reply); + } + else { + Serial.println(""); + } + } + + /* Write our message into reply buffer to send */ + memset(reply, 0, sizeof(reply)); + memcpy(reply, msg, sizeof(msg)); + replySz = strnlen(reply, sizeof(reply)); + + Serial.println("Sending reply..."); + if ((wolfSSL_write(ssl, reply, replySz)) != replySz) { + ret = wolfSSL_get_error(ssl, 0); + wolfSSL_ERR_error_string(ret, errBuf); + Serial.print("TLS Write Error: "); + Serial.println(errBuf); + } + else { + Serial.println("Reply sent!"); + } + + Serial.println("Shutdown!"); + do { + delay(1); + retry_shutdown--; + ret = wolfSSL_shutdown(ssl); + } while ((ret == WOLFSSL_SHUTDOWN_NOT_DONE) && (retry_shutdown > 0)); + + if (retry_shutdown <= 0) { + /* if wolfSSL_free is called before properly shutting down the + * ssl object, undesired results may occur. */ + Serial.println("Warning! Shutdown did not properly complete."); + } + + wolfSSL_free(ssl); + Serial.println("Connection complete."); + if (REPEAT_CONNECTION) { + Serial.println(); + Serial.println("Waiting for next connection."); + } + else { + client.stop(); + Serial.println("Done!"); + while (1) { + /* wait forever if not repeating */ + delay(100); + } + } + } + else { + /* Serial.println("Client not connected. Trying again..."); */ + } + + delay(100); +} /* Arduino loop repeats */ diff --git a/Arduino/sketches/wolfssl_version/README.md b/Arduino/sketches/wolfssl_version/README.md new file mode 100644 index 00000000..3abfe829 --- /dev/null +++ b/Arduino/sketches/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/Arduino/sketches/wolfssl_version/wolfssl_version.ino b/Arduino/sketches/wolfssl_version/wolfssl_version.ino new file mode 100644 index 00000000..12be948f --- /dev/null +++ b/Arduino/sketches/wolfssl_version/wolfssl_version.ino @@ -0,0 +1,74 @@ +/* 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 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 + + /* 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); +}