123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894 |
- /* wolfssl_client.ino
- *
- * 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
- */
- /*
- Tested with:
- 1) Intel Galileo acting as the Client, with a laptop acting as a server using
- the server example provided in examples/server.
- Legacy Arduino v1.86 was used to compile and program the Galileo
- 2) Espressif ESP32 WiFi
- 3) Arduino Due, Nano33 IoT, Nano RP-2040
- */
- /*
- * Note to code editors: the Arduino client and server examples are edited in
- * parallel for side-by-side comparison between examples.
- */
- /* If you have a private include, define it here, otherwise edit WiFi params */
- #define MY_PRIVATE_CONFIG "/workspace/my_private_config.h"
- /* set REPEAT_CONNECTION to a non-zero value to continually run the example. */
- #define REPEAT_CONNECTION 0
- /* Edit this with your other TLS host server address to connect to: */
- #define WOLFSSL_TLS_SERVER_HOST "192.168.1.39"
- /* wolfssl TLS examples communicate on port 11111 */
- #define WOLFSSL_PORT 11111
- /* Choose a monitor serial baud rate: 9600, 14400, 19200, 57600, 74880, etc. */
- #define SERIAL_BAUD 115200
- /* We'll wait up to 2000 milliseconds to properly shut down connection */
- #define SHUTDOWN_DELAY_MS 2000
- /* Number of times to retry connection. */
- #define RECONNECT_ATTEMPTS 20
- /* Optional stress test. Define to consume memory until exhausted: */
- /* #define MEMORY_STRESS_TEST */
- /* Choose client or server example, not both. */
- #define WOLFSSL_CLIENT_EXAMPLE
- /* #define WOLFSSL_SERVER_EXAMPLE */
- #if defined(MY_PRIVATE_CONFIG)
- /* the /workspace directory may contain a private config
- * excluded from GitHub with items such as WiFi passwords */
- #include MY_PRIVATE_CONFIG
- static const char* ssid PROGMEM = MY_ARDUINO_WIFI_SSID;
- static const char* password PROGMEM = MY_ARDUINO_WIFI_PASSWORD;
- #else
- /* when using WiFi capable boards: */
- static const char* ssid PROGMEM = "your_SSID";
- static const char* password PROGMEM = "your_PASSWORD";
- #endif
- #define BROADCAST_ADDRESS "255.255.255.255"
- /* There's an optional 3rd party NTPClient library by Fabrice Weinberg.
- * If it is installed, uncomment define USE_NTP_LIB here: */
- /* #define USE_NTP_LIB */
- #ifdef USE_NTP_LIB
- #include <NTPClient.h>
- #endif
- #include <wolfssl.h>
- /* Important: make sure settings.h appears before any other wolfSSL headers */
- #include <wolfssl/wolfcrypt/settings.h>
- /* Reminder: settings.h includes user_settings.h
- * For ALL project wolfSSL settings, see:
- * [your path]/Arduino\libraries\wolfSSL\src\user_settings.h */
- #include <wolfssl/ssl.h>
- #include <wolfssl/certs_test.h>
- #include <wolfssl/wolfcrypt/error-crypt.h>
- /* Define DEBUG_WOLFSSL in user_settings.h for more verbose logging. */
- #if defined(DEBUG_WOLFSSL)
- #define PROGRESS_DOT F("")
- #else
- #define PROGRESS_DOT F(".")
- #endif
- /* Convert a macro to a string */
- #define xstr(x) str(x)
- #define str(x) #x
- /* optional board-specific networking includes */
- #if defined(ESP32)
- #define USING_WIFI
- #include <WiFi.h>
- #include <WiFiUdp.h>
- #ifdef USE_NTP_LIB
- WiFiUDP ntpUDP;
- #endif
- /* Ensure the F() flash macro is defined */
- #ifndef F
- #define F
- #endif
- WiFiClient client;
- #elif defined(ESP8266)
- #define USING_WIFI
- #include <ESP8266WiFi.h>
- WiFiClient client;
- #elif defined(ARDUINO_SAM_DUE)
- #include <SPI.h>
- /* There's no WiFi/Ethernet on the Due. Requires Ethernet Shield.
- /* Needs "Ethernet by Various" library to be installed. Tested with V2.0.2 */
- #include <Ethernet.h>
- EthernetClient client;
- #elif defined(ARDUINO_SAMD_NANO_33_IOT)
- #define USING_WIFI
- #include <SPI.h>
- #include <WiFiNINA.h> /* Needs Arduino WiFiNINA library installed manually */
- WiFiClient client;
- #elif defined(ARDUINO_ARCH_RP2040)
- #define USING_WIFI
- #include <SPI.h>
- #include <WiFiNINA.h>
- WiFiClient client;
- #elif defined(USING_WIFI)
- #define USING_WIFI
- #include <WiFi.h>
- #include <WiFiUdp.h>
- #ifdef USE_NTP_LIB
- WiFiUDP ntpUDP;
- #endif
- WiFiClient client;
- /* TODO
- #elif defined(OTHER_BOARD)
- */
- #else
- #define USING_WIFI
- WiFiClient client;
- #endif
- /* Only for syntax highlighters to show interesting options enabled: */
- #if defined(HAVE_SNI) \
- || defined(HAVE_MAX_FRAGMENT) \
- || defined(HAVE_TRUSTED_CA) \
- || defined(HAVE_TRUNCATED_HMAC) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \
- || defined(HAVE_SUPPORTED_CURVES) \
- || defined(HAVE_ALPN) \
- || defined(HAVE_SESSION_TICKET) \
- || defined(HAVE_SECURE_RENEGOTIATION) \
- || defined(HAVE_SERVER_RENEGOTIATION_INFO)
- #endif
- static const char host[] PROGMEM = WOLFSSL_TLS_SERVER_HOST; /* server to connect to */
- static const int port PROGMEM = WOLFSSL_PORT; /* port on server to connect to */
- static WOLFSSL_CTX* ctx = NULL;
- static WOLFSSL* ssl = NULL;
- static char* wc_error_message = (char*)malloc(80 + 1);
- static char errBuf[80];
- #if defined(MEMORY_STRESS_TEST)
- #define MEMORY_STRESS_ITERATIONS 100
- #define MEMORY_STRESS_BLOCK_SIZE 1024
- #define MEMORY_STRESS_INITIAL (4*1024)
- static char* memory_stress[MEMORY_STRESS_ITERATIONS]; /* typically 1K per item */
- static int mem_ctr = 0;
- #endif
- static int EthernetSend(WOLFSSL* ssl, char* msg, int sz, void* ctx);
- static int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx);
- static int reconnect = RECONNECT_ATTEMPTS;
- static int lng_index PROGMEM = 0; /* 0 = English */
- #if defined(__arm__)
- #include <malloc.h>
- extern char _end;
- extern "C" char *sbrk(int i);
- static char *ramstart=(char *)0x20070000;
- static char *ramend=(char *)0x20088000;
- #endif
- /*****************************************************************************/
- /* fail_wait - in case of unrecoverable error */
- /*****************************************************************************/
- int fail_wait(void) {
- show_memory();
- Serial.println(F("Failed. Halt."));
- while (1) {
- delay(1000);
- }
- return 0;
- }
- /*****************************************************************************/
- /* show_memory() to optionally view during debugging. */
- /*****************************************************************************/
- int show_memory(void)
- {
- #if defined(__arm__)
- struct mallinfo mi = mallinfo();
- char *heapend=sbrk(0);
- register char * stack_ptr asm("sp");
- #if defined(DEBUG_WOLFSSL_VERBOSE)
- Serial.print(" arena=");
- Serial.println(mi.arena);
- Serial.print(" ordblks=");
- Serial.println(mi.ordblks);
- Serial.print(" uordblks=");
- Serial.println(mi.uordblks);
- Serial.print(" fordblks=");
- Serial.println(mi.fordblks);
- Serial.print(" keepcost=");
- Serial.println(mi.keepcost);
- #endif
- #if defined(DEBUG_WOLFSSL) || defined(MEMORY_STRESS_TEST)
- Serial.print("Estimated free memory: ");
- Serial.print(stack_ptr - heapend + mi.fordblks);
- Serial.println(F(" bytes"));
- #endif
- #if (0)
- /* Experimental: not supported on all devices: */
- Serial.print("RAM Start %lx\n", (unsigned long)ramstart);
- Serial.print("Data/Bss end %lx\n", (unsigned long)&_end);
- Serial.print("Heap End %lx\n", (unsigned long)heapend);
- Serial.print("Stack Ptr %lx\n",(unsigned long)stack_ptr);
- Serial.print("RAM End %lx\n", (unsigned long)ramend);
- Serial.print("Heap RAM Used: ",mi.uordblks);
- Serial.print("Program RAM Used ",&_end - ramstart);
- Serial.print("Stack RAM Used ",ramend - stack_ptr);
- Serial.print("Estimated Free RAM: %d\n\n",stack_ptr - heapend + mi.fordblks);
- #endif
- #else
- Serial.println(F("show_memory() not implemented for this platform"));
- #endif
- return 0;
- }
- /*****************************************************************************/
- /* EthernetSend() to send a message string. */
- /*****************************************************************************/
- int EthernetSend(WOLFSSL* ssl, char* message, int sz, void* ctx) {
- int sent = 0;
- (void)ssl;
- (void)ctx;
- sent = client.write((byte*)message, sz);
- return sent;
- }
- /*****************************************************************************/
- /* EthernetReceive() to receive a reply string. */
- /*****************************************************************************/
- int EthernetReceive(WOLFSSL* ssl, char* reply, int sz, void* ctx) {
- int ret = 0;
- (void)ssl;
- (void)ctx;
- while (client.available() > 0 && ret < sz) {
- reply[ret++] = client.read();
- }
- return ret;
- }
- /*****************************************************************************/
- /* Arduino setup_hardware() */
- /*****************************************************************************/
- int setup_hardware(void) {
- int ret = 0;
- #if defined(ARDUINO_SAMD_NANO_33_IOT)
- Serial.println(F("Detected known tested and working Arduino Nano 33 IoT"));
- #elif defined(ARDUINO_ARCH_RP2040)
- Serial.println(F("Detected known tested and working Arduino RP-2040"));
- #elif defined(__arm__) && defined(ID_TRNG) && defined(TRNG)
- /* need to manually turn on random number generator on Arduino Due, etc. */
- pmc_enable_periph_clk(ID_TRNG);
- trng_enable(TRNG);
- Serial.println(F("Enabled ARM TRNG"));
- #endif
- show_memory();
- randomSeed(analogRead(0));
- return ret;
- }
- /*****************************************************************************/
- /* Arduino setup_datetime() */
- /* The device needs to have a valid date within the valid range of certs. */
- /*****************************************************************************/
- int setup_datetime(void) {
- int ret = 0;
- int ntp_tries = 20;
- /* we need a date in the range of cert expiration */
- #ifdef USE_NTP_LIB
- #if defined(ESP32)
- NTPClient timeClient(ntpUDP, "pool.ntp.org");
- timeClient.begin();
- timeClient.update();
- delay(1000);
- while (!timeClient.isTimeSet() && (ntp_tries > 0)) {
- timeClient.forceUpdate();
- Serial.println(F("Waiting for NTP update"));
- delay(2000);
- ntp_tries--;
- }
- if (ntp_tries <= 0) {
- Serial.println(F("Warning: gave up waiting on NTP"));
- }
- Serial.println(timeClient.getFormattedTime());
- Serial.println(timeClient.getEpochTime());
- #endif
- #endif
- #if defined(ESP32)
- /* see esp32-hal-time.c */
- ntp_tries = 5;
- /* Replace "pool.ntp.org" with your preferred NTP server */
- configTime(0, 0, "pool.ntp.org");
- /* Wait for time to be set */
- while ((time(nullptr) <= 100000) && ntp_tries > 0) {
- Serial.println(F("Waiting for time to be set..."));
- delay(2000);
- ntp_tries--;
- }
- #endif
- return ret;
- } /* setup_datetime */
- /*****************************************************************************/
- /* Arduino setup_network() */
- /*****************************************************************************/
- int setup_network(void) {
- int ret = 0;
- #if defined(USING_WIFI)
- int status = WL_IDLE_STATUS;
- /* The ESP8266 & ESP32 support both AP and STA. We'll use STA: */
- #if defined(ESP8266) || defined(ESP32)
- WiFi.mode(WIFI_STA);
- #else
- String fv;
- if (WiFi.status() == WL_NO_MODULE) {
- Serial.println("Communication with WiFi module failed!");
- /* don't continue if no network */
- while (true) ;
- }
- fv = WiFi.firmwareVersion();
- if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
- Serial.println("Please upgrade the firmware");
- }
- #endif
- Serial.print(F("Connecting to WiFi "));
- Serial.print(ssid);
- status = WiFi.begin(ssid, password);
- while (status != WL_CONNECTED) {
- delay(1000);
- Serial.print(F("."));
- Serial.print(status);
- status = WiFi.status();
- }
- Serial.println(F(" Connected!"));
- #else
- /* Newer Ethernet shields have a
- * MAC address printed on a sticker on the shield */
- byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
- IPAddress ip(192, 168, 1, 42);
- IPAddress myDns(192, 168, 1, 1);
- Ethernet.init(10); /* Most Arduino shields */
- /* Ethernet.init(5); * MKR ETH Shield */
- /* Ethernet.init(0); * Teensy 2.0 */
- /* Ethernet.init(20); * Teensy++ 2.0 */
- /* Ethernet.init(15); * ESP8266 with Adafruit FeatherWing Ethernet */
- /* Ethernet.init(33); * ESP32 with Adafruit FeatherWing Ethernet */
- Serial.println(F("Initialize Ethernet with DHCP:"));
- if (Ethernet.begin(mac) == 0) {
- Serial.println(F("Failed to configure Ethernet using DHCP"));
- /* Check for Ethernet hardware present */
- if (Ethernet.hardwareStatus() == EthernetNoHardware) {
- Serial.println(F("Ethernet shield was not found."));
- while (true) {
- delay(1); /* do nothing */
- }
- }
- if (Ethernet.linkStatus() == LinkOFF) {
- Serial.println(F("Ethernet cable is not connected."));
- }
- /* try to configure using IP address instead of DHCP : */
- Ethernet.begin(mac, ip, myDns);
- }
- else {
- Serial.print(F(" DHCP assigned IP "));
- Serial.println(Ethernet.localIP());
- }
- /* We'll assume the Ethernet connection is ready to go. */
- #endif
- Serial.println(F("********************************************************"));
- Serial.print(F(" wolfSSL Example Client IP = "));
- #if defined(USING_WIFI)
- Serial.println(WiFi.localIP());
- #else
- Serial.println(Ethernet.localIP());
- #endif
- Serial.print(F(" Configured Server Host to connect to: "));
- Serial.println(host);
- Serial.println(F("********************************************************"));
- Serial.println(F("Setup network complete."));
- return ret;
- }
- /*****************************************************************************/
- /* Arduino setup_wolfssl() */
- /*****************************************************************************/
- int setup_wolfssl(void) {
- int ret = 0;
- WOLFSSL_METHOD* method;
- /* Show a revision of wolfssl user_settings.h file in use when available: */
- #if defined(WOLFSSL_USER_SETTINGS_ID)
- Serial.print(F("WOLFSSL_USER_SETTINGS_ID: "));
- Serial.println(F(WOLFSSL_USER_SETTINGS_ID));
- #else
- Serial.println(F("No WOLFSSL_USER_SETTINGS_ID found."));
- #endif
- #if defined(NO_WOLFSSL_SERVER)
- Serial.println(F("wolfSSL server code disabled to save space."));
- #endif
- #if defined(NO_WOLFSSL_CLIENT)
- Serial.println(F("wolfSSL client code disabled to save space."));
- #endif
- #if defined(DEBUG_WOLFSSL)
- wolfSSL_Debugging_ON();
- Serial.println(F("wolfSSL Debugging is On!"));
- #else
- Serial.println(F("wolfSSL Debugging is Off! (enable with DEBUG_WOLFSSL)"));
- #endif
- /* See ssl.c for TLS cache settings. Larger cache = use more RAM. */
- #if defined(NO_SESSION_CACHE)
- Serial.println(F("wolfSSL TLS NO_SESSION_CACHE"));
- #elif defined(MICRO_SESSION_CACHEx)
- Serial.println(F("wolfSSL TLS MICRO_SESSION_CACHE"));
- #elif defined(SMALL_SESSION_CACHE)
- Serial.println(F("wolfSSL TLS SMALL_SESSION_CACHE"));
- #elif defined(MEDIUM_SESSION_CACHE)
- Serial.println(F("wolfSSL TLS MEDIUM_SESSION_CACHE"));
- #elif defined(BIG_SESSION_CACHE)
- Serial.println(F("wolfSSL TLS BIG_SESSION_CACHE"));
- #elif defined(HUGE_SESSION_CACHE)
- Serial.println(F("wolfSSL TLS HUGE_SESSION_CACHE"));
- #elif defined(HUGE_SESSION_CACHE)
- Serial.println(F("wolfSSL TLS HUGE_SESSION_CACHE"));
- #else
- Serial.println(F("WARNING: Unknown or no TLS session cache setting."));
- /* See wolfssl/src/ssl.c for amount of memory used.
- * It is best on embedded devices to choose a TLS session cache size. */
- #endif
- ret = wolfSSL_Init();
- if (ret == WOLFSSL_SUCCESS) {
- Serial.println("Successfully called wolfSSL_Init");
- }
- else {
- Serial.println("ERROR: wolfSSL_Init failed");
- }
- /* See companion server example with wolfSSLv23_server_method here.
- * method = wolfSSLv23_client_method()); SSL 3.0 - TLS 1.3.
- * method = wolfTLSv1_2_client_method(); only TLS 1.2
- * method = wolfTLSv1_3_client_method(); only TLS 1.3
- *
- * see Arduino\libraries\wolfssl\src\user_settings.h */
- Serial.println("Here we go!");
- method = wolfSSLv23_client_method();
- if (method == NULL) {
- Serial.println(F("unable to get wolfssl client method"));
- fail_wait();
- }
- ctx = wolfSSL_CTX_new(method);
- if (ctx == NULL) {
- Serial.println(F("unable to get ctx"));
- fail_wait();
- }
- return ret;
- }
- /*****************************************************************************/
- /* Arduino setup_certificates() */
- /*****************************************************************************/
- int setup_certificates(void) {
- int ret = 0;
- Serial.println(F("Initializing certificates..."));
- show_memory();
- /* Use built-in validation, No verification callback function: */
- wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0);
- /* Certificate */
- Serial.println("Initializing certificates...");
- ret = wolfSSL_CTX_use_certificate_buffer(ctx,
- CTX_CLIENT_CERT,
- CTX_CLIENT_CERT_SIZE,
- CTX_CLIENT_CERT_TYPE);
- if (ret == WOLFSSL_SUCCESS) {
- Serial.print("Success: use certificate: ");
- Serial.println(xstr(CTX_SERVER_CERT));
- }
- else {
- Serial.println(F("Error: wolfSSL_CTX_use_certificate_buffer failed: "));
- wc_ErrorString(ret, wc_error_message);
- Serial.println(wc_error_message);
- fail_wait();
- }
- /* Setup private client key */
- ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx,
- CTX_CLIENT_KEY,
- CTX_CLIENT_KEY_SIZE,
- CTX_CLIENT_KEY_TYPE);
- if (ret == WOLFSSL_SUCCESS) {
- Serial.print("Success: use private key buffer: ");
- Serial.println(xstr(CTX_SERVER_KEY));
- }
- else {
- Serial.println(F("Error: wolfSSL_CTX_use_PrivateKey_buffer failed: "));
- wc_ErrorString(ret, wc_error_message);
- Serial.println(wc_error_message);
- fail_wait();
- }
- ret = wolfSSL_CTX_load_verify_buffer(ctx,
- CTX_CA_CERT,
- CTX_CA_CERT_SIZE,
- CTX_CA_CERT_TYPE);
- if (ret == WOLFSSL_SUCCESS) {
- Serial.println(F("Success: load_verify CTX_CA_CERT"));
- }
- else {
- Serial.println(F("Error: wolfSSL_CTX_load_verify_buffer failed: "));
- wc_ErrorString(ret, wc_error_message);
- Serial.println(wc_error_message);
- fail_wait();
- }
- return ret;
- } /* Arduino setup */
- /*****************************************************************************/
- /*****************************************************************************/
- /* Arduino setup() */
- /*****************************************************************************/
- /*****************************************************************************/
- void setup(void) {
- int i = 0;
- Serial.begin(SERIAL_BAUD);
- while (!Serial && (i < 10)) {
- /* wait for serial port to connect. Needed for native USB port only */
- delay(1000);
- i++;
- }
- Serial.println(F(""));
- Serial.println(F(""));
- Serial.println(F("wolfSSL TLS Client Example Startup."));
- /* define DEBUG_WOLFSSL in wolfSSL user_settings.h for diagnostics */
- #if defined(DEBUG_WOLFSSL)
- wolfSSL_Debugging_ON();
- #endif
- /* Optionally pre-allocate a large block of memory for testing */
- #if defined(MEMORY_STRESS_TEST)
- Serial.println(F("WARNING: Memory Stress Test Active!"));
- Serial.print(F("Allocating extra memory: "));
- Serial.print(MEMORY_STRESS_INITIAL);
- Serial.println(F(" bytes..."));
- memory_stress[mem_ctr] = (char*)malloc(MEMORY_STRESS_INITIAL);
- show_memory();
- #endif
- setup_hardware();
- setup_network();
- setup_datetime();
- setup_wolfssl();
- setup_certificates();
- /* Initialize wolfSSL using callback functions. */
- wolfSSL_SetIOSend(ctx, EthernetSend);
- wolfSSL_SetIORecv(ctx, EthernetReceive);
- Serial.println(F("Completed Arduino setup!"));
- /* See companion wolfssl_server.ino code; server begins listening here
- * https://github.com/wolfSSL/wolfssl/tree/master/IDE/ARDUINO/sketches/wolfssl_server
- * Any other server will work. See also:
- * https://github.com/wolfSSL/wolfssl/tree/master/examples/client
- */
- /* See companion wolfssl_server.ino code */
- return;
- } /* Arduino setup */
- /*****************************************************************************/
- /* wolfSSL error_check() */
- /*****************************************************************************/
- int error_check(int this_ret, bool halt_on_error,
- const __FlashStringHelper* message) {
- int ret = 0;
- if (this_ret == WOLFSSL_SUCCESS) {
- Serial.print(F("Success: "));
- Serial.println(message);
- }
- else {
- Serial.print(F("ERROR: return = "));
- Serial.print(this_ret);
- Serial.print(F(": "));
- Serial.println(message);
- Serial.println(wc_GetErrorString(this_ret));
- if (halt_on_error) {
- fail_wait();
- }
- }
- show_memory();
- return ret;
- } /* error_check */
- /*****************************************************************************/
- /* wolfSSL error_check_ssl */
- /* Parameters: */
- /* ssl is the current WOLFSSL object pointer */
- /* halt_on_error set to true to suspend operations for critical error */
- /* message is expected to be a memory-efficient F("") macro string */
- /*****************************************************************************/
- int error_check_ssl(WOLFSSL* ssl, int this_ret, bool halt_on_error,
- const __FlashStringHelper* message) {
- int err = 0;
- if (ssl == NULL) {
- Serial.println(F("ssl is Null; Unable to allocate SSL object?"));
- #ifndef DEBUG_WOLFSSL
- Serial.println(F("Define DEBUG_WOLFSSL in user_settings.h for more."));
- #else
- Serial.println(F("See wolfssl/wolfcrypt/error-crypt.h for codes."));
- #endif
- Serial.print(F("ERROR: "));
- Serial.println(message);
- show_memory();
- if (halt_on_error) {
- fail_wait();
- }
- }
- else {
- err = wolfSSL_get_error(ssl, this_ret);
- if (err == WOLFSSL_SUCCESS) {
- Serial.print(F("Success m: "));
- Serial.println(message);
- }
- else {
- if (err < 0) {
- wolfSSL_ERR_error_string(err, errBuf);
- Serial.print(F("WOLFSSL Error: "));
- Serial.print(err);
- Serial.print(F("; "));
- Serial.println(errBuf);
- }
- else {
- Serial.println(F("Success: ssl object."));
- }
- }
- }
- return err;
- }
- /*****************************************************************************/
- /*****************************************************************************/
- /* Arduino loop() */
- /*****************************************************************************/
- /*****************************************************************************/
- void loop() {
- char reply[80];
- char msg[32] = "hello wolfssl!";
- const char* cipherName;
- int retry_shutdown = SHUTDOWN_DELAY_MS; /* max try, once per millisecond */
- int total_input = 0;
- int msgSz = 0;
- int input = 0;
- int ret = 0;
- int err = 0;
- msgSz = (int)strlen(msg);
- Serial.println(F(""));
- Serial.println(F("Starting Arduino loop() ..."));
- if (reconnect) {
- reconnect--;
- /* WiFi client returns true if connection succeeds, false if not. */
- /* Wired client returns int (1,-1,-2,-3,-4) for connection status. */
- Serial.print(F("Connecting to "));
- Serial.print(host);
- Serial.print(F(":"));
- Serial.println(port);
- /* can also use: IPAddress server(192,168,1,37); */
- Serial.println(F("Here we go..."));
- ret = client.connect(host, port);
- Serial.println(F("Ok, checking..."));
- if (ret > 0) {
- Serial.println(F("Connected!"));
- /* initialize wolfSSL */
- ret = wolfSSL_Init();
- error_check(ret, false, F("calling wolfSSL_Init") );
- /* create secure connection object. see setup for ctx certs. */
- Serial.println(F("Calling ssl = wolfSSL_new(ctx)"));
- ssl = wolfSSL_new(ctx);
- error_check_ssl(ssl, 0, true, F("Create WOLFSSL object from ctx"));
- Serial.print(F("Connecting to wolfSSL TLS Secure Server..."));
- do {
- err = 0; /* reset error */
- Serial.println(F("wolfSSL_connect ..."));
- ret = wolfSSL_connect(ssl);
- Serial.print("wolfSSL_connect return result =");
- Serial.println(ret);
- if ((ret != WOLFSSL_SUCCESS) && (ret != WC_PENDING_E)) {
- Serial.println(F("Failed connection, checking error."));
- err = error_check_ssl(ssl, ret, true,
- F("Create WOLFSSL object from ctx"));
- Serial.print("err =");
- Serial.println(err);
- }
- else {
- Serial.print(PROGRESS_DOT);
- }
- } while (err == WC_PENDING_E);
- Serial.println();
- Serial.println(F("Connected!"));
- Serial.print(F("SSL version is "));
- Serial.println(wolfSSL_get_version(ssl));
- cipherName = wolfSSL_get_cipher(ssl);
- Serial.print(F("SSL cipher suite is "));
- Serial.println(cipherName);
- /* see test.h
- * TODO: test.h needs a little bit of Arduino work for these:
- showPeerEx(ssl, lng_index);
- showPeerPEM(ssl);
- */
- Serial.print(F("Sending secure message to server: "));
- Serial.println(msg);
- ret = wolfSSL_write(ssl, msg, msgSz);
- if (ret == msgSz) {
- Serial.print(F("Waiting for Server response..."));
- while (!client.available()) {
- /* wait for data */
- delay(1); /* 1 ms delay */
- }
- Serial.print(F("Reading response.."));
- /* read data */
- do {
- ret = wolfSSL_read(ssl, reply, sizeof(reply) - 1);
- if (ret < 0) {
- error_check_ssl(ssl, ret, false,
- F("during TLS Read"));
- }
- else {
- Serial.print(PROGRESS_DOT);
- }
- } while (err == WC_PENDING_E);
- Serial.println();
- Serial.println();
- Serial.println(reply); /* typically: I hear you fa shizzle! */
- Serial.println();
- } /* wolfSSL_write message size matched */
- else {
- error_check_ssl(ssl, ret, false,
- F("during TLS Write"));
- } /* any wolfSSL_write message size mismatch is an error */
- Serial.print(F("Shutting down.."));
- do {
- delay(1);
- Serial.print(PROGRESS_DOT);
- retry_shutdown--;
- ret = wolfSSL_shutdown(ssl);
- } while ( (ret == WOLFSSL_SHUTDOWN_NOT_DONE)
- && (retry_shutdown > 0)
- ); /* There may be pending data, so wait until done. */
- Serial.println();
- if (retry_shutdown <= 0) {
- /* if wolfSSL_free is called before properly shutting down the
- * ssl object, undesired results may occur. */
- Serial.println(F("Warning! Shutdown did not properly complete."));
- }
- wolfSSL_free(ssl);
- client.stop();
- Serial.println(F("Connection complete."));
- if (REPEAT_CONNECTION) {
- reconnect = RECONNECT_ATTEMPTS;
- }
- else {
- reconnect = 0;
- }
- } /* client.connect(host, port) */
- else {
- Serial.println(F("Problem sending message. Trying to reconnect..."));
- }
- }
- delay(1000);
- if ((reconnect > 0) && (REPEAT_CONNECTION)) {
- Serial.println(F("Arduino loop repeating..."));
- Serial.println();
- }
- else {
- printf("wow");
- Serial.println(F("Done!"));
- while(1) {
- /* wait forever */
- }
- }
- #if defined(MEMORY_STRESS_TEST)
- if (mem_ctr < MEMORY_STRESS_ITERATIONS) {
- /* reminder: mem_ctr == 0 is MEMORY_STRESS_INITIAL allocation */
- mem_ctr++;
- Serial.print(F("Memory stress increment: "));
- Serial.print(mem_ctr);
- Serial.print(F(". Allocating addition memory (bytes): "));
- Serial.println(MEMORY_STRESS_BLOCK_SIZE);
- memory_stress[mem_ctr] = (char*)malloc(MEMORY_STRESS_BLOCK_SIZE);
- show_memory();
- }
- #endif
- } /* Arduino loop repeats */
|