Browse Source

Update Arduino examples; add wolfcrypt breadcrumbs.

gojimmypi 1 month ago
parent
commit
e40eb3c774

+ 8 - 5
.gitignore

@@ -82,16 +82,19 @@ snifftest
 output
 mcapi/test
 testsuite/testsuite
-tests/unit
 testsuite/testsuite.test
+testsuite/*.der
+testsuite/*.pem
+testsuite/*.raw
+testsuite/*.obj
+testsuite/*.pdb
+testsuite/*.idb
+tests/unit
 tests/unit.test
 tests/bio_write_test.txt
 tests/test-log-dump-to-file.txt
 tests/cert_cache.tmp
 test-write-dhparams.pem
-testsuite/*.der
-testsuite/*.pem
-testsuite/*.raw
 cert.der
 cert.pem
 certecc.der
@@ -402,7 +405,7 @@ XXX-fips-test
 # Generated user_settings_asm.h.
 user_settings_asm.h
 
-# VisualGD
+# VisualGDB
 **/.visualgdb
 
 # Espressif sdk config default should be saved in sdkconfig.defaults

+ 10 - 1
IDE/ARDUINO/Arduino_README_prepend.md

@@ -1,4 +1,13 @@
 # Arduino wolfSSL Library
 
-The library is modified from wolfSSL Release ${WOLFSSL_VERSION} for the Arduino platform.
+This library is restructured from [wolfSSL](https://github.com/wolfSSL/wolfssl/) Release ${WOLFSSL_VERSION} for the Arduino platform.
 
+The Official wolfSSL Arduino Library is found in [The Library Manager index](http://downloads.arduino.cc/libraries/library_index.json).
+
+See the [Arduino-wolfSSL logs](https://downloads.arduino.cc/libraries/logs/github.com/wolfSSL/Arduino-wolfSSL/).
+
+## Arduino Releases
+
+The first Official wolfSSL Arduino Library is `5.6.6-Arduino.1`: a slightly modified, post [release 5.6.6](https://github.com/wolfSSL/wolfssl/releases/tag/v5.6.6-stable) version update.
+
+See other [wolfSSL releases versions](https://github.com/wolfSSL/wolfssl/releases). The `./wolfssl-arduino.sh INSTALL` [script](https://github.com/wolfSSL/wolfssl/tree/master/IDE/ARDUINO) can be used to install specific GitHub versions as needed.

+ 28 - 3
IDE/ARDUINO/README.md

@@ -1,5 +1,14 @@
 # wolfSSL with Arduino
 
+See the [example sketches](./sketches/README.md):
+
+- [sketches/wolfssl_server](./sketches/wolfssl_server/README.md)
+- [sketches/wolfssl_client](./sketches/wolfssl_client/README.md)
+
+When publishing a new version to the Arduino Registry, be sure to edit `WOLFSSL_VERSION_ARUINO_SUFFIX` in the `wolfssl-arduino.sh` script.
+
+## 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.
 
@@ -12,7 +21,7 @@ https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectron
 
 ## Using wolfSSL from the Arduino IDE
 
-Coming soon! https://github.com/wolfSSL/arduino-wolfSSL See [PR #1](https://github.com/wolfSSL/Arduino-wolfSSL/pull/1).
+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.
 
@@ -28,7 +37,7 @@ directory and creates a stub header file called `wolfssl.h` inside that director
 
 ### Step 1:
 
-To configure wolfSSL with Arduino, enter one of the following commands
+To configure wolfSSL with Arduino, enter ONE of the following 4 commands
 from within the `wolfssl/IDE/ARDUINO` directory:
 
 1. `./wolfssl-arduino.sh`
@@ -93,9 +102,25 @@ Open an example Arduino sketch for wolfSSL:
 
 #### Script Examples
 
-Publish wolfSSL from WSL to a repository.
+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/

+ 1 - 0
IDE/ARDUINO/include.am

@@ -11,4 +11,5 @@ EXTRA_DIST+= IDE/ARDUINO/sketches/wolfssl_client/README.md
 EXTRA_DIST+= IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino
 EXTRA_DIST+= IDE/ARDUINO/sketches/wolfssl_server/README.md
 EXTRA_DIST+= IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino
+EXTRA_DIST+= IDE/ARDUINO/wolfssl.h
 EXTRA_DIST+= IDE/ARDUINO/wolfssl-arduino.sh

+ 2 - 2
IDE/ARDUINO/library.properties.template

@@ -1,6 +1,6 @@
-name=wolfSSL
+name=wolfssl
 version=${WOLFSSL_VERSION}${WOLFSSL_VERSION_ARUINO_SUFFIX}
-author=wolfSSL inc
+author=wolfSSL Inc.
 maintainer=wolfSSL inc <support@wolfssl.com>
 sentence=A lightweight SSL/TLS library written in ANSI C and targeted for embedded, RTOS, and resource-constrained environments.
 paragraph=Manual: https://www.wolfssl.com/documentation/manuals/wolfssl/index.html.

+ 816 - 103
IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino

@@ -20,157 +20,870 @@
  */
 
 /*
- This was original tested with Intel Galileo acting as the Client, with a 
-laptop acting as a server using the server example provided in examples/server.
-Legacy Ardunio v1.86 was used to compile and program the Galileo 
+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
 */
 
-#define USE_CERT_BUFFERS_2048
+/*
+ * 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.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
+    const char* ssid PROGMEM = CONFIG_ESP_WIFI_SSID;
+    const char* password PROGMEM  = CONFIG_ESP_WIFI_PASSWORD;
+#else
+    /* when using WiFi capable boards: */
+    const char* ssid PROGMEM  = "your_SSID";
+    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 <NTPClient.h>
+#endif
+
 #include <wolfssl.h>
+/* Important: make sure settings.h appears before any other wolfSSL headers */
+#include <wolfssl/wolfcrypt/settings.h>
+/* Reminder: settings.h includes user_settings.h
+ * For ALL project wolfSSL settings, see:
+ * [your path]/Arduino\libraries\wolfSSL\src\user_settings.h   */
 #include <wolfssl/ssl.h>
-#include <Ethernet.h>
 #include <wolfssl/certs_test.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
+
+/* 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 <WiFi.h>
+    #include <WiFiUdp.h>
+    #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 <ESP8266WiFi.h>
+    WiFiClient client;
+
+#elif defined(ARDUINO_SAM_DUE)
+    #include <SPI.h>
+    /* 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 <Ethernet.h>
+    EthernetClient client;
+
+#elif defined(ARDUINO_SAMD_NANO_33_IOT)
+    #define USING_WIFI
+    #include <SPI.h>
+    #include <WiFiNINA.h>
+    WiFiClient client;
+
+#elif defined(ARDUINO_ARCH_RP2040)
+    #define USING_WIFI
+    #include <SPI.h>
+    #include <WiFiNINA.h>
+    WiFiClient client;
 
+#elif defined(USING_WIFI)
+    #define USING_WIFI
+    #include <WiFi.h>
+    #include <WiFiUdp.h>
+    #ifdef USE_NTP_LIB
+        WiFiUDP ntpUDP;
+    #endif
+    WiFiClient client;
 
-const char host[] = "192.168.1.148"; /* server to connect to */
-const int port = 11111; /* port on server to connect to */
+/* TODO
+#elif defined(OTHER_BOARD)
+*/
+#else
+    #define USING_WIFI
+    WiFiClient client;
+
+#endif
 
-int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx);
-int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx);
-int reconnect = 10;
+/* 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
 
-EthernetClient client;
+const char host[] PROGMEM = WOLFSSL_TLS_SERVER_HOST; /* server to connect to */
+const int port PROGMEM = WOLFSSL_PORT; /* port on server to connect to */
+const int serial_baud PROGMEM = SERIAL_BAUD; /* local serial port to monitor */
 
 WOLFSSL_CTX* ctx = NULL;
 WOLFSSL* ssl = NULL;
+char* wc_error_message = (char*)malloc(80 + 1);
+char errBuf[80];
+
+#if defined(MEMORY_STRESS_TEST)
+    #define MEMORY_STRESS_ITERATIONS 100
+    #define MEMORY_STRESS_BLOCK_SIZE 1024
+    #define MEMORY_STRESS_INITIAL (4*1024)
+    char* memory_stress[MEMORY_STRESS_ITERATIONS]; /* typically 1K per item */
+    int mem_ctr        = 0;
+#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 <malloc.h>
+    extern char _end;
+    extern "C" char *sbrk(int i);
+    char *ramstart=(char *)0x20070000;
+    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;
 
-void setup() {
+    if (WiFi.status() == WL_NO_MODULE) {
+        Serial.println("Communication with WiFi module failed!");
+        /* don't continue if no network */
+        while (true) ;
+    }
+
+    String fv = WiFi.firmwareVersion();
+    if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
+        Serial.println("Please upgrade the firmware");
+    }
+
+    /* The ESP8266 & ESP32 support both AP and STA. We'll use STA: */
+    #if defined(ESP8266) || defined(ESP32)
+        WiFi.mode(WIFI_STA);
+    #endif
+
+    Serial.print(F("Connecting to WiFi "));
+    Serial.print(ssid);
+    while (status != WL_CONNECTED) {
+        status = WiFi.begin(ssid, password);
+        delay(5000);
+        Serial.print(F("."));
+    }
+
+    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;
-    /* Initialize Return Code */
-    int rc;
-    Serial.begin(9600);
-    /* Delay need to ensure connection to server */
-    delay(4000);
 
-    method = wolfTLSv1_2_client_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("unable to get method");
-    return;
+        Serial.println(F("unable to get wolfssl client method"));
+        fail_wait();
     }
     ctx = wolfSSL_CTX_new(method);
     if (ctx == NULL) {
-        Serial.println("unable to get ctx");
-    return;
+        Serial.println(F("unable to get ctx"));
+        fail_wait();
     }
-    /* initialize wolfSSL using callback functions */
+
+    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);
-    rc = wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048,\
-                                        sizeof_ca_cert_der_2048,\
-                                        WOLFSSL_FILETYPE_ASN1);
-    Serial.print("\n\n Return code of load_verify is:");
-    Serial.println(rc);
-    Serial.println("");
-    rc = wolfSSL_CTX_use_certificate_buffer(ctx, client_cert_der_2048,\
-                                            sizeof_client_cert_der_2048,\
-                                            WOLFSSL_FILETYPE_ASN1);
-    Serial.print("\n\n Return code of use_certificate_buffer is:");
-    Serial.println(rc);
-    Serial.println("");
-    rc = wolfSSL_CTX_use_PrivateKey_buffer(ctx, client_key_der_2048,\
-                                            sizeof_client_key_der_2048,\
-                                            WOLFSSL_FILETYPE_ASN1);
-    Serial.print("\n\n Return code of use_PrivateKey_buffer is:");
-    Serial.println(rc);
-    Serial.println("");
+
+    /* 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) {
+    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 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_datetime();
+
+    setup_network();
+
+    setup_wolfssl();
+
+    setup_certificates();
+
+    /* Initialize wolfSSL using callback functions. */
     wolfSSL_SetIOSend(ctx, EthernetSend);
     wolfSSL_SetIORecv(ctx, EthernetReceive);
-    return;
-}
 
-int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx) {
-    int sent = 0;
-    sent = client.write((byte*)msg, sz);
-    return sent;
-}
+    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 */
 
-int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx) {
+/*****************************************************************************/
+/* wolfSSL error_check()                                                     */
+/*****************************************************************************/
+int error_check(int this_ret, bool halt_on_error,
+                      const __FlashStringHelper* message) {
     int ret = 0;
-    while (client.available() > 0 && ret < sz) {
-        reply[ret++] = client.read();
+    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() {
-    int err            = 0;
-    int input          = 0;
-    int total_input    = 0;
-    char msg[32]       = "hello wolfssl!";
-    int msgSz          = (int)strlen(msg);
-    char errBuf[80];
     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--;
-        if (client.connect(host, port)) {
-            Serial.print("Connected to ");
-            Serial.println(host);
+        /* 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);
-            if (ssl == NULL) {
-                Serial.println("Unable to allocate SSL object");
-                return;
-            }
-            err = wolfSSL_connect(ssl);
-            if (err != WOLFSSL_SUCCESS) {
-                err = wolfSSL_get_error(ssl, 0);
-                wolfSSL_ERR_error_string(err, errBuf);
-                Serial.print("TLS Connect Error: ");
-                Serial.println(errBuf);
-            }
-            Serial.print("SSL version is ");
+            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("SSL cipher suite is ");
+            Serial.print(F("SSL cipher suite is "));
             Serial.println(cipherName);
-            if ((wolfSSL_write(ssl, msg, msgSz)) == msgSz) {
-                Serial.print("Server response: ");
-                /* wait for data */
-                while (!client.available()) {}
+
+            /* 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 */
-                while (wolfSSL_pending(ssl)) {
-                    input = wolfSSL_read(ssl, reply, sizeof(reply) - 1);
-                    total_input += input;
-                    if (input < 0) {
-                        err = wolfSSL_get_error(ssl, 0);
-                        wolfSSL_ERR_error_string(err, errBuf);
-                        Serial.print("TLS Read Error: ");
-                        Serial.println(errBuf);
-                        break;
-                    } 
-                    else if (input > 0) {
-                        reply[input] = '\0';
-                        Serial.print(reply);
+                do {
+                    ret = wolfSSL_read(ssl, reply, sizeof(reply) - 1);
+                    if (ret < 0) {
+                        error_check_ssl(ssl, ret, false,
+                                        F("during TLS Read"));
                     }
                     else {
-                        Serial.println();
+                        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 {
-                err = wolfSSL_get_error(ssl, 0);
-                wolfSSL_ERR_error_string(err, errBuf);
-                Serial.print("TLS Write Error: ");
-                Serial.println(errBuf);
+                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_shutdown(ssl);
+
             wolfSSL_free(ssl);
             client.stop();
-            Serial.println("Connection complete.");
-            reconnect = 0;
-        }
+            Serial.println(F("Connection complete."));
+            if (REPEAT_CONNECTION) {
+                reconnect = RECONNECT_ATTEMPTS;
+            }
+            else {
+                reconnect = 0;
+            }
+        } /* client.connect(host, port) */
         else {
-            Serial.println("Trying to reconnect...");
+            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 */

+ 779 - 125
IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino

@@ -19,161 +19,815 @@
  * 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
+    const char* ssid PROGMEM = CONFIG_ESP_WIFI_SSID;
+    const char* password PROGMEM  = CONFIG_ESP_WIFI_PASSWORD;
+#else
+    /* when using WiFi capable boards: */
+    const char* ssid PROGMEM  = "your_SSID";
+    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 <NTPClient.h>
+#endif
 
 #include <wolfssl.h>
+/* Important: make sure settings.h appears before any other wolfSSL headers */
+#include <wolfssl/wolfcrypt/settings.h>
+/* Reminder: settings.h includes user_settings.h
+ * For ALL project wolfSSL settings, see:
+ * [your path]/Arduino\libraries\wolfSSL\src\user_settings.h   */
 #include <wolfssl/ssl.h>
-#include <Ethernet.h>
-
-#define USE_CERT_BUFFERS_256
 #include <wolfssl/certs_test.h>
+#include <wolfssl/wolfcrypt/error-crypt.h>
 
-#ifdef NO_WOLFSSL_SERVER
-  #error Please undefine NO_WOLFSSL_SERVER for this example
+/* 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
 
-const int port = 11111; /* port to listen on */
+/* Convert a macro to a string */
+#define xstr(x) str(x)
+#define str(x) #x
 
-int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx);
-int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx);
+/* optional board-specific networking includes */
+#if defined(ESP32)
+    #define USING_WIFI
+    #include <WiFi.h>
+    #include <WiFiUdp.h>
+    #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 <ESP8266WiFi.h>
+    WiFiClient client;
+    WiFiServer server(WOLFSSL_PORT);
+#elif defined(ARDUINO_SAM_DUE)
+    #include <SPI.h>
+    /* 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 <Ethernet.h>
+    EthernetClient client;
+    EthernetClient server(WOLFSSL_PORT);
+#elif defined(ARDUINO_SAMD_NANO_33_IOT)
+    #define USING_WIFI
+    #include <SPI.h>
+    #include <WiFiNINA.h>
+    WiFiClient client;
+    WiFiServer server(WOLFSSL_PORT);
+#elif defined(ARDUINO_ARCH_RP2040)
+    #define USING_WIFI
+    #include <SPI.h>
+    #include <WiFiNINA.h>
+    WiFiClient client;
+    WiFiServer server(WOLFSSL_PORT);
+#elif defined(USING_WIFI)
+    #define USING_WIFI
+    #include <WiFi.h>
+    #include <WiFiUdp.h>
+    #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
 
-EthernetServer server(port);
-EthernetClient client;
+
+/* we expect our IP address from DHCP */
+const int serial_baud = SERIAL_BAUD; /* local serial port to monitor */
 
 WOLFSSL_CTX* ctx = NULL;
 WOLFSSL* ssl = NULL;
+char* wc_error_message = (char*)malloc(80 + 1);
+char errBuf[80];
 
-void setup() {
-  int err;
-  WOLFSSL_METHOD* method;
+#if defined(MEMORY_STRESS_TEST)
+    #define MEMORY_STRESS_ITERATIONS 100
+    #define MEMORY_STRESS_BLOCK_SIZE 1024
+    #define MEMORY_STRESS_INITIAL (4*1024)
+    char* memory_stress[MEMORY_STRESS_ITERATIONS]; /* typically 1K per item */
+    int mem_ctr        = 0;
+#endif
 
-  Serial.begin(9600);
+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 */
 
-  method = wolfTLSv1_2_server_method();
-  if (method == NULL) {
-    Serial.println("unable to get method");
-    return;
-  }
-  ctx = wolfSSL_CTX_new(method);
-  if (ctx == NULL) {
-    Serial.println("unable to get ctx");
-    return;
-  }
-
-  /* initialize wolfSSL using callback functions */
-  wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
-  wolfSSL_SetIOSend(ctx, EthernetSend);
-  wolfSSL_SetIORecv(ctx, EthernetReceive);
-
-  /* setup the private key and certificate */
-  err = wolfSSL_CTX_use_PrivateKey_buffer(ctx, ecc_key_der_256, 
-    sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1);
-  if (err != WOLFSSL_SUCCESS) {
-    Serial.println("error setting key");
-    return;
-  }
-  err = wolfSSL_CTX_use_certificate_buffer(ctx, serv_ecc_der_256, 
-    sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1);
-  if (err != WOLFSSL_SUCCESS) {
-    Serial.println("error setting certificate");
-    return;
-  }
+#if defined(__arm__)
+    #include <malloc.h>
+    extern char _end;
+    extern "C" char *sbrk(int i);
+    char *ramstart=(char *)0x20070000;
+    char *ramend=(char *)0x20088000;
+#endif
 
-  /* Start the server */
-  server.begin();
-  
-  return;
+/*****************************************************************************/
+/* fail_wait - in case of unrecoverable error                                */
+/*****************************************************************************/
+int fail_wait(void) {
+    show_memory();
+
+    Serial.println(F("Failed. Halt."));
+    while (1) {
+        delay(1000);
+    }
+    return 0;
 }
 
-int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx) {
-  int sent = 0;
+/*****************************************************************************/
+/* show_memory() to optionally view during debugging.                         */
+/*****************************************************************************/
+int show_memory(void)
+{
+#if defined(__arm__)
+    struct mallinfo mi = mallinfo();
 
-  sent = client.write((byte*)msg, sz);
+    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
 
-  return sent;
+    #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;
+    int ret = 0;
+    (void)ssl;
+    (void)ctx;
 
-  while (client.available() > 0 && ret < sz) {
-    reply[ret++] = client.read();
-  }
+    while (client.available() > 0 && ret < sz) {
+        reply[ret++] = client.read();
+    }
+    return ret;
+}
 
-  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;
 }
 
-void loop() {
-  int err = 0;
-  int input = 0;
-  char errBuf[80];
-  char reply[80];
-  int replySz = 0;
-  const char* cipherName;
-
-  /* Listen for incoming client requests. */
-  client = server.available();
-  if (!client) {
+/*****************************************************************************/
+/* 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;
+
+    if (WiFi.status() == WL_NO_MODULE) {
+        Serial.println("Communication with WiFi module failed!");
+        /* don't continue if no network */
+        while (true) ;
+    }
+
+    String fv = WiFi.firmwareVersion();
+    if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
+        Serial.println("Please upgrade the firmware");
+    }
+
+    /* The ESP8266 & ESP32 support both AP and STA. We'll use STA: */
+    #if defined(ESP8266) || defined(ESP32)
+        WiFi.mode(WIFI_STA);
+    #endif
+
+    Serial.print(F("Connecting to WiFi "));
+    Serial.print(ssid);
+    while (status != WL_CONNECTED) {
+        status = WiFi.begin(ssid, password);
+        delay(5000);
+        Serial.print(F("."));
+    }
+
+    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) {
+    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 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_datetime();
+
+    setup_network();
+
+    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 */
 
-  if (client.connected()) {
+/*****************************************************************************/
+/* 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();
 
-    Serial.println("Client connected");
+    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;
 
-    ssl = wolfSSL_new(ctx);
     if (ssl == NULL) {
-      Serial.println("Unable to allocate SSL object");
-      return;
-    }
-
-    err = wolfSSL_accept(ssl);
-    if (err != WOLFSSL_SUCCESS) {
-      err = wolfSSL_get_error(ssl, 0);
-      wolfSSL_ERR_error_string(err, errBuf);
-      Serial.print("TLS Accept Error: ");
-      Serial.println(errBuf);
-    }
-
-    Serial.print("SSL version is ");
-    Serial.println(wolfSSL_get_version(ssl));
-    
-    cipherName = wolfSSL_get_cipher(ssl);
-    Serial.print("SSL cipher suite is ");
-    Serial.println(cipherName);
-
-    Serial.print("Server Read: ");
-    /* wait for data */
-    while (!client.available()) {}
-    /* read data */
-    while (wolfSSL_pending(ssl)) {
-      input = wolfSSL_read(ssl, reply, sizeof(reply) - 1);
-      if (input < 0) {
-        err = wolfSSL_get_error(ssl, 0);
-        wolfSSL_ERR_error_string(err, 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();
-      }
-    }
-
-    /* echo data */
-    if ((wolfSSL_write(ssl, reply, replySz)) != replySz) {
-      err = wolfSSL_get_error(ssl, 0);
-      wolfSSL_ERR_error_string(err, errBuf);
-      Serial.print("TLS Write Error: ");
-      Serial.println(errBuf);
-    }
-    
-    wolfSSL_shutdown(ssl);
-    wolfSSL_free(ssl);
-  }
-
-  client.stop();
-  Serial.println("Connection complete");
+        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("<end of reply, input == 0>");
+            }
+        }
+
+        /* 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 */

+ 98 - 65
IDE/ARDUINO/wolfssl-arduino.sh

@@ -4,19 +4,32 @@
 # an Arduino project
 # run as bash ./wolfssl-arduino.sh [INSTALL] [path]
 #
+# ./wolfssl-arduino.sh
 # The default is to install to a local wolfSSL directory (`ROOT_DIR`).
 # If successfully built, and the INSTALL option is used, tis directory
 # is then moved to the target.
 #
+# ./wolfssl-arduino.sh INSTALL
+# Creates a local wolfSSL directory and then moves it to the ARDUINO_ROOT
+#
+# ./wolfssl-arduino.sh INSTALL /mnt/c/workspace/Arduino-wolfSSL-$USER
+# Updates the Arduino-wolfSSL fork for $USER to refresh versions.
+#
 # To ensure a pristine build, the directory must not exist.
 #
 # Reminder there's typically no $USER for GitHub actions, but:
 # ROOT_DIR="/mnt/c/Users/$USER/Documents/Arduino/libraries"
 #
-ROOT_DIR="/wolfSSL"
+# The company name is "wolfSSL Inc."; There’s a space, no comma, and a period after "Inc."
+# The Arduino library name is "wolfssl" (all lower case)
+# The Arduino library directory name is "wolfssl" (all lower case)
+# The Arduino library include file is "wolfssl.h" (all lower case)
+# The Published wolfSSL Arduino Registry is at https://github.com/wolfSSL/Arduino-wolfSSL.git
+# See https://downloads.arduino.cc/libraries/logs/github.com/wolfSSL/Arduino-wolfSSL/
+ROOT_DIR="/wolfssl"
 
 # The Arduino Version will initially have a suffix appended during fine tuning stage.
-WOLFSSL_VERSION_ARUINO_SUFFIX="01"
+WOLFSSL_VERSION_ARUINO_SUFFIX="-Arduino.2"
 
 # For verbose copy, set CP_CMD="-v", otherwise clear it: CP_CMD="cp"
 # Do not set to empty string, as copy will fail with this: CP_CMD=""
@@ -32,7 +45,7 @@ MY_SHELLCHECK="shellcheck"
 # Unlike a local Arduino library that requires a clean directory,
 # we'll allow extra files, overwrites, etc.
 #
-# Note in all cases, the local IDE/ARDUINO/wolfSSL must be empty.
+# Note in all cases, the local IDE/ARDUINO/wolfssl must be empty.
 THIS_INSTALL_IS_GITHUB="false"
 
 # Check if the executable is available in the PATH
@@ -97,6 +110,7 @@ fi
 
 
 ROOT_SRC_DIR="${ROOT_DIR}/src"
+EXAMPLES_DIR="${ROOT_DIR}/examples"
 WOLFSSL_SRC="${ROOT_SRC_DIR}/src"
 WOLFSSL_HEADERS="${ROOT_SRC_DIR}/wolfssl"
 WOLFCRYPT_ROOT="${ROOT_SRC_DIR}/wolfcrypt"
@@ -121,100 +135,111 @@ if [ "$WOLFSSL_VERSION" = "" ]; then
     exit 1
 else
     echo "Found wolfSSL version $WOLFSSL_VERSION"
+    echo "# WOLFSSL_VERSION_ARUINO_SUFFIX $WOLFSSL_VERSION_ARUINO_SUFFIX"
 fi
+echo ""
 
 THIS_DIR=${PWD##*/}
 
 if [ "$THIS_DIR" = "ARDUINO" ]; then
-    # mkdir ./wolfSSL
+    # mkdir ./wolfssl
     if [ -d ".${ROOT_DIR}" ]; then
         echo "ERROR: $(realpath ".${ROOT_DIR}") is not empty"
         exit 1
     else
         echo "Step 01: mkdir .${ROOT_DIR}"
-        mkdir .${ROOT_DIR}
+        mkdir ."${ROOT_DIR}"
     fi
 
-    # mkdir ./wolfSSL/src
+    # mkdir ./wolfssl/src
     if [ ! -d ".${ROOT_SRC_DIR}" ]; then
         echo "Step 02: mkdir .${ROOT_SRC_DIR}"
-        mkdir .${ROOT_SRC_DIR}
+        mkdir ."${ROOT_SRC_DIR}"
     fi
 
-    # mkdir ./wolfSSL/src/wolfssl
+    # mkdir ./wolfssl/src/wolfssl
     if [ ! -d ".${WOLFSSL_HEADERS}" ]; then
         echo "Step 03: mkdir .${WOLFSSL_HEADERS}"
-        mkdir .${WOLFSSL_HEADERS}
+        mkdir ."${WOLFSSL_HEADERS}"
     fi
 
-    #  cp ../../wolfssl/*.h  ./wolfSSL/src/wolfssl
-    echo "Step 04: cp    ${WOLFSSL_HEADERS_TOP}/*.h               .${WOLFSSL_HEADERS}"
-    $CP_CMD ${WOLFSSL_HEADERS_TOP}/*.h .${WOLFSSL_HEADERS}
+    #  cp ../../wolfssl/*.h  ./wolfssl/src/wolfssl
+    echo "Step 04: cp    ${WOLFSSL_HEADERS_TOP}/*.h              .${WOLFSSL_HEADERS}"
+    $CP_CMD "${WOLFSSL_HEADERS_TOP}"/*.h ."${WOLFSSL_HEADERS}"
     if [ ! -d ".${WOLFCRYPT_HEADERS}" ]; then
-        #  mkdir ./wolfSSL/src/wolfssl/wolfcrypt
+        #  mkdir ./wolfssl/src/wolfssl/wolfcrypt
         echo "Step 05: mkdir .${WOLFCRYPT_HEADERS}"
-        mkdir .${WOLFCRYPT_HEADERS}
-        mkdir .${WOLFCRYPT_HEADERS}/port
-        mkdir .${WOLFCRYPT_HEADERS}/port/atmel
-        mkdir .${WOLFCRYPT_HEADERS}/port/Espressif
+        mkdir ."${WOLFCRYPT_HEADERS}"
+        mkdir ."${WOLFCRYPT_HEADERS}/port"
+        mkdir ."${WOLFCRYPT_HEADERS}/port/atmel"
+        mkdir ."${WOLFCRYPT_HEADERS}/port/Espressif"
     fi
 
-    # cp  ../../wolfssl/wolfcrypt/*.h  ./wolfSSL/src/wolfssl/wolfcrypt
-    echo "Step 06: cp    ${WOLFCRYPT_HEADERS_TOP}/*.h     .${WOLFCRYPT_HEADERS}"
-    $CP_CMD ${WOLFCRYPT_HEADERS_TOP}/*.h                .${WOLFCRYPT_HEADERS}                 || exit 1
-    $CP_CMD ${WOLFCRYPT_HEADERS_TOP}/port/atmel/*.h     .${WOLFCRYPT_HEADERS}/port/atmel      || exit 1
-    $CP_CMD ${WOLFCRYPT_HEADERS_TOP}/port/Espressif/*.h .${WOLFCRYPT_HEADERS}/port/Espressif  || exit 1
+    # cp  ../../wolfssl/wolfcrypt/*.h  ./wolfssl/src/wolfssl/wolfcrypt
+    echo "Step 06: cp    ${WOLFCRYPT_HEADERS_TOP}/*.h    .${WOLFCRYPT_HEADERS}"
+    $CP_CMD "${WOLFCRYPT_HEADERS_TOP}"/*.h                ."${WOLFCRYPT_HEADERS}"                 || exit 1
+    $CP_CMD "${WOLFCRYPT_HEADERS_TOP}"/port/atmel/*.h     ."${WOLFCRYPT_HEADERS}/port/atmel"      || exit 1
+    $CP_CMD "${WOLFCRYPT_HEADERS_TOP}"/port/Espressif/*.h ."${WOLFCRYPT_HEADERS}/port/Espressif"  || exit 1
 
     # Add in source files to wolfcrypt/src
     if [ ! -d ".${WOLFCRYPT_ROOT}" ]; then
-        # mkdir ./wolfSSL/src/wolfcrypt
+        # mkdir ./wolfssl/src/wolfcrypt
         echo "Step 07: mkdir .${WOLFCRYPT_ROOT}"
-        mkdir .${WOLFCRYPT_ROOT}
+        mkdir ."${WOLFCRYPT_ROOT}"
     fi
 
-    # mkdir ./wolfSSL/src/wolfcrypt/src
+    # mkdir ./wolfssl/src/wolfcrypt/src
     if [ ! -d ".${WOLFCRYPT_SRC}" ]; then
         echo "Step 08: mkdir .${WOLFCRYPT_SRC}"
-        mkdir .${WOLFCRYPT_SRC}
-        mkdir .${WOLFCRYPT_SRC}/port
-        mkdir .${WOLFCRYPT_SRC}/port/atmel
-        mkdir .${WOLFCRYPT_SRC}/port/Espressif
+        mkdir ."${WOLFCRYPT_SRC}"
+        mkdir ."${WOLFCRYPT_SRC}"/port
+        mkdir ."${WOLFCRYPT_SRC}"/port/atmel
+        mkdir ."${WOLFCRYPT_SRC}"/port/Espressif
     fi
 
-    # cp  ../../wolfcrypt/src/*.c  ./wolfSSL/src/wolfcrypt/src
-    echo "Step 09: cp    ${WOLFCRYPT_SRC_TOP}/*.c         .${WOLFCRYPT_SRC}"
-    $CP_CMD -r ${WOLFCRYPT_SRC_TOP}/*.c                  .${WOLFCRYPT_SRC}                || exit 1
-    $CP_CMD -r ${WOLFCRYPT_SRC_TOP}/port/atmel/*.c       .${WOLFCRYPT_SRC}/port/atmel     || exit 1
-    $CP_CMD -r ${WOLFCRYPT_SRC_TOP}/port/Espressif/*.c   .${WOLFCRYPT_SRC}/port/Espressif || exit 1
+    # cp  ../../wolfcrypt/src/*.c  ./wolfssl/src/wolfcrypt/src
+    echo "Step 09: cp    ${WOLFCRYPT_SRC_TOP}/*.c        .${WOLFCRYPT_SRC}"
+    $CP_CMD -r "${WOLFCRYPT_SRC_TOP}"/*.c                  ."${WOLFCRYPT_SRC}"                || exit 1
+    $CP_CMD -r "${WOLFCRYPT_SRC_TOP}"/port/atmel/*.c       ."${WOLFCRYPT_SRC}"/port/atmel     || exit 1
+    $CP_CMD -r "${WOLFCRYPT_SRC_TOP}"/port/Espressif/*.c   ."${WOLFCRYPT_SRC}"/port/Espressif || exit 1
 
     # Add in source files to top level src folders
     if [ ! -d ".${WOLFSSL_SRC}" ]; then
-        # mkdir ./wolfSSL/src/src
+        # mkdir ./wolfssl/src/src
         echo "Step 10: mkdir .${WOLFSSL_SRC}"
-        mkdir .${WOLFSSL_SRC}
+        mkdir ."${WOLFSSL_SRC}"
     fi
-    $CP_CMD ${WOLFSSL_SRC_TOP}/*.c .${WOLFSSL_SRC}                                        || exit 1
+    $CP_CMD "${WOLFSSL_SRC_TOP}"/*.c ."${WOLFSSL_SRC}"                                        || exit 1
     # put bio and evp as includes
-    $CP_CMD .${WOLFSSL_SRC}/bio.c .${WOLFSSL_HEADERS}                                     || exit 1
-    $CP_CMD .${WOLFCRYPT_SRC}/evp.c .${WOLFSSL_HEADERS}                                   || exit 1
+    $CP_CMD ."${WOLFSSL_SRC}"/bio.c   ."${WOLFSSL_HEADERS}"                                   || exit 1
+    $CP_CMD ."${WOLFCRYPT_SRC}"/evp.c ."${WOLFSSL_HEADERS}"                                   || exit 1
 
     # make a copy of evp.c and bio.c for ssl.c to include inline
-    $CP_CMD .${WOLFSSL_HEADERS}/evp.c .${WOLFCRYPT_SRC}/evp.c                             || exit 1
-    $CP_CMD .${WOLFSSL_HEADERS}/bio.c .${WOLFCRYPT_SRC}/bio.c                             || exit 1
+    $CP_CMD ."${WOLFSSL_HEADERS}"/evp.c ."${WOLFCRYPT_SRC}"/evp.c                             || exit 1
+    $CP_CMD ."${WOLFSSL_HEADERS}"/bio.c ."${WOLFCRYPT_SRC}"/bio.c                             || exit 1
 
     # copy openssl compatibility headers to their appropriate location
     if [ ! -d ".${OPENSSL_DIR}" ]; then
-        mkdir .${OPENSSL_DIR}
+        mkdir ."${OPENSSL_DIR}"
     fi
-    $CP_CMD ${OPENSSL_DIR_TOP}/* .${OPENSSL_DIR}                                          || exit 1
+    $CP_CMD "${OPENSSL_DIR_TOP}"/* ."${OPENSSL_DIR}"                                          || exit 1
+
+    # Finally, copy the Arduino-specific wolfssl library files into place: [lib]/src
+    $CP_CMD ./wolfssl.h ".${ROOT_SRC_DIR}"/wolfssl.h
 
+    echo "Copy examples...."
+    # Copy examples
+    mkdir -p ".${ROOT_SRC_DIR}"/examples
 
-    cat > .${ROOT_SRC_DIR}/wolfssl.h <<EOF
-/* Generated wolfSSL header file for Arduino */
-#include <user_settings.h>
-#include <wolfssl/wolfcrypt/settings.h>
-#include <wolfssl/ssl.h>
-EOF
+    echo "Copy wolfssl_client example...."
+    mkdir -p ".${EXAMPLES_DIR}"/wolfssl_client
+    $CP_CMD ./sketches/wolfssl_client/wolfssl_client.ino ".${EXAMPLES_DIR}"/wolfssl_client/wolfssl_client.ino || exit 1
+    $CP_CMD ./sketches/wolfssl_client/README.md          ".${EXAMPLES_DIR}"/wolfssl_client/README.md          || exit 1
+
+    echo "Copy wolfssl_server example...."
+    mkdir -p .${EXAMPLES_DIR}/wolfssl_server
+    $CP_CMD ./sketches/wolfssl_server/wolfssl_server.ino ".${EXAMPLES_DIR}"/wolfssl_server/wolfssl_server.ino || exit 1
+    $CP_CMD ./sketches/wolfssl_server/README.md          ".${EXAMPLES_DIR}"/wolfssl_server/README.md          || exit 1
 
 else
     echo "ERROR: You must be in the IDE/ARDUINO directory to run this script"
@@ -248,23 +273,23 @@ sed -i.backup  s/"$ARDUINO_VERSION_SUFFIX_PLACEHOLDER"/"$WOLFSSL_VERSION_ARUINO_
 # echo "${WOLFSSL_VERSION_ARUINO_SUFFIX}"
 
 echo "Step 11: Final root file copy"
-$CP_CMD  PREPENDED_README.md        .${ROOT_DIR}/README.md           || exit 1
-$CP_CMD  library.properties.tmp     .${ROOT_DIR}/library.properties  || exit 1
-$CP_CMD  ${TOP_DIR}/"LICENSING"     .${ROOT_DIR}/                    || exit 1
-$CP_CMD  ${TOP_DIR}/"README"        .${ROOT_DIR}/                    || exit 1
-$CP_CMD  ${TOP_DIR}/"COPYING"       .${ROOT_DIR}/                    || exit 1
-$CP_CMD  ${TOP_DIR}/"ChangeLog.md"  .${ROOT_DIR}/                    || exit 1
-$CP_CMD  ${TOP_DIR}/".editorconfig" .${ROOT_DIR}/                    || exit 1
-$CP_CMD  ${TOP_DIR}/".gitignore"    .${ROOT_DIR}/                    || exit 1
+$CP_CMD  PREPENDED_README.md          ."${ROOT_DIR}"/README.md           || exit 1
+$CP_CMD  library.properties.tmp       ."${ROOT_DIR}"/library.properties  || exit 1
+$CP_CMD  "${TOP_DIR}"/"LICENSING"     ."${ROOT_DIR}"/                    || exit 1
+$CP_CMD  "${TOP_DIR}"/"README"        ."${ROOT_DIR}"/                    || exit 1
+$CP_CMD  "${TOP_DIR}"/"COPYING"       ."${ROOT_DIR}"/                    || exit 1
+$CP_CMD  "${TOP_DIR}"/"ChangeLog.md"  ."${ROOT_DIR}"/                    || exit 1
+$CP_CMD  "${TOP_DIR}"/".editorconfig" ."${ROOT_DIR}"/                    || exit 1
+$CP_CMD  "${TOP_DIR}"/".gitignore"    ."${ROOT_DIR}"/                    || exit 1
 
-$CP_CMD  "keywords.txt"             .${ROOT_DIR}/                    || exit 1
+$CP_CMD  "keywords.txt"               ."${ROOT_DIR}"/                    || exit 1
 
 
-echo "Step 12: workspace to publish:"
+echo "Step 12: Workspace to publish:"
 echo ""
 head -n 3  PREPENDED_README.md
 echo ""
-ls ./wolfSSL -al
+ls ./wolfssl -al
 echo ""
 
 # Optionally install to a separate directory.
@@ -273,14 +298,22 @@ echo ""
 if [ "$THIS_OPERATION" = "INSTALL" ]; then
     if [ "$THIS_INSTALL_IS_GITHUB" = "true" ]; then
         echo "Installing to GitHub directory: $THIS_INSTALL_DIR"
-        cp -r ".$ROOT_DIR"/* "$THIS_INSTALL_DIR" || exit 1
+        cp -r ."$ROOT_DIR"/* "$THIS_INSTALL_DIR" || exit 1
     else
+        echo "Config:"
+        echo "cp ../../examples/configs/user_settings_arduino.h  ".${ROOT_SRC_DIR}"/user_settings.h"
+        # Nearly an ordinary copy, but we remove any lines with ">>" (typically edit with caution warning in comments)
+        grep -v '>>' ../../examples/configs/user_settings_arduino.h > ".${ROOT_SRC_DIR}"/user_settings.h || exit 1
+
+        # Show the user_settings.h revision string:
+        grep "WOLFSSL_USER_SETTINGS_ID" ."${ROOT_SRC_DIR}/user_settings.h"
+        echo ""
+
         echo "Install:"
-        echo "cp ../../examples/configs/user_settings_arduino.h  .${ROOT_SRC_DIR}/user_settings.h"
-        cp ../../examples/configs/user_settings_arduino.h  ".${ROOT_SRC_DIR}/user_settings.h" || exit 1
+        echo "mv .$ROOT_DIR $ARDUINO_ROOT"
+        mv  ."$ROOT_DIR" "$ARDUINO_ROOT" || exit 1
 
-        echo "mv $ROOT_DIR $ARDUINO_ROOT"
-        mv ".$ROOT_DIR" "$ARDUINO_ROOT" || exit 1
+        echo "Arduino wolfSSL Version: $WOLFSSL_VERSION$WOLFSSL_VERSION_ARUINO_SUFFIX"
     fi
 fi
 

+ 39 - 0
IDE/ARDUINO/wolfssl.h

@@ -0,0 +1,39 @@
+/* wolfssl.h
+ *
+ * Copyright (C) 2006-2024 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* Edit with caution. This is an Arduino-library specific header for wolfSSL */
+
+#ifndef WOLFSSL_USER_SETTINGS
+    #define WOLFSSL_USER_SETTINGS
+#endif
+
+#include <Arduino.h>
+
+/* wolfSSL user_settings.h must be included from settings.h */
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/ssl.h>
+
+int wolfSSL_Arduino_Serial_Print(const char *const s)
+{
+    /* See wolfssl/wolfcrypt/logging.c */
+    Serial.println(F(s));
+    return 0;
+};

+ 63 - 11
examples/configs/user_settings_arduino.h

@@ -19,7 +19,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  */
 
-/* This is a sample Arduino user_settings.h for wolfSSL */
+/* This is a sample Arduino user_settings.h for wolfSSL
+  >> Edit with caution. This is the file copied to wolfSSL Arduino library.
+  >> at publish time. (lines with ">>" are removed)
+*/
+
+/* Define a macro to display user settings version in example code: */
+#define WOLFSSL_USER_SETTINGS_ID "Arduino user_settings.h v5.6.6 Rev 5"
 
 #define NO_FILESYSTEM
 #define USE_CERT_BUFFERS_2048
@@ -29,15 +35,26 @@
 
 #define HAVE_ECC
 #define WOLFSSL_SMALL_STACK
-/* #define WOLFSSL_SMALL_STACK_EXTRA */
-/* #define WOLFSSL_SMALL_STACK_CIPHERS */
-/* #define NO_DH */
+/* #define WOLFSSL_SMALL_STACK_EXTRA    */
+/* #define WOLFSSL_SMALL_STACK_CIPHERS  */
+/* #define NO_DH                        */
+#define MICRO_SESSION_CACHE
 
 /* RSA must be enabled for examples, but can be disabled like this: */
 /* #define NO_RSA */
 #define RSA_LOW_MEM
 
-/* #define NO_OLD_TLS */
+#define NO_OLD_TLS
+/* TLS 1.3                                 */
+/* #define WOLFSSL_TLS13 */
+#if defined(WOLFSSL_TLS13)
+    #define HAVE_TLS_EXTENSIONS
+    #define WC_RSA_PSS
+    #define HAVE_HKDF
+    #define HAVE_AEAD
+#endif
+
+/*  #define HAVE_SUPPORTED_CURVES  */
 
 /* Cannot use WOLFSSL_NO_MALLOC with small stack */
 /* #define WOLFSSL_NO_MALLOC */
@@ -45,6 +62,35 @@
 #define HAVE_TLS_EXTENSIONS
 #define HAVE_SUPPORTED_CURVES
 
+/* To further reduce size, client or server functionality can be disabled.
+ * Here, we check if the example code gave us a hint.
+ *
+ * The calling application can define either one of these macros before
+ * including the Arduino wolfssl.h library file:
+ *
+ *    WOLFSSL_CLIENT_EXAMPLE
+ *    WOLFSSL_SERVER_EXAMPLE
+ */
+#if defined(WOLFSSL_CLIENT_EXAMPLE)
+    #define NO_WOLFSSL_SERVER
+#elif defined(WOLFSSL_SERVER_EXAMPLE)
+    #define NO_WOLFSSL_CLIENT
+#else
+    /* Provide a hint to application that neither WOLFSSL_CLIENT_EXAMPLE
+     * or WOLFSSL_SERVER_EXAMPLE macro hint was desired but not found. */
+    #define NO_WOLFSSL_SERVER_CLIENT_MISSING
+    #warning "Define WOLFSSL_CLIENT_EXAMPLE or WOLFSSL_SERVER_EXAMPLE to" \
+             " optimize memory for small embedded devices."
+    /* Both can be disabled in wolfssl test & benchmark */
+#endif
+
+
+#define NO_DH
+#define NO_DSA
+#define USE_FAST_MATH
+#define WOLFSSL_SMALL_STACK
+#define SINGLE_THREADED
+#define WOLFSSL_LOW_MEMORY
 #define HAVE_AESGCM
 
 /* optionally turn off SHA512/224 SHA512/256 */
@@ -241,13 +287,14 @@
     #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI
     /***** END CONFIG_IDF_TARGET_ESP266 *****/
 #else
-    /* Anything else encountered, disable HW accleration */
+    /* Anything else encountered, disable HW acceleration */
     #define NO_ESP32_CRYPT
     #define NO_WOLFSSL_ESP32_CRYPT_HASH
     #define NO_WOLFSSL_ESP32_CRYPT_AES
     #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI
 #endif /* CONFIG_IDF_TARGET Check */
 
+#define DEBUG_WOLFSSL
 /* Debug options:
 
 #define ESP_VERIFY_MEMBLOCK
@@ -266,10 +313,10 @@
 
 #define WOLFSSL_ESPIDF_ERROR_PAUSE /* Pause in a loop rather than exit. */
 #define WOLFSSL_HW_METRICS
-
+#define ALT_ECC_SIZE
 /* #define HASH_SIZE_LIMIT */ /* for test.c */
 
-/* #define NO_HW_MATH_TEST */ /* Optionall turn off HW math checks */
+/* #define NO_HW_MATH_TEST */ /* Optionally turn off HW math checks */
 
 /* Optionally include alternate HW test library: alt_hw_test.h */
 /* When enabling, the ./components/wolfssl/CMakeLists.txt file
@@ -301,6 +348,7 @@
 #define ATCA_WOLFSSL
 */
 
+/* optional SM4 Ciphers. See https://github.com/wolfSSL/wolfsm
 /* The section below defines macros used in typically all of the wolfSSL
  * examples such as the client and server for certs stored in header files.
  *
@@ -384,6 +432,9 @@
     #define WOLFSSL_BASE16
 #else
     #if defined(USE_CERT_BUFFERS_2048)
+        #ifdef USE_CERT_BUFFERS_1024
+            #error "USE_CERT_BUFFERS_1024 is already defined. Pick one."
+        #endif
         #include <wolfssl/certs_test.h>
         #define CTX_CA_CERT          ca_cert_der_2048
         #define CTX_CA_CERT_SIZE     sizeof_ca_cert_der_2048
@@ -402,8 +453,10 @@
         #define CTX_CLIENT_KEY       client_key_der_2048
         #define CTX_CLIENT_KEY_SIZE  sizeof_client_key_der_2048
         #define CTX_CLIENT_KEY_TYPE  WOLFSSL_FILETYPE_ASN1
-
     #elif defined(USE_CERT_BUFFERS_1024)
+        #ifdef USE_CERT_BUFFERS_2048
+            #error "USE_CERT_BUFFERS_2048 is already defined. Pick one."
+        #endif
         #include <wolfssl/certs_test.h>
         #define CTX_CA_CERT          ca_cert_der_1024
         #define CTX_CA_CERT_SIZE     sizeof_ca_cert_der_1024
@@ -423,7 +476,6 @@
         #define CTX_SERVER_KEY_SIZE  sizeof_server_key_der_1024
         #define CTX_SERVER_KEY_TYPE  WOLFSSL_FILETYPE_ASN1
     #else
-        /* Optionally define custom cert arrays, sizes, and types here */
         #error "Must define USE_CERT_BUFFERS_2048 or USE_CERT_BUFFERS_1024"
     #endif
-#endif /* Conditional key and cert constant names */
+#endif

+ 4 - 0
src/internal.c

@@ -5428,7 +5428,9 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
         keySz = ssl->eccTempKeySz;
         /* get curve type */
         if (ssl->ecdhCurveOID > 0) {
+            WOLFSSL_MSG("calling ecc_cuve"); /* TODO; review */
             ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL);
+            WOLFSSL_MSG("ecc_curve done");
         }
     #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) && \
         (defined(WOLFSSL_SM4_CBC) || defined(WOLFSSL_SM4_GCM) || \
@@ -5462,7 +5464,9 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer)
     else
 #endif
     {
+        WOLFSSL_MSG("make key"); /* TODO review */
         ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, ecc_curve);
+        WOLFSSL_MSG("make key done");
     }
 
     /* make sure the curve is set for TLS */

+ 9 - 0
src/tls13.c

@@ -136,6 +136,15 @@
     #define FALSE 0
 #endif
 
+#ifndef HAVE_AEAD
+    #ifndef _MSC_VER
+        #error "The build option HAVE_AEAD is required for TLS 1.3"
+    #else
+        #pragma \
+        message("error: The build option HAVE_AEAD is required for TLS 1.3")
+    #endif
+#endif
+
 #ifndef HAVE_HKDF
     #ifndef _MSC_VER
         #error "The build option HAVE_HKDF is required for TLS 1.3"

+ 51 - 22
wolfcrypt/src/ecc.c

@@ -1650,7 +1650,7 @@ static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve,
 #ifdef ECC_CACHE_CURVE
     int x;
 #endif
-
+    WOLFSSL_ENTER("wc_ecc_curve_load");
     if (dp == NULL || pCurve == NULL)
         return BAD_FUNC_ARG;
 
@@ -1751,6 +1751,8 @@ static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve,
     wc_UnLockMutex(&ecc_curve_cache_mutex);
 #endif
 
+    WOLFSSL_LEAVE("wc_ecc_curve_load", ret);
+
     return ret;
 }
 
@@ -2629,7 +2631,7 @@ int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct)
    int    err;
 
    (void)ct;
-
+   WOLFSSL_ENTER("ecc_map_ex");
    if (P == NULL || modulus == NULL)
        return ECC_BAD_ARG_E;
 
@@ -2658,6 +2660,7 @@ int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct)
 #endif /* WOLFSSL_SMALL_STACK_CACHE */
 #endif
    {
+      WOLFSSL_MSG("ecc new mp");
       NEW_MP_INT_SIZE(t1, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC);
       NEW_MP_INT_SIZE(t2, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC);
    #ifdef MP_INT_SIZE_CHECK_NULL
@@ -2683,7 +2686,7 @@ int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct)
    #endif
    #endif
    }
-
+   WOLFSSL_MSG("ecc init");
    err = INIT_MP_INT_SIZE(t1, mp_bitsused(modulus));
    if (err == MP_OKAY) {
       err = INIT_MP_INT_SIZE(t2, mp_bitsused(modulus));
@@ -2814,7 +2817,10 @@ done:
    }
 
    return err;
+   /* end !defined(WOLFSSL_SP_MATH) */
+
 #else
+   /* begin defined(WOLFSSL_SP_MATH) */
    if (P == NULL || modulus == NULL)
        return ECC_BAD_ARG_E;
 
@@ -2823,26 +2829,27 @@ done:
 
 #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SP_SM2)
    if ((mp_count_bits(modulus) == 256) && (!mp_is_bit_set(modulus, 224))) {
-       return sp_ecc_map_sm2_256(P->x, P->y, P->z);
+       err = sp_ecc_map_sm2_256(P->x, P->y, P->z);
    }
-#endif
-#ifndef WOLFSSL_SP_NO_256
+#elif defined(WOLFSSL_SP_NO_256)
    if (mp_count_bits(modulus) == 256) {
-       return sp_ecc_map_256(P->x, P->y, P->z);
+       err = sp_ecc_map_256(P->x, P->y, P->z);
    }
-#endif
-#ifdef WOLFSSL_SP_384
+#elif defined(WOLFSSL_SP_384)
    if (mp_count_bits(modulus) == 384) {
-       return sp_ecc_map_384(P->x, P->y, P->z);
+       err = sp_ecc_map_384(P->x, P->y, P->z);
    }
-#endif
-#ifdef WOLFSSL_SP_521
+#elif defined(WOLFSSL_SP_521)
    if (mp_count_bits(modulus) == 521) {
-       return sp_ecc_map_521(P->x, P->y, P->z);
+       err = sp_ecc_map_521(P->x, P->y, P->z);
    }
+#else
+   err = ECC_BAD_ARG_E;
 #endif
-   return ECC_BAD_ARG_E;
-#endif
+
+   WOLFSSL_LEAVE("ecc_map_ex (SP Math)");
+   return err;
+#endif /* WOLFSSL_SP_MATH */
 }
 #endif /* !FREESCALE_LTC_ECC && !WOLFSSL_STM32_PKA */
 
@@ -3831,7 +3838,7 @@ int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point* G, ecc_point* R, mp_int* a,
    ecc_key       key;
 #endif
    mp_digit      mp;
-
+   WOLFSSL_ENTER("wc_ecc_mulmod_ex2");
    if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
       return ECC_BAD_ARG_E;
    }
@@ -3993,6 +4000,7 @@ static int wc_ecc_new_point_ex(ecc_point** point, void* heap)
    int err = MP_OKAY;
    ecc_point* p;
 
+   WOLFSSL_ENTER("wc_ecc_new_point_ex");
    if (point == NULL) {
        return BAD_FUNC_ARG;
    }
@@ -4000,23 +4008,32 @@ static int wc_ecc_new_point_ex(ecc_point** point, void* heap)
    p = *point;
 #ifndef WOLFSSL_NO_MALLOC
    if (p == NULL) {
-      p = (ecc_point*)XMALLOC(sizeof(ecc_point), heap, DYNAMIC_TYPE_ECC);
+       WOLFSSL_MSG_EX("XMALLOC ecc_point %d bytes.", sizeof(ecc_point));
+       p = (ecc_point*)XMALLOC(sizeof(ecc_point), heap, DYNAMIC_TYPE_ECC);
+       WOLFSSL_MSG("XMALLOC ecc_point complete.");
+   }
+   else {
+       WOLFSSL_MSG("XMALLOC ecc_point skipped! (p == NULL)");
    }
 #endif
    if (p == NULL) {
+      WOLFSSL_MSG("failed to XMALLOC ecc_point");
       return MEMORY_E;
    }
    XMEMSET(p, 0, sizeof(ecc_point));
 
 #ifndef ALT_ECC_SIZE
+   WOLFSSL_MSG("mp_init_multi for ecc x,y,z (!ALT_ECC_SIZE)");
    err = mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL);
    if (err != MP_OKAY) {
+      WOLFSSL_MSG("mp_init_multi failed.");
    #ifndef WOLFSSL_NO_MALLOC
       XFREE(p, heap, DYNAMIC_TYPE_ECC);
    #endif
       return err;
    }
 #else
+   WOLFSSL_MSG("alt_fp_init ecc x,y,z (ALT_ECC_SIZE)");
    p->x = (mp_int*)&p->xyz[0];
    p->y = (mp_int*)&p->xyz[1];
    p->z = (mp_int*)&p->xyz[2];
@@ -4027,14 +4044,18 @@ static int wc_ecc_new_point_ex(ecc_point** point, void* heap)
 
    *point = p;
    (void)heap;
+   WOLFSSL_LEAVE("wc_ecc_new_point_ex", err);
+
    return err;
-}
+} /* wc_ecc_new_point_ex */
+
 ecc_point* wc_ecc_new_point_h(void* heap)
 {
     ecc_point* p = NULL;
     (void)wc_ecc_new_point_ex(&p, heap);
     return p;
 }
+
 ecc_point* wc_ecc_new_point(void)
 {
    ecc_point* p = NULL;
@@ -5171,6 +5192,7 @@ int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order)
 #ifndef WOLFSSL_ECC_GEN_REJECT_SAMPLING
     int err;
     byte buf[ECC_MAXSIZE_GEN];
+    WOLFSSL_ENTER("wc_ecc_gen_k");
 
     if (rng == NULL || size < 0 || size + 8 > ECC_MAXSIZE_GEN || k == NULL ||
                                                                 order == NULL) {
@@ -5256,6 +5278,7 @@ int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order)
     wc_MemZero_Check(buf, ECC_MAXSIZE_GEN);
 #endif
 
+    WOLFSSL_LEAVE("wc_ecc_gen_k", err);
     return err;
 #endif
 #else
@@ -5295,9 +5318,9 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve,
 #ifdef HAVE_ECC_MAKE_PUB
     ecc_point* pub;
 #endif /* HAVE_ECC_MAKE_PUB */
-
     (void)rng;
 
+    WOLFSSL_ENTER("ecc_make_pub_ex");
     if (key == NULL) {
         return BAD_FUNC_ARG;
     }
@@ -5394,6 +5417,7 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve,
         ecc_point  lcl_base;
         base = &lcl_base;
     #endif
+
         err = wc_ecc_new_point_ex(&base, key->heap);
 
         /* read in the x/y for this key */
@@ -5450,7 +5474,7 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve,
     }
 
     RESTORE_VECTOR_REGISTERS();
-
+    WOLFSSL_LEAVE("ecc_make_pub_ex", err);
     return err;
 }
 
@@ -5511,6 +5535,8 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key,
         int curve_id, int flags)
 {
     int err = 0;
+    WOLFSSL_ENTER("_ecc_make_key_ex");
+
 #if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) && \
     !defined(WOLFSSL_ATECC608A)
     const CRYS_ECPKI_Domain_t*  pDomain;
@@ -5809,7 +5835,6 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key,
         err = WC_KEY_SIZE_E;
 #else
         DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
-
         /* setup the key variables */
 #ifndef ALT_ECC_SIZE
         err = mp_init(key->k);
@@ -5821,6 +5846,7 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key,
 
         /* load curve info */
         if (err == MP_OKAY) {
+            WOLFSSL_MSG("load curve specs");
             ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err);
             if (err != MP_OKAY) {
                 WOLFSSL_MSG("ALLOC_CURVE_SPECS failed");
@@ -5828,6 +5854,7 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key,
         }
 
         if (err == MP_OKAY) {
+
             err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
             if (err != MP_OKAY) {
                 WOLFSSL_MSG("wc_ecc_curve_load failed");
@@ -5880,6 +5907,7 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key,
 #endif
 
 #endif /* HAVE_ECC_MAKE_PUB */
+    WOLFSSL_LEAVE("_ecc_make_key_ex", err);
 
     return err;
 #endif /* !WOLF_CRYPTO_CB_ONLY_ECC */
@@ -5890,9 +5918,9 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id,
                         int flags)
 {
     int err;
+    WOLFSSL_ENTER("wc_ecc_make_key_ex2");
 
     SAVE_VECTOR_REGISTERS(return _svr_ret;);
-
     err = _ecc_make_key_ex(rng, keysize, key, curve_id, flags);
 
 #if (FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN)) && \
@@ -5918,6 +5946,7 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id,
 WOLFSSL_ABI
 int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id)
 {
+    WOLFSSL_ENTER("wc_ecc_make_key_ex");
     return wc_ecc_make_key_ex2(rng, keysize, key, curve_id, WC_ECC_FLAG_NONE);
 }
 

+ 5 - 2
wolfcrypt/src/logging.c

@@ -234,7 +234,9 @@ void WOLFSSL_TIME(int count)
 
 #ifdef DEBUG_WOLFSSL
 
-#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
+#if defined(ARDUINO)
+    /* see Arduino wolfssl.h for wolfSSL_Arduino_Serial_Print */
+#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
     /* see wc_port.h for fio.h and nio.h includes */
 #elif defined(WOLFSSL_SGX)
     /* Declare sprintf for ocall */
@@ -281,9 +283,10 @@ static void wolfssl_log(const int logLevel, const char *const logMessage)
     else {
 #if defined(WOLFSSL_USER_LOG)
         WOLFSSL_USER_LOG(logMessage);
+#elif defined(ARDUINO)
+        wolfSSL_Arduino_Serial_Print(logMessage);
 #elif defined(WOLFSSL_LOG_PRINTF)
         printf("%s\n", logMessage);
-
 #elif defined(THREADX) && !defined(THREADX_NO_DC_PRINTF)
         dc_log_printf("%s\n", logMessage);
 #elif defined(WOLFSSL_DEOS)

+ 37 - 11
wolfcrypt/src/random.c

@@ -1648,7 +1648,14 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
         seedSz = MAX_SEED_SZ;
     }
 
-    if (wc_RNG_HealthTestLocal(0, rng->heap, devId) == 0) {
+    ret = wc_RNG_HealthTestLocal(0, rng->heap, devId);
+    if (ret != 0) {
+        #if defined(DEBUG_WOLFSSL)
+        WOLFSSL_MSG_EX("wc_RNG_HealthTestLocal failed err = %d", ret);
+        #endif
+        ret = DRBG_CONT_FAILURE;
+    }
+    else {
     #ifndef WOLFSSL_SMALL_STACK
         byte seed[MAX_SEED_SZ];
     #else
@@ -1720,10 +1727,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
     #ifdef WOLFSSL_SMALL_STACK
         XFREE(seed, rng->heap, DYNAMIC_TYPE_SEED);
     #endif
-    }
-    else {
-        ret = DRBG_CONT_FAILURE;
-    }
+    } /* else swc_RNG_HealthTestLocal was successful */
 
     if (ret == DRBG_SUCCESS) {
 #ifdef WOLFSSL_CHECK_MEM_ZERO
@@ -2226,16 +2230,32 @@ static int wc_RNG_HealthTestLocal(int reseed, void* heap, int devId)
 #else
         const byte* seedB = seedB_data;
         const byte* outputB = outputB_data;
+#endif
+#if defined(DEBUG_WOLFSSL)
+        WOLFSSL_MSG_EX("RNG_HEALTH_TEST_CHECK_SIZE = %d",
+                        RNG_HEALTH_TEST_CHECK_SIZE);
+        WOLFSSL_MSG_EX("sizeof(seedB_data)         = %d",
+                        (int)sizeof(outputB_data));
 #endif
         ret = wc_RNG_HealthTest_ex(0, NULL, 0,
                                    seedB, sizeof(seedB_data),
                                    NULL, 0,
                                    check, RNG_HEALTH_TEST_CHECK_SIZE,
                                    heap, devId);
-        if (ret == 0) {
-            if (ConstantCompare(check, outputB,
-                                RNG_HEALTH_TEST_CHECK_SIZE) != 0)
+        if (ret != 0) {
+            #if defined(DEBUG_WOLFSSL)
+            WOLFSSL_MSG_EX("RNG_HealthTest failed: err = %d", ret);
+            #endif
+        }
+        else {
+            ret = ConstantCompare(check, outputB,
+                                RNG_HEALTH_TEST_CHECK_SIZE);
+            if (ret != 0) {
+                #if defined(DEBUG_WOLFSSL)
+                WOLFSSL_MSG_EX("Random ConstantCompare failed: err = %d", ret);
+                #endif
                 ret = -1;
+            }
         }
 
         /* The previous test cases use a large seed instead of a seed and nonce.
@@ -3490,7 +3510,11 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
             if (sz < len)
                 len = sz;
         /* Get an Arduino framework random number */
-        #if defined(__arm__)
+        #if defined(ARDUINO_SAMD_NANO_33_IOT) || \
+            defined(ARDUINO_ARCH_RP2040)
+            /* Known, tested boards working with random() */
+            rand = random();
+        #elif defined(ARDUINO_SAM_DUE)
             /* See: https://github.com/avrxml/asf/tree/master/sam/utils/cmsis/sam3x/include */
             #if defined(__SAM3A4C__)
                 #ifndef TRNG
@@ -3534,10 +3558,12 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
             #warning "Not yet tested on STM32 targets"
             rand = random();
         #else
-            /* TODO: Pull requests appreciated for new targets */
-            #warning "Not yet tested on this target"
+            /* TODO: Pull requests appreciated for new targets.
+             * Do *all* other Arduino boards support random()?
+             * Probably not 100%, but most will likely work: */
             rand = random();
         #endif
+
             XMEMCPY(output, &rand, len);
             output += len;
             sz -= len;

+ 5 - 0
wolfssl/wolfcrypt/logging.h

@@ -89,6 +89,11 @@ enum wc_FuncNum {
 };
 #endif
 
+#if defined(ARDUINO)
+/* implemented in Arduino wolfssl.h */
+extern WOLFSSL_API int wolfSSL_Arduino_Serial_Print(const char* const s);
+#endif /* ARDUINO */
+
 typedef void (*wolfSSL_Logging_cb)(const int logLevel,
                                    const char *const logMessage);