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