diff --git a/lwip/README.md b/lwip/README.md new file mode 100644 index 00000000..891cfe37 --- /dev/null +++ b/lwip/README.md @@ -0,0 +1,22 @@ +# LWIP Native Example + +Assumes there is an existing STM project with native LwIP support. wolfSSL needs to be compiled with the macro `WOLFSSL_LWIP_NATIVE` + +The main function to call in the example code is `tls_echoclient_connect();` + +Macros in `lwipopts.h` were also adjusted to better handle TLS packets, which can be as large as 16k. The macros adjusted were: +- MEM_SIZE(16*1024) +- MEMP_NUM_PBUF (10 -> 20) +- PBUF_POOL_SIZE (8 -> 9) +- PBUF_POOL_BUFSIZE (512 -> 2048) +- TCP_WND (2*TCP_MSS -> 11*TCP_MSS) + + +To start up a server for the example client to connect to use the bundled wolfSSL example +server on a desktop: + +``` +cd wolfssl +./configure && make +./examples/server/server -b -d -p 11111 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -i +``` diff --git a/lwip/example-lwip-native-echoclient.c b/lwip/example-lwip-native-echoclient.c new file mode 100644 index 00000000..3d3f18d3 --- /dev/null +++ b/lwip/example-lwip-native-echoclient.c @@ -0,0 +1,240 @@ +/* example-lwip-native-echoclient.c + * + * Copyright (C) 2006-2022 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ + +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/tcp.h" +#include "lwip/memp.h" +#include +#include + +#ifndef WOLFSSL_USER_SETTINGS +#include +#endif +#include +#include + +#ifndef NO_RSA + #define USE_CERT_BUFFERS_2048 + #define CA_CERTS ca_cert_der_2048 + #define CA_CERTS_LEN sizeof_ca_cert_der_2048 + #define CLIENT_CERT client_cert_der_2048 + #define CLIENT_CERT_LEN sizeof_client_cert_der_2048 + #define CLIENT_KEY client_key_der_2048 + #define CLIENT_KEY_LEN sizeof_client_key_der_2048 +#elif defined(HAVE_ECC) + #define USE_CERT_BUFFERS_256 + #define CA_CERTS ca_ecc_cert_der_256 + #define CA_CERTS_LEN sizeof_ca_ecc_cert_der_256 + #define CLIENT_CERT cliecc_cert_der_256 + #define CLIENT_CERT_LEN sizeof_cliecc_cert_der_256 + #define CLIENT_KEY ecc_clikey_der_256 + #define CLIENT_KEY_LEN sizeof_ecc_clikey_der_256 +#else + #error This examples requires either RSA or ECC to be enabled +#endif +#include +#include + +#ifndef DEST_PORT + #define DEST_PORT 11111 +#endif +#ifndef DEST_IP_ADDR0 + #define DEST_IP_ADDR0 127 + #define DEST_IP_ADDR1 0 + #define DEST_IP_ADDR2 0 + #define DEST_IP_ADDR3 1 +#endif + +#ifndef MAX_MSG_SIZE +#define MAX_MSG_SIZE +#endif + +#define TEST_MSG "TLS **TEST 1** " + +static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err); +static void TLS_shutdown(void); +static int TLS_connect(void); +static int TLS_setup(void); + +struct tcp_pcb *tls_pcb = NULL; +struct tcp_pcb *debug_pcb = NULL; + +static int tlsConnected = 0; +static int tcpConnected = 0; +static int tlsWaitingForReply = 0; + +static WOLFSSL_CTX *ctx = NULL; +static WOLFSSL *ssl = NULL; + +void loggingCb(const int logLevel, const char *const logMessage) +{ + printf("%s\n", logMessage); + (void)logLevel; +} + +void tls_echoclient_connect(void) +{ + ip_addr_t DestIPaddr; + + if (tcpConnected == 0) { + tls_pcb = tcp_new(); + if (tls_pcb != NULL) { + IP4_ADDR(&DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3); + tcp_connect(tls_pcb, &DestIPaddr, DEST_PORT, + tcp_echoclient_connected); + } + } + + if (tcpConnected == 1 && tlsConnected == 0) { + TLS_connect(); + } + + if (tlsConnected == 1) { + int ret; + char reply[MAX_MSG_SIZE]; + int err; + + if (tlsWaitingForReply == 0) { + ret = wolfSSL_write(ssl, TEST_MSG, sizeof(TEST_MSG)); + if (ret <= 0) { + loggingCb(0, "error when writing TLS message"); + shutdown(); + } + else { + tlsWaitingForReply = 1; + } + } + + /* read a reply from the server */ + if (tlsWaitingForReply == 1) { + memset(reply, 0, sizeof(reply)); + ret = wolfSSL_read(ssl, reply, sizeof(reply)); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + if (err != SSL_ERROR_WANT_READ && + err != WOLFSSL_ERROR_WANT_WRITE) { + loggingCb(0, "error when reading TLS message"); + shutdown(); + } + } + if (ret > 0) { + loggingCb(0, reply); + shutdown(); /* received reply, done with connection */ + } + } + } +} + +static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err) +{ + if (err == ERR_OK) { + tcpConnected = 1; + /* a tcp_poll could be added here for connection timeout checking */ + return TLS_setup(); + } + return ERR_OK; +} + + +/* setup all the TLS structures and load CA */ +static int TLS_setup(void) +{ + int ret; + +#ifdef DEBUG_WOLFSSL + /* redirect wolfssl debug print outs */ + wolfSSL_SetLoggingCb(loggingCb); + wolfSSL_Debugging_ON(); +#endif + wolfSSL_Init(); /* called once on program startup */ + ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (ctx == NULL) { + loggingCb(0, "ctx was null"); + shutdown(); + return ERR_MEM; + } + + /* Load the CA */ + ret = wolfSSL_CTX_load_verify_buffer(ctx, CA_CERTS, CA_CERTS_LEN, + WOLFSSL_FILETYPE_ASN1); + if (ret != WOLFSSL_SUCCESS) { + loggingCb(0, "error loading in verify buffer"); + return ERR_MEM; + } + +#if 1 + /* Disable peer certificate validation for testing */ + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL); +#endif + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + loggingCb(0, "ssl was null"); + return ERR_MEM; + } + wolfSSL_SetIO_LwIP(ssl, tls_pcb, NULL, NULL, NULL); + return ERR_OK; +} + +static int TLS_connect(void) +{ + if (wolfSSL_connect(ssl) != WOLFSSL_SUCCESS) { + /* check if hitting a want read/write case and should call again */ + int err = wolfSSL_get_error(ssl, 0); + if (err != SSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE) { + loggingCb(0, "connect error, shutting down"); + loggingCb(0, wolfSSL_ERR_reason_error_string(err)); + shutdown(); + return ERR_CONN; + } + loggingCb(0, "found want read/write"); + } + else { + loggingCb(0, "setting tlsConnected to 1"); + tlsConnected = 1; + } + return ERR_OK; +} + +/* close all connections and free TLS session */ +static void TLS_shutdown(void) +{ + if (ssl != NULL) { + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + } + + if (ctx != NULL) { + wolfSSL_CTX_free(ctx); + } + + tlsConnected = 0; + tlsWaitingForReply = 0; + wolfSSL_Cleanup(); + + if (tcpConnected == 1) { + tcp_output(tls_pcb); + tcp_close(tls_pcb); + tls_pcb = NULL; + tcpConnected = 0; + } +}