diff --git a/.gitignore b/.gitignore index 7bd2affdb..5bd31033f 100644 --- a/.gitignore +++ b/.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 diff --git a/IDE/ARDUINO/Arduino_README_prepend.md b/IDE/ARDUINO/Arduino_README_prepend.md index 5c789f609..594a06784 100644 --- a/IDE/ARDUINO/Arduino_README_prepend.md +++ b/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. diff --git a/IDE/ARDUINO/README.md b/IDE/ARDUINO/README.md index 6ca29942b..30989d8c7 100644 --- a/IDE/ARDUINO/README.md +++ b/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/ diff --git a/IDE/ARDUINO/include.am b/IDE/ARDUINO/include.am index c0214e47c..4d027005e 100644 --- a/IDE/ARDUINO/include.am +++ b/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 diff --git a/IDE/ARDUINO/library.properties.template b/IDE/ARDUINO/library.properties.template index ae1b5a287..9b18e8c20 100644 --- a/IDE/ARDUINO/library.properties.template +++ b/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 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. diff --git a/IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino b/IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino index 61362ae98..514c7dc4f 100644 --- a/IDE/ARDUINO/sketches/wolfssl_client/wolfssl_client.ino +++ b/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 +#endif + #include +/* Important: make sure settings.h appears before any other wolfSSL headers */ +#include +/* Reminder: settings.h includes user_settings.h + * For ALL project wolfSSL settings, see: + * [your path]/Arduino\libraries\wolfSSL\src\user_settings.h */ #include -#include #include +#include +/* Define DEBUG_WOLFSSL in user_settings.h for more verbose logging. */ +#if defined(DEBUG_WOLFSSL) + #define PROGRESS_DOT F("") +#else + #define PROGRESS_DOT F(".") +#endif -const char host[] = "192.168.1.148"; /* server to connect to */ -const int port = 11111; /* port on server to connect to */ +/* 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); -int reconnect = 10; +/* optional board-specific networking includes */ +#if defined(ESP32) + #define USING_WIFI + #include + #include + #ifdef USE_NTP_LIB + WiFiUDP ntpUDP; + #endif + /* Ensure the F() flash macro is defined */ + #ifndef F + #define F + #endif + WiFiClient client; -EthernetClient client; +#elif defined(ESP8266) + #define USING_WIFI + #include + WiFiClient client; + +#elif defined(ARDUINO_SAM_DUE) + #include + /* There's no WiFi/Ethernet on the Due. Requires Ethernet Shield. + /* Needs "Ethernet by Various" library to be installed. Tested with V2.0.2 */ + #include + EthernetClient client; + +#elif defined(ARDUINO_SAMD_NANO_33_IOT) + #define USING_WIFI + #include + #include + WiFiClient client; + +#elif defined(ARDUINO_ARCH_RP2040) + #define USING_WIFI + #include + #include + WiFiClient client; + +#elif defined(USING_WIFI) + #define USING_WIFI + #include + #include + #ifdef USE_NTP_LIB + WiFiUDP ntpUDP; + #endif + WiFiClient client; + +/* TODO +#elif defined(OTHER_BOARD) +*/ +#else + #define USING_WIFI + WiFiClient client; + +#endif + +/* Only for syntax highlighters to show interesting options enabled: */ +#if defined(HAVE_SNI) \ + || defined(HAVE_MAX_FRAGMENT) \ + || defined(HAVE_TRUSTED_CA) \ + || defined(HAVE_TRUNCATED_HMAC) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \ + || defined(HAVE_SUPPORTED_CURVES) \ + || defined(HAVE_ALPN) \ + || defined(HAVE_SESSION_TICKET) \ + || defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) +#endif + +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]; -void setup() { - WOLFSSL_METHOD* method; - /* Initialize Return Code */ - int rc; - Serial.begin(9600); - /* Delay need to ensure connection to server */ - delay(4000); +#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 - method = wolfTLSv1_2_client_method(); - if (method == NULL) { - Serial.println("unable to get method"); - return; +static int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx); +static int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx); +static int reconnect = RECONNECT_ATTEMPTS; +static int lng_index PROGMEM = 0; /* 0 = English */ + +#if defined(__arm__) + #include + extern char _end; + extern "C" char *sbrk(int i); + 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); } - 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_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(""); - wolfSSL_SetIOSend(ctx, EthernetSend); - wolfSSL_SetIORecv(ctx, EthernetReceive); - return; + return 0; } -int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx) { +/*****************************************************************************/ +/* 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; - sent = client.write((byte*)msg, sz); + (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; } -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]; - const char* cipherName; - if (reconnect) { - reconnect--; - if (client.connect(host, port)) { - Serial.print("Connected to "); - Serial.println(host); - ssl = wolfSSL_new(ctx); - if (ssl == NULL) { - Serial.println("Unable to allocate SSL object"); - return; +/*****************************************************************************/ +/* 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; + + 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 */ } - 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 "); - Serial.println(wolfSSL_get_version(ssl)); - cipherName = wolfSSL_get_cipher(ssl); - Serial.print("SSL cipher suite is "); - Serial.println(cipherName); - if ((wolfSSL_write(ssl, msg, msgSz)) == msgSz) { - Serial.print("Server response: "); - /* wait for data */ - while (!client.available()) {} - /* 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); - } - else { - Serial.println(); - } - } - } - else { - 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."); - reconnect = 0; + } + if (Ethernet.linkStatus() == LinkOFF) { + Serial.println(F("Ethernet cable is not connected.")); + } + /* try to configure using IP address instead of DHCP : */ + Ethernet.begin(mac, ip, myDns); + } + else { + Serial.print(F(" DHCP assigned IP ")); + Serial.println(Ethernet.localIP()); + } + /* We'll assume the Ethernet connection is ready to go. */ +#endif + + Serial.println(F("********************************************************")); + Serial.print(F(" wolfSSL Example Client IP = ")); +#if defined(USING_WIFI) + Serial.println(WiFi.localIP()); +#else + Serial.println(Ethernet.localIP()); +#endif + Serial.print(F(" Configured Server Host to connect to: ")); + Serial.println(host); + Serial.println(F("********************************************************")); + Serial.println(F("Setup network complete.")); + + return ret; +} + +/*****************************************************************************/ +/* Arduino setup_wolfssl() */ +/*****************************************************************************/ +int setup_wolfssl(void) { + int ret = 0; + WOLFSSL_METHOD* method; + + /* Show a revision of wolfssl user_settings.h file in use when available: */ +#if defined(WOLFSSL_USER_SETTINGS_ID) + Serial.print(F("WOLFSSL_USER_SETTINGS_ID: ")); + Serial.println(F(WOLFSSL_USER_SETTINGS_ID)); +#else + Serial.println(F("No WOLFSSL_USER_SETTINGS_ID found.")); +#endif + +#if defined(NO_WOLFSSL_SERVER) + Serial.println(F("wolfSSL server code disabled to save space.")); +#endif +#if defined(NO_WOLFSSL_CLIENT) + Serial.println(F("wolfSSL client code disabled to save space.")); +#endif + +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); + Serial.println(F("wolfSSL Debugging is On!")); +#else + Serial.println(F("wolfSSL Debugging is Off! (enable with DEBUG_WOLFSSL)")); +#endif + + /* See ssl.c for TLS cache settings. Larger cache = use more RAM. */ +#if defined(NO_SESSION_CACHE) + Serial.println(F("wolfSSL TLS NO_SESSION_CACHE")); +#elif defined(MICRO_SESSION_CACHEx) + Serial.println(F("wolfSSL TLS MICRO_SESSION_CACHE")); +#elif defined(SMALL_SESSION_CACHE) + Serial.println(F("wolfSSL TLS SMALL_SESSION_CACHE")); +#elif defined(MEDIUM_SESSION_CACHE) + Serial.println(F("wolfSSL TLS MEDIUM_SESSION_CACHE")); +#elif defined(BIG_SESSION_CACHE) + Serial.println(F("wolfSSL TLS BIG_SESSION_CACHE")); +#elif defined(HUGE_SESSION_CACHE) + Serial.println(F("wolfSSL TLS HUGE_SESSION_CACHE")); +#elif defined(HUGE_SESSION_CACHE) + Serial.println(F("wolfSSL TLS HUGE_SESSION_CACHE")); +#else + Serial.println(F("WARNING: Unknown or no TLS session cache setting.")); + /* See wolfssl/src/ssl.c for amount of memory used. + * It is best on embedded devices to choose a TLS session cache size. */ +#endif + + ret = wolfSSL_Init(); + if (ret == WOLFSSL_SUCCESS) { + Serial.println("Successfully called wolfSSL_Init"); + } + else { + Serial.println("ERROR: wolfSSL_Init failed"); + } + + /* See companion server example with wolfSSLv23_server_method here. + * method = wolfSSLv23_client_method()); SSL 3.0 - TLS 1.3. + * method = wolfTLSv1_2_client_method(); only TLS 1.2 + * method = wolfTLSv1_3_client_method(); only TLS 1.3 + * + * see Arduino\libraries\wolfssl\src\user_settings.h */ + + Serial.println("Here we go!"); + + method = wolfSSLv23_client_method(); + if (method == NULL) { + Serial.println(F("unable to get wolfssl client method")); + fail_wait(); + } + ctx = wolfSSL_CTX_new(method); + if (ctx == NULL) { + Serial.println(F("unable to get ctx")); + fail_wait(); + } + + return ret; +} + +/*****************************************************************************/ +/* Arduino setup_certificates() */ +/*****************************************************************************/ +int setup_certificates(void) { + int ret = 0; + + Serial.println(F("Initializing certificates...")); + show_memory(); + + /* Use built-in validation, No verification callback function: */ + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); + + /* Certificate */ + Serial.println("Initializing certificates..."); + ret = wolfSSL_CTX_use_certificate_buffer(ctx, + CTX_CLIENT_CERT, + CTX_CLIENT_CERT_SIZE, + CTX_CLIENT_CERT_TYPE); + if (ret == WOLFSSL_SUCCESS) { + Serial.print("Success: use certificate: "); + Serial.println(xstr(CTX_SERVER_CERT)); + } + else { + Serial.println(F("Error: wolfSSL_CTX_use_certificate_buffer failed: ")); + wc_ErrorString(ret, wc_error_message); + Serial.println(wc_error_message); + fail_wait(); + } + + /* Setup private client key */ + ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, + CTX_CLIENT_KEY, + CTX_CLIENT_KEY_SIZE, + CTX_CLIENT_KEY_TYPE); + if (ret == WOLFSSL_SUCCESS) { + Serial.print("Success: use private key buffer: "); + Serial.println(xstr(CTX_SERVER_KEY)); + } + else { + Serial.println(F("Error: wolfSSL_CTX_use_PrivateKey_buffer failed: ")); + wc_ErrorString(ret, wc_error_message); + Serial.println(wc_error_message); + fail_wait(); + } + + ret = wolfSSL_CTX_load_verify_buffer(ctx, + CTX_CA_CERT, + CTX_CA_CERT_SIZE, + CTX_CA_CERT_TYPE); + if (ret == WOLFSSL_SUCCESS) { + Serial.println(F("Success: load_verify CTX_CA_CERT")); + } + else { + Serial.println(F("Error: wolfSSL_CTX_load_verify_buffer failed: ")); + wc_ErrorString(ret, wc_error_message); + Serial.println(wc_error_message); + fail_wait(); + } + + + + return ret; +} /* Arduino setup */ + +/*****************************************************************************/ +/*****************************************************************************/ +/* Arduino setup() */ +/*****************************************************************************/ +/*****************************************************************************/ +void setup(void) { + 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); + + Serial.println(F("Completed Arduino setup!")); + /* See companion wolfssl_server.ino code; server begins listening here + * https://github.com/wolfSSL/wolfssl/tree/master/IDE/ARDUINO/sketches/wolfssl_server + * Any other server will work. See also: + * https://github.com/wolfSSL/wolfssl/tree/master/examples/client + */ + /* See companion wolfssl_server.ino code */ + return; +} /* Arduino setup */ + +/*****************************************************************************/ +/* wolfSSL error_check() */ +/*****************************************************************************/ +int error_check(int this_ret, bool halt_on_error, + const __FlashStringHelper* message) { + int ret = 0; + if (this_ret == WOLFSSL_SUCCESS) { + Serial.print(F("Success: ")); + Serial.println(message); + } + else { + Serial.print(F("ERROR: return = ")); + Serial.print(this_ret); + Serial.print(F(": ")); + Serial.println(message); + Serial.println(wc_GetErrorString(this_ret)); + if (halt_on_error) { + fail_wait(); + } + } + show_memory(); + + return ret; +} /* error_check */ + +/*****************************************************************************/ +/* wolfSSL error_check_ssl */ +/* Parameters: */ +/* ssl is the current WOLFSSL object pointer */ +/* halt_on_error set to true to suspend operations for critical error */ +/* message is expected to be a memory-efficient F("") macro string */ +/*****************************************************************************/ +int error_check_ssl(WOLFSSL* ssl, int this_ret, bool halt_on_error, + const __FlashStringHelper* message) { + int err = 0; + + if (ssl == NULL) { + Serial.println(F("ssl is Null; Unable to allocate SSL object?")); +#ifndef DEBUG_WOLFSSL + Serial.println(F("Define DEBUG_WOLFSSL in user_settings.h for more.")); +#else + Serial.println(F("See wolfssl/wolfcrypt/error-crypt.h for codes.")); +#endif + Serial.print(F("ERROR: ")); + Serial.println(message); + show_memory(); + if (halt_on_error) { + fail_wait(); + } + } + else { + err = wolfSSL_get_error(ssl, this_ret); + if (err == WOLFSSL_SUCCESS) { + Serial.print(F("Success m: ")); + Serial.println(message); } else { - Serial.println("Trying to reconnect..."); + if (err < 0) { + wolfSSL_ERR_error_string(err, errBuf); + Serial.print(F("WOLFSSL Error: ")); + Serial.print(err); + Serial.print(F("; ")); + Serial.println(errBuf); + } + else { + Serial.println(F("Success: ssl object.")); + } + } + } + + return err; +} + +/*****************************************************************************/ +/*****************************************************************************/ +/* Arduino loop() */ +/*****************************************************************************/ +/*****************************************************************************/ +void loop() { + char reply[80]; + char msg[32] = "hello wolfssl!"; + const char* cipherName; + int retry_shutdown = SHUTDOWN_DELAY_MS; /* max try, once per millisecond */ + int total_input = 0; + int msgSz = 0; + int input = 0; + int ret = 0; + int err = 0; + msgSz = (int)strlen(msg); + Serial.println(F("")); + Serial.println(F("Starting Arduino loop() ...")); + + if (reconnect) { + reconnect--; + /* WiFi client returns true if connection succeeds, false if not. */ + /* Wired client returns int (1,-1,-2,-3,-4) for connection status. */ + Serial.print(F("Connecting to ")); + Serial.print(host); + Serial.print(F(":")); + Serial.println(port); + /* can also use: IPAddress server(192,168,1,37); */ + Serial.println(F("Here we go...")); + ret = client.connect(host, port); + Serial.println(F("Ok, checking...")); + if (ret > 0) { + Serial.println(F("Connected!")); + + /* initialize wolfSSL */ + ret = wolfSSL_Init(); + error_check(ret, false, F("calling wolfSSL_Init") ); + + /* create secure connection object. see setup for ctx certs. */ + Serial.println(F("Calling ssl = wolfSSL_new(ctx)")); + ssl = wolfSSL_new(ctx); + error_check_ssl(ssl, 0, true, F("Create WOLFSSL object from ctx")); + + Serial.print(F("Connecting to wolfSSL TLS Secure Server...")); + do { + err = 0; /* reset error */ + Serial.println(F("wolfSSL_connect ...")); + ret = wolfSSL_connect(ssl); + Serial.print("wolfSSL_connect return result ="); + Serial.println(ret); + if ((ret != WOLFSSL_SUCCESS) && (ret != WC_PENDING_E)) { + Serial.println(F("Failed connection, checking error.")); + err = error_check_ssl(ssl, ret, true, + F("Create WOLFSSL object from ctx")); + Serial.print("err ="); + Serial.println(err); + } + else { + Serial.print(PROGRESS_DOT); + } + } while (err == WC_PENDING_E); + + Serial.println(); + Serial.println(F("Connected!")); + Serial.print(F("SSL version is ")); + Serial.println(wolfSSL_get_version(ssl)); + + cipherName = wolfSSL_get_cipher(ssl); + Serial.print(F("SSL cipher suite is ")); + Serial.println(cipherName); + + /* see test.h + * TODO: test.h needs a little bit of Arduino work for these: + showPeerEx(ssl, lng_index); + showPeerPEM(ssl); + */ + + Serial.print(F("Sending secure message to server: ")); + Serial.println(msg); + ret = wolfSSL_write(ssl, msg, msgSz); + if (ret == msgSz) { + Serial.print(F("Waiting for Server response...")); + + while (!client.available()) { + /* wait for data */ + delay(1); /* 1 ms delay */ + } + + Serial.print(F("Reading response..")); + /* read data */ + do { + ret = wolfSSL_read(ssl, reply, sizeof(reply) - 1); + if (ret < 0) { + error_check_ssl(ssl, ret, false, + F("during TLS Read")); + } + else { + Serial.print(PROGRESS_DOT); + } + } while (err == WC_PENDING_E); + Serial.println(); + + Serial.println(); + Serial.println(reply); /* typically: I hear you fa shizzle! */ + Serial.println(); + + } /* wolfSSL_write message size matched */ + else { + error_check_ssl(ssl, ret, false, + F("during TLS Write")); + } /* any wolfSSL_write message size mismatch is an error */ + + Serial.print(F("Shutting down..")); + do { + delay(1); + Serial.print(PROGRESS_DOT); + retry_shutdown--; + ret = wolfSSL_shutdown(ssl); + } while ( (ret == WOLFSSL_SHUTDOWN_NOT_DONE) + && (retry_shutdown > 0) + ); /* There may be pending data, so wait until done. */ + Serial.println(); + + if (retry_shutdown <= 0) { + /* if wolfSSL_free is called before properly shutting down the + * ssl object, undesired results may occur. */ + Serial.println(F("Warning! Shutdown did not properly complete.")); + } + + wolfSSL_free(ssl); + client.stop(); + Serial.println(F("Connection complete.")); + if (REPEAT_CONNECTION) { + reconnect = RECONNECT_ATTEMPTS; + } + else { + reconnect = 0; + } + } /* client.connect(host, port) */ + else { + Serial.println(F("Problem sending message. Trying to reconnect...")); } } delay(1000); -} + if ((reconnect > 0) && (REPEAT_CONNECTION)) { + Serial.println(F("Arduino loop repeating...")); + Serial.println(); + } + else { + printf("wow"); + Serial.println(F("Done!")); + while(1) { + /* wait forever */ + } + } + +#if defined(MEMORY_STRESS_TEST) + if (mem_ctr < MEMORY_STRESS_ITERATIONS) { + /* reminder: mem_ctr == 0 is MEMORY_STRESS_INITIAL allocation */ + mem_ctr++; + Serial.print(F("Memory stress increment: ")); + Serial.print(mem_ctr); + Serial.print(F(". Allocating addition memory (bytes): ")); + Serial.println(MEMORY_STRESS_BLOCK_SIZE); + memory_stress[mem_ctr] = (char*)malloc(MEMORY_STRESS_BLOCK_SIZE); + show_memory(); + } +#endif +} /* Arduino loop repeats */ diff --git a/IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino b/IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino index f331e7810..747136235 100644 --- a/IDE/ARDUINO/sketches/wolfssl_server/wolfssl_server.ino +++ b/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: -#include -#include -#include +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 -#define USE_CERT_BUFFERS_256 -#include +2) Espressif ESP32 WiFi -#ifdef NO_WOLFSSL_SERVER - #error Please undefine NO_WOLFSSL_SERVER for this example +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 -const int port = 11111; /* port to listen on */ +#define BROADCAST_ADDRESS "255.255.255.255" -int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx); -int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx); +/* There's an optional 3rd party NTPClient library by Fabrice Weinberg. + * If it is installed, uncomment define USE_NTP_LIB here: */ +/* #define USE_NTP_LIB */ +#ifdef USE_NTP_LIB + #include +#endif -EthernetServer server(port); -EthernetClient client; +#include +/* Important: make sure settings.h appears before any other wolfSSL headers */ +#include +/* Reminder: settings.h includes user_settings.h + * For ALL project wolfSSL settings, see: + * [your path]/Arduino\libraries\wolfSSL\src\user_settings.h */ +#include +#include +#include + +/* Define DEBUG_WOLFSSL in user_settings.h for more verbose logging. */ +#if defined(DEBUG_WOLFSSL) + #define PROGRESS_DOT F("") +#else + #define PROGRESS_DOT F(".") +#endif + +/* Convert a macro to a string */ +#define xstr(x) str(x) +#define str(x) #x + +/* optional board-specific networking includes */ +#if defined(ESP32) + #define USING_WIFI + #include + #include + #ifdef USE_NTP_LIB + WiFiUDP ntpUDP; + #endif + /* Ensure the F() flash macro is defined */ + #ifndef F + #define F + #endif + WiFiClient client; + WiFiServer server(WOLFSSL_PORT); +#elif defined(ESP8266) + #define USING_WIFI + #include + WiFiClient client; + WiFiServer server(WOLFSSL_PORT); +#elif defined(ARDUINO_SAM_DUE) + #include + /* There's no WiFi/Ethernet on the Due. Requires Ethernet Shield. + /* Needs "Ethernet by Various" library to be installed. Tested with V2.0.2 */ + #include + EthernetClient client; + EthernetClient server(WOLFSSL_PORT); +#elif defined(ARDUINO_SAMD_NANO_33_IOT) + #define USING_WIFI + #include + #include + WiFiClient client; + WiFiServer server(WOLFSSL_PORT); +#elif defined(ARDUINO_ARCH_RP2040) + #define USING_WIFI + #include + #include + WiFiClient client; + WiFiServer server(WOLFSSL_PORT); +#elif defined(USING_WIFI) + #define USING_WIFI + #include + #include + #ifdef USE_NTP_LIB + WiFiUDP ntpUDP; + #endif + WiFiClient client; + WiFiServer server(WOLFSSL_PORT); +/* TODO +#elif defined(OTHER_BOARD) +*/ +#else + #define USING_WIFI + WiFiClient client; + WiFiServer server(WOLFSSL_PORT); +#endif + +/* Only for syntax highlighters to show interesting options enabled: */ +#if defined(HAVE_SNI) \ + || defined(HAVE_MAX_FRAGMENT) \ + || defined(HAVE_TRUSTED_CA) \ + || defined(HAVE_TRUNCATED_HMAC) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \ + || defined(HAVE_SUPPORTED_CURVES) \ + || defined(HAVE_ALPN) \ + || defined(HAVE_SESSION_TICKET) \ + || defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) +#endif + + +/* we expect our IP address from DHCP */ +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; - } +#if defined(__arm__) + #include + extern char _end; + extern "C" char *sbrk(int i); + char *ramstart=(char *)0x20070000; + char *ramend=(char *)0x20088000; +#endif - /* initialize wolfSSL using callback functions */ - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); - wolfSSL_SetIOSend(ctx, EthernetSend); - wolfSSL_SetIORecv(ctx, EthernetReceive); +/*****************************************************************************/ +/* fail_wait - in case of unrecoverable error */ +/*****************************************************************************/ +int fail_wait(void) { + show_memory(); - /* 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; - } - - /* Start the server */ - server.begin(); - - return; + 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(); - } - - return ret; + while (client.available() > 0 && ret < sz) { + reply[ret++] = client.read(); + } + return ret; } -void loop() { - int err = 0; - int input = 0; - char errBuf[80]; - char reply[80]; - int replySz = 0; - const char* cipherName; +/*****************************************************************************/ +/* Arduino setup_hardware() */ +/*****************************************************************************/ +int setup_hardware(void) { + int ret = 0; - /* Listen for incoming client requests. */ - client = server.available(); - if (!client) { +#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; + + 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; + 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.")); + } + } } - 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"); + return err; } + +/*****************************************************************************/ +/*****************************************************************************/ +/* Arduino loop() */ +/*****************************************************************************/ +/*****************************************************************************/ +void loop() { + char errBuf[80] = "(no error"; + char reply[80] = "(no reply)"; + const char msg[] = "I hear you fa shizzle!"; + const char* cipherName; + int input = 0; + int replySz = 0; + int retry_shutdown = SHUTDOWN_DELAY_MS; /* max try, once per millisecond */ + int ret = 0; + IPAddress broadcast_address(255, 255, 255, 255); + + /* Listen for incoming client requests. */ + client = server.available(); + if (client) { + Serial.println("Have Client"); + while (!client.connected()) { + /* wait for the client to actually connect */ + delay(10); + } + Serial.print("Client connected from remote IP: "); + Serial.println(client.remoteIP()); + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + Serial.println("Unable to allocate SSL object"); + fail_wait(); + } + + ret = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + ret = wolfSSL_get_error(ssl, 0); + wolfSSL_ERR_error_string(ret, errBuf); + Serial.print("TLS Accept Error: "); + Serial.println(errBuf); + } + + cipherName = wolfSSL_get_cipher(ssl); + Serial.print("SSL cipher suite is "); + Serial.println(cipherName); + + Serial.print("Server Read: "); + while (!client.available()) { + /* wait for data */ + } + + /* read data */ + while (wolfSSL_pending(ssl)) { + input = wolfSSL_read(ssl, reply, sizeof(reply) - 1); + if (input < 0) { + ret = wolfSSL_get_error(ssl, 0); + wolfSSL_ERR_error_string(ret, errBuf); + Serial.print("TLS Read Error: "); + Serial.println(errBuf); + break; + } + else if (input > 0) { + replySz = input; + reply[input] = '\0'; + Serial.print(reply); + } + else { + Serial.println(""); + } + } + + /* Write our message into reply buffer to send */ + memset(reply, 0, sizeof(reply)); + memcpy(reply, msg, sizeof(msg)); + replySz = strnlen(reply, sizeof(reply)); + + Serial.println("Sending reply..."); + if ((wolfSSL_write(ssl, reply, replySz)) != replySz) { + ret = wolfSSL_get_error(ssl, 0); + wolfSSL_ERR_error_string(ret, errBuf); + Serial.print("TLS Write Error: "); + Serial.println(errBuf); + } + else { + Serial.println("Reply sent!"); + } + + Serial.println("Shutdown!"); + do { + delay(1); + retry_shutdown--; + ret = wolfSSL_shutdown(ssl); + } while ((ret == WOLFSSL_SHUTDOWN_NOT_DONE) && (retry_shutdown > 0)); + + if (retry_shutdown <= 0) { + /* if wolfSSL_free is called before properly shutting down the + * ssl object, undesired results may occur. */ + Serial.println("Warning! Shutdown did not properly complete."); + } + + wolfSSL_free(ssl); + Serial.println("Connection complete."); + if (REPEAT_CONNECTION) { + Serial.println(); + Serial.println("Waiting for next connection."); + } + else { + client.stop(); + Serial.println("Done!"); + while (1) { + /* wait forever if not repeating */ + delay(100); + } + } + } + else { + /* Serial.println("Client not connected. Trying again..."); */ + } + + delay(100); +} /* Arduino loop repeats */ diff --git a/IDE/ARDUINO/wolfssl-arduino.sh b/IDE/ARDUINO/wolfssl-arduino.sh index 555a4e3b1..bf439b86b 100755 --- a/IDE/ARDUINO/wolfssl-arduino.sh +++ b/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 - cat > .${ROOT_SRC_DIR}/wolfssl.h < -#include -#include -EOF + echo "Copy examples...." + # Copy examples + mkdir -p ".${ROOT_SRC_DIR}"/examples + + 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 "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 "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 - echo "mv $ROOT_DIR $ARDUINO_ROOT" - mv ".$ROOT_DIR" "$ARDUINO_ROOT" || exit 1 + # Show the user_settings.h revision string: + grep "WOLFSSL_USER_SETTINGS_ID" ."${ROOT_SRC_DIR}/user_settings.h" + echo "" + + echo "Install:" + 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 diff --git a/IDE/ARDUINO/wolfssl.h b/IDE/ARDUINO/wolfssl.h new file mode 100644 index 000000000..46ef50d3e --- /dev/null +++ b/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 + +/* wolfSSL user_settings.h must be included from settings.h */ +#include +#include + +int wolfSSL_Arduino_Serial_Print(const char *const s) +{ + /* See wolfssl/wolfcrypt/logging.c */ + Serial.println(F(s)); + return 0; +}; diff --git a/examples/configs/user_settings_arduino.h b/examples/configs/user_settings_arduino.h index a9486a82e..b5bb8f3d5 100644 --- a/examples/configs/user_settings_arduino.h +++ b/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 #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 #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 diff --git a/src/internal.c b/src/internal.c index 157e44749..552cf105b 100644 --- a/src/internal.c +++ b/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 */ diff --git a/src/tls13.c b/src/tls13.c index cb27926d0..8088d58ae 100644 --- a/src/tls13.c +++ b/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" diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 2b7b01080..598e77d06 100644 --- a/wolfcrypt/src/ecc.c +++ b/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); } diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index a84645427..43c44a1e7 100644 --- a/wolfcrypt/src/logging.c +++ b/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) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index f310b01b3..d44f2e2d2 100644 --- a/wolfcrypt/src/random.c +++ b/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; diff --git a/wolfssl/wolfcrypt/logging.h b/wolfssl/wolfcrypt/logging.h index 498b605e5..4eee1fa68 100644 --- a/wolfssl/wolfcrypt/logging.h +++ b/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);