From a251e596c5a5bac2de740bb18ebbdc279991f17b Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Wed, 26 Sep 2018 10:00:42 +0200 Subject: [PATCH 01/19] - very early version with mbed TLS support. --- src/AsyncTCP.cpp | 147 +++++++++++++-- src/AsyncTCP.h | 14 +- src/tcp_mbedtls.c | 469 ++++++++++++++++++++++++++++++++++++++++++++++ src/tcp_mbedtls.h | 46 +++++ 4 files changed, 653 insertions(+), 23 deletions(-) create mode 100644 src/tcp_mbedtls.c create mode 100644 src/tcp_mbedtls.h diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index e6040951..3e1ede9d 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -215,6 +215,7 @@ static int8_t _tcp_poll(void * arg, struct tcp_pcb * pcb) { } static int8_t _tcp_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { + log_i("_tcp_recv"); lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); e->event = LWIP_TCP_RECV; e->arg = arg; @@ -228,6 +229,7 @@ static int8_t _tcp_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_ } static int8_t _tcp_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { + log_e("_tcp_sent"); lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); e->event = LWIP_TCP_SENT; e->arg = arg; @@ -432,8 +434,6 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) , next(NULL) , _in_lwip_thread(false) { - //ets_printf("+: 0x%08x\n", (uint32_t)this); - _pcb = pcb; if(_pcb){ _rx_last_packet = millis(); @@ -449,11 +449,9 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) AsyncClient::~AsyncClient(){ if(_pcb) _close(); - - //ets_printf("-: 0x%08x\n", (uint32_t)this); } -bool AsyncClient::connect(IPAddress ip, uint16_t port){ +bool AsyncClient::connect(IPAddress ip, uint16_t port, bool secure){ if (_pcb){ log_w("already connected, state %d", _pcb->state); return false; @@ -473,11 +471,19 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){ return false; } + Serial.print("connect res ip: "); + Serial.println(secure); + + _pcb_secure = secure; + _handshake_done = !secure; + tcp_arg(pcb, this); tcp_err(pcb, &_tcp_error); if(_in_lwip_thread){ + log_i("tcp_connect-1: _in_lwip_thread: %d", _in_lwip_thread); tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected); } else { + log_i("tcp_connect-2: _in_lwip_thread: %d", _in_lwip_thread); _tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected); } return true; @@ -495,37 +501,64 @@ AsyncClient& AsyncClient::operator=(const AsyncClient& other){ tcp_sent(_pcb, &_tcp_sent); tcp_err(_pcb, &_tcp_error); tcp_poll(_pcb, &_tcp_poll, 1); + + if(tcp_ssl_has(_pcb)){ + _pcb_secure = true; + _handshake_done = false; + tcp_ssl_arg(_pcb, this); + tcp_ssl_data(_pcb, &_s_data); + tcp_ssl_handshake(_pcb, &_s_handshake); + tcp_ssl_err(_pcb, &_s_ssl_error); + } else { + _pcb_secure = false; + _handshake_done = true; + } } return *this; } int8_t AsyncClient::_connected(void* pcb, int8_t err){ _pcb = reinterpret_cast(pcb); + + log_i("error: %d", err); if(_pcb){ _rx_last_packet = millis(); _pcb_busy = false; tcp_recv(_pcb, &_tcp_recv); tcp_sent(_pcb, &_tcp_sent); tcp_poll(_pcb, &_tcp_poll, 1); + + if(_pcb_secure){ + tcp_ssl_arg(_pcb, this); + log_e("_pcb: 0x%x", _pcb); + if(tcp_ssl_new_client(_pcb) < 0){ + return _close(); + } + + tcp_ssl_arg(_pcb, this); + tcp_ssl_data(_pcb, &_s_data); + tcp_ssl_handshake(_pcb, &_s_handshake); + tcp_ssl_err(_pcb, &_s_ssl_error); + } } _in_lwip_thread = true; - if(_connect_cb) + if(!_pcb_secure && _connect_cb) _connect_cb(_connect_cb_arg, this); _in_lwip_thread = false; return ERR_OK; } int8_t AsyncClient::_close(){ - //ets_printf("X: 0x%08x\n", (uint32_t)this); int8_t err = ERR_OK; if(_pcb) { - //log_i(""); + if(_pcb_secure){ + tcp_ssl_free(_pcb); + } tcp_arg(_pcb, NULL); tcp_sent(_pcb, NULL); tcp_recv(_pcb, NULL); tcp_err(_pcb, NULL); tcp_poll(_pcb, NULL, 0); - _tcp_clear_events(this); if(_in_lwip_thread){ err = tcp_close(_pcb); } else { @@ -535,6 +568,7 @@ int8_t AsyncClient::_close(){ err = abort(); } _pcb = NULL; + // _tcp_clear_events(this); if(_discard_cb) _discard_cb(_discard_cb_arg, this); } @@ -542,6 +576,7 @@ int8_t AsyncClient::_close(){ } void AsyncClient::_error(int8_t err) { + log_e("Error!! %d", err); if(_pcb){ tcp_arg(_pcb, NULL); tcp_sent(_pcb, NULL); @@ -556,7 +591,16 @@ void AsyncClient::_error(int8_t err) { _discard_cb(_discard_cb_arg, this); } +void AsyncClient::_ssl_error(int8_t err){ + if(_error_cb) + _error_cb(_error_cb_arg, this, err+64); +} + int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { + log_e("_sent"); + if (_pcb_secure && !_handshake_done) + return ERR_OK; + _in_lwip_thread = false; _rx_last_packet = millis(); //log_i("%u", len); @@ -567,13 +611,15 @@ int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { } int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { + log_e("_recv"); if(!_pcb || pcb != _pcb){ - log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - if(pb){ - pbuf_free(pb); - } - return ERR_OK; - } + log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + if(pb){ + pbuf_free(pb); + } + return ERR_OK; + } + _in_lwip_thread = false; if(pb == NULL){ return _close(); @@ -581,6 +627,18 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { while(pb != NULL){ _rx_last_packet = millis(); + if(_pcb_secure){ + // log_i("_recv: %d\n", pb->tot_len); + int read_bytes = tcp_ssl_read(pcb, pb); + if(read_bytes < 0){ + if (read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + log_e("_recv err: %d\n", read_bytes); + _close(); + } + //return read_bytes; + } + return ERR_OK; + } //we should not ack before we assimilate the data //log_i("%u", pb->len); //Serial.write((const uint8_t *)pb->payload, pb->len); @@ -627,6 +685,10 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ _close(); return ERR_OK; } + if(_pcb_secure && !_handshake_done && (now - _rx_last_packet) >= 2000){ + _close(); + return ERR_OK; + } // Everything is fine if(_poll_cb) _poll_cb(_poll_cb_arg, this); @@ -636,7 +698,7 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ void AsyncClient::_dns_found(struct ip_addr *ipaddr){ _in_lwip_thread = true; if(ipaddr){ - connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port); + connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port, _pcb_secure); } else { log_e("dns fail"); if(_error_cb) @@ -651,13 +713,26 @@ bool AsyncClient::operator==(const AsyncClient &other) { return _pcb == other._pcb; } -bool AsyncClient::connect(const char* host, uint16_t port){ +bool AsyncClient::connect(const char* host, uint16_t port, bool secure){ ip_addr_t addr; + + Serial.print("connect ip: "); + Serial.println(secure); + err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_s_dns_found, this); if(err == ERR_OK) { - return connect(IPAddress(addr.u_addr.ip4.addr), port); + Serial.print("connect a ip: "); + Serial.println(secure); + + return connect(IPAddress(addr.u_addr.ip4.addr), port, secure); } else if(err == ERR_INPROGRESS) { + + Serial.print("connect b ip: "); + Serial.println(secure); + _connect_port = port; + _pcb_secure = secure; + _handshake_done = !secure; return true; } log_e("error: %d", err); @@ -723,13 +798,22 @@ size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { return will_send; } - size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { if(!_pcb || size == 0 || data == NULL) return 0; size_t room = space(); if(!room) return 0; + if(_pcb_secure){ + int sent = tcp_ssl_write(_pcb, (uint8_t*)data, size); + if(sent >= 0){ + // @ToDo: ??? + //_tx_unacked_len += sent; + return sent; + } + _close(); + return 0; + } size_t will_send = (room < size) ? room : size; int8_t err = ERR_OK; if(_in_lwip_thread){ @@ -743,6 +827,9 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { } bool AsyncClient::send(){ + if(_pcb_secure) + return true; + int8_t err = ERR_OK; if(_in_lwip_thread){ err = tcp_output(_pcb); @@ -955,6 +1042,7 @@ void AsyncClient::onPoll(AcConnectHandler cb, void* arg){ } +// void AsyncClient::_s_dns_found(const char * name, ip_addr_t * ipaddr, void * arg){ void AsyncClient::_s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg){ if(arg){ reinterpret_cast(arg)->_dns_found(ipaddr); @@ -977,7 +1065,7 @@ int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, i reinterpret_cast(arg)->_recv(pcb, pb, err); } else { if(pb){ - pbuf_free(pb); + pbuf_free(pb); } log_e("Bad Args: 0x%08x 0x%08x", arg, pcb); } @@ -1010,6 +1098,25 @@ int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ return ERR_OK; } +void AsyncClient::_s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len){ + log_i("_s_data"); + AsyncClient *c = reinterpret_cast(arg); + if(c->_recv_cb) + c->_recv_cb(c->_recv_cb_arg, c, data, len); +} + +void AsyncClient::_s_handshake(void *arg, struct tcp_pcb *tcp, struct tcp_ssl_pcb* ssl){ + AsyncClient *c = reinterpret_cast(arg); + log_i("_s_handshake: done!"); + c->_handshake_done = true; + if(c->_connect_cb) + c->_connect_cb(c->_connect_cb_arg, c); +} + +void AsyncClient::_s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err){ + reinterpret_cast(arg)->_ssl_error(err); +} + const char * AsyncClient::errorToString(int8_t error){ switch(error){ case 0: return "OK"; diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 6cd0fca2..b8a417fd 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -24,10 +24,12 @@ #include "IPAddress.h" #include +#include extern "C" { #include "freertos/semphr.h" #include "lwip/pbuf.h" } +#include "tcp_mbedtls.h" class AsyncClient; @@ -48,6 +50,7 @@ struct ip_addr; class AsyncClient { protected: tcp_pcb* _pcb; + // sslclient_context* _ssl_context; AcConnectHandler _connect_cb; void* _connect_cb_arg; @@ -67,6 +70,8 @@ class AsyncClient { void* _poll_cb_arg; bool _pcb_busy; + bool _pcb_secure; + bool _handshake_done; uint32_t _pcb_sent_at; bool _close_pcb; bool _ack_pcb; @@ -79,10 +84,13 @@ class AsyncClient { int8_t _close(); int8_t _connected(void* pcb, int8_t err); void _error(int8_t err); + void _ssl_error(int8_t err); int8_t _poll(tcp_pcb* pcb); int8_t _sent(tcp_pcb* pcb, uint16_t len); void _dns_found(struct ip_addr *ipaddr); - + static void _s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len); + static void _s_handshake(void *arg, struct tcp_pcb *tcp, struct tcp_ssl_pcb* ssl); + static void _s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err); public: AsyncClient* prev; @@ -99,8 +107,8 @@ class AsyncClient { bool operator!=(const AsyncClient &other) { return !(*this == other); } - bool connect(IPAddress ip, uint16_t port); - bool connect(const char* host, uint16_t port); + bool connect(IPAddress ip, uint16_t port, bool secure = false); + bool connect(const char* host, uint16_t port, bool secure = false); void close(bool now = false); void stop(); int8_t abort(); diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c new file mode 100644 index 00000000..db9db212 --- /dev/null +++ b/src/tcp_mbedtls.c @@ -0,0 +1,469 @@ +#include "tcp_mbedtls.h" +#include "lwip/tcp.h" +#include "mbedtls/debug.h" +#include + +#define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) + +static const char pers[] = "esp32-tls"; + +static int handle_error(int err) +{ + if(err == -30848){ + return err; + } +#ifdef MBEDTLS_ERROR_C + char error_buf[100]; + mbedtls_strerror(err, error_buf, 100); + TCP_SSL_DEBUG("%s\n", error_buf); +#endif + TCP_SSL_DEBUG("MbedTLS message code: %d\n", err); + return err; +} + +static uint8_t _tcp_ssl_has_client = 0; + +struct tcp_ssl_pcb { + struct tcp_pcb *tcp; + int fd; + mbedtls_ssl_context ssl_ctx; + mbedtls_ssl_config ssl_conf; + mbedtls_ctr_drbg_context drbg_ctx; + mbedtls_entropy_context entropy_ctx; + uint8_t type; + // int handshake; + void* arg; + tcp_ssl_data_cb_t on_data; + tcp_ssl_handshake_cb_t on_handshake; + tcp_ssl_error_cb_t on_error; + int last_wr; + struct pbuf *tcp_pbuf; + int pbuf_offset; + struct tcp_ssl_pcb* next; +}; + +typedef struct tcp_ssl_pcb tcp_ssl_t; + +static tcp_ssl_t * tcp_ssl_array = NULL; +static int tcp_ssl_next_fd = 0; + +int tcp_ssl_recv(void *ctx, unsigned char *buf, size_t len) { + tcp_ssl_t *fd_data = (tcp_ssl_t*)ctx; + uint8_t *read_buf = NULL; + uint8_t *pread_buf = NULL; + u16_t recv_len = 0; + + if(fd_data->tcp_pbuf == NULL || fd_data->tcp_pbuf->tot_len == 0) { + return 0; + } + + read_buf =(uint8_t*)calloc(fd_data->tcp_pbuf->len + 1, sizeof(uint8_t)); + pread_buf = read_buf; + if (pread_buf != NULL){ + recv_len = pbuf_copy_partial(fd_data->tcp_pbuf, read_buf, len, fd_data->pbuf_offset); + fd_data->pbuf_offset += recv_len; + } + + if (recv_len != 0) { + memcpy(buf, read_buf, recv_len); + } + + if(len < recv_len) { + TCP_SSL_DEBUG("tcp_ssl_recv: got %d bytes more than expected\n", recv_len - len); + } + + free(pread_buf); + pread_buf = NULL; + + return recv_len; +} + +int tcp_ssl_send(void *ctx, const unsigned char *buf, size_t size) { + if(ctx == NULL) { + TCP_SSL_DEBUG("tcp_ssl_send: no context set\n"); + return -1; + } + + if(buf == NULL) { + TCP_SSL_DEBUG("tcp_ssl_send: buf not set\n"); + return -1; + } + + tcp_ssl_t *tcp = (tcp_ssl_t*)ctx; + + size_t room = tcp_sndbuf(tcp->tcp); + size_t will_send = (room < size) ? room : size; + + TCP_SSL_DEBUG("len: %d, has space? %d\n", size, room); + + int8_t ret = tcp_write(tcp->tcp, buf, will_send, 0); + if(ret == ERR_OK) { + TCP_SSL_DEBUG("oki!\n"); + } + + return will_send; +} + +uint8_t tcp_ssl_has_client() { + return _tcp_ssl_has_client; +} + +tcp_ssl_t * tcp_ssl_new(struct tcp_pcb *tcp) { + + if(tcp_ssl_next_fd < 0){ + tcp_ssl_next_fd = 0;//overflow + } + + tcp_ssl_t * new_item = (tcp_ssl_t*)malloc(sizeof(tcp_ssl_t)); + if(!new_item){ + TCP_SSL_DEBUG("tcp_ssl_new: failed to allocate tcp_ssl\n"); + return NULL; + } + + new_item->tcp = tcp; + new_item->arg = NULL; + new_item->on_data = NULL; + new_item->on_handshake = NULL; + new_item->on_error = NULL; + new_item->tcp_pbuf = NULL; + new_item->pbuf_offset = 0; + new_item->next = NULL; + // new_item->ssl_ctx = NULL; + // new_item->ssl = NULL; + new_item->fd = tcp_ssl_next_fd++; + + if(tcp_ssl_array == NULL){ + tcp_ssl_array = new_item; + } else { + tcp_ssl_t * item = tcp_ssl_array; + while(item->next != NULL) + item = item->next; + item->next = new_item; + } + + TCP_SSL_DEBUG("tcp_ssl_new: %d: 0x%x\n", new_item->fd, tcp); + return new_item; +} + +tcp_ssl_t* tcp_ssl_get(struct tcp_pcb *tcp) { + if(tcp == NULL) { + return NULL; + } + tcp_ssl_t * item = tcp_ssl_array; + while(item && item->tcp != tcp){ + item = item->next; + } + return item; +} + +int tcp_ssl_new_client(struct tcp_pcb *tcp) { + tcp_ssl_t* tcp_ssl; + + TCP_SSL_DEBUG("tcp_ssl_new_client\n"); + + if(tcp == NULL) { + return -1; + } + + if(tcp_ssl_get(tcp) != NULL){ + TCP_SSL_DEBUG("tcp_ssl_new_client: tcp_ssl already exists\n"); + return -1; + } + + tcp_ssl = tcp_ssl_new(tcp); + if(tcp_ssl == NULL){ + return -1; + } + + // + mbedtls_entropy_init(&tcp_ssl->entropy_ctx); + mbedtls_ctr_drbg_init(&tcp_ssl->drbg_ctx); + mbedtls_ssl_init(&tcp_ssl->ssl_ctx); + mbedtls_ssl_config_init(&tcp_ssl->ssl_conf); + + mbedtls_ctr_drbg_seed(&tcp_ssl->drbg_ctx, mbedtls_entropy_func, + &tcp_ssl->entropy_ctx, (const unsigned char*)pers, strlen(pers)); + + if(mbedtls_ssl_config_defaults(&tcp_ssl->ssl_conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) { + TCP_SSL_DEBUG("error setting SSL config.\n"); + + // tcp_ssl_free(tcp); + return -1; + } + + mbedtls_ssl_conf_authmode(&tcp_ssl->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); + int ret = 0; + + // @ToDo: there's no hostname at this stage, set it later. + // if((ret = mbedtls_ssl_set_hostname(&ctx->ssl_ctx, host)) != 0){ + // return handle_error(ret); + // } + + mbedtls_ssl_conf_rng(&tcp_ssl->ssl_conf, mbedtls_ctr_drbg_random, &tcp_ssl->drbg_ctx); + + if ((ret = mbedtls_ssl_setup(&tcp_ssl->ssl_ctx, &tcp_ssl->ssl_conf)) != 0) { + // tcp_ssl_free(tcp); + return handle_error(ret); + } + + // mbedtls_ssl_set_bio(&tcp_ssl->ssl_ctx, (void*)tcp_ssl, tcp_ssl_send, tcp_ssl_recv, NULL ); + mbedtls_ssl_set_bio(&tcp_ssl->ssl_ctx, (void*)tcp_ssl, tcp_ssl_send, tcp_ssl_recv, NULL); + // mbedtls_ssl_set_bio(&tcp_ssl->ssl_ctx, &tcp_ssl->fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + // @ToDo: do we need this here? + ret = mbedtls_ssl_handshake(&tcp_ssl->ssl_ctx); + handle_error(ret); + TCP_SSL_DEBUG("ret mbedtls_ssl_handshake: %d, want read: %d, write: %d\n", ret, MBEDTLS_ERR_SSL_WANT_READ, MBEDTLS_ERR_SSL_WANT_WRITE); + // if (ret != 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + // TCP_SSL_DEBUG("tcp_ssl_new_client: mbedtls_ssl_handshake: %d.\n", ret); + // // if(tcp_ssl->on_error) + // // tcp_ssl->on_error(tcp_ssl->arg, tcp_ssl->tcp, ret); + // } + + TCP_SSL_DEBUG("end tcp_ssl_new_client %d.\n", tcp_ssl->fd); + + return tcp_ssl->fd; +} + +int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) { + if(tcp == NULL) { + return -1; + } + + tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp); + + TCP_SSL_DEBUG("tcp_ssl_write %x\n, state: %d\n", tcp_ssl, tcp->state); + + if(tcp_ssl == NULL){ + TCP_SSL_DEBUG("tcp_ssl_write: tcp_ssl is NULL\n"); + return 0; + } + + tcp_ssl->last_wr = 0; + + TCP_SSL_DEBUG("about to call mbedtls_ssl_write\n"); + int rc = mbedtls_ssl_write(&tcp_ssl->ssl_ctx, data, len); + + TCP_SSL_DEBUG("tcp_ssl_write: %u -> %d (%d)\r\n", len, tcp_ssl->last_wr, rc); + + if (rc < 0){ + // @ToDO: ??? + // if(rc != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + TCP_SSL_DEBUG("tcp_ssl_write error: %d\r\n", rc); + // } + return rc; + } + + return tcp_ssl->last_wr; +} + +int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { + TCP_SSL_DEBUG("tcp_ssl_ssl_read\n"); + + if(tcp == NULL) { + return -1; + } + tcp_ssl_t* fd_data = NULL; + + int read_bytes = 0; + int total_bytes = 0; + uint8_t *read_buf; + + fd_data = tcp_ssl_get(tcp); + if(fd_data == NULL) { + TCP_SSL_DEBUG("tcp_ssl_read: tcp_ssl is NULL\n"); + return ERR_TCP_SSL_INVALID_CLIENTFD_DATA; + } + + if(p == NULL) { + TCP_SSL_DEBUG("tcp_ssl_read:p == NULL\n"); + return ERR_TCP_SSL_INVALID_DATA; + } + + TCP_SSL_DEBUG("READY TO READ SOME DATA\n"); + + fd_data->tcp_pbuf = p; + fd_data->pbuf_offset = 0; + + do { + if(fd_data->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + TCP_SSL_DEBUG("start handshake: %d\n", fd_data->ssl_ctx.state); + int ret = mbedtls_ssl_handshake(&fd_data->ssl_ctx); + if(ret == 0) { + if(fd_data->on_handshake) + fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data); + } else if(ret != MBEDTLS_ERR_SSL_WANT_READ || ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + // if(fd_data->on_error) + // fd_data->on_error(fd_data->arg, fd_data->tcp, ret); + + TCP_SSL_DEBUG("handshake error: %d\n", ret); + // return ret; + //return 0; + } + } else { + uint8_t readb[1024]; + read_bytes = mbedtls_ssl_read(&fd_data->ssl_ctx, &readb, 1024); + TCP_SSL_DEBUG("start read: %d.\n", read_bytes); + if(read_bytes < 0) { + handle_error(read_bytes); + if(read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes); + } + total_bytes = read_bytes; + break; + } else if(read_bytes > 0) { + if(fd_data->on_data){ + fd_data->on_data(fd_data->arg, tcp, &readb, read_bytes); + } + total_bytes+= read_bytes; + } + } + // if(fd_data->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + // TCP_SSL_DEBUG("start handshake.\n"); + // int ret = mbedtls_ssl_handshake(&fd_data->ssl_ctx); + // if(ret == 0) { + // if(fd_data->on_handshake) + // fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data); + // } else if(ret != MBEDTLS_ERR_SSL_WANT_READ || ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + // if(fd_data->on_error) + // fd_data->on_error(fd_data->arg, fd_data->tcp, ret); + // return ret; + // } + // } + // // @TODO: FIX! + // read_bytes = mbedtls_ssl_read(&fd_data->ssl_ctx, &read_buf, 0); + // TCP_SSL_DEBUG("tcp_ssl_ssl_read: read_bytes: %d (%d)\n", read_bytes, MBEDTLS_SSL_HANDSHAKE_OVER); + // if(read_bytes < 0) { + // handle_error(read_bytes); + // if(read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + // TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes); + // } + // total_bytes = read_bytes; + // break; + // } else if(read_bytes > 0){ + // if(fd_data->on_data){ + // fd_data->on_data(fd_data->arg, tcp, read_buf, read_bytes); + // } + // total_bytes+= read_bytes; + // } else { + // TCP_SSL_DEBUG("start handshake? %d.\n", fd_data->ssl_ctx.state); + // if(fd_data->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + // TCP_SSL_DEBUG("start handshake.\n"); + // int ret = mbedtls_ssl_handshake(&fd_data->ssl_ctx); + // if(ret == 0) { + // if(fd_data->on_handshake) + // fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data); + // } else if(ret != MBEDTLS_ERR_SSL_WANT_READ || ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + // if(fd_data->on_error) + // fd_data->on_error(fd_data->arg, fd_data->tcp, ret); + // return ret; + // } + // } + // } + } while (p->tot_len - fd_data->pbuf_offset > 0); + + // OLD + // if(fd_data->handshake != MBEDTLS_SSL_HANDSHAKE_OVER) { + // fd_data->handshake = mbedtls_ssl_handshake(&fd_data->ssl_ctx); + // if(fd_data->handshake == 0){ + // TCP_SSL_DEBUG("tcp_ssl_read: handshake OK\n"); + // if(fd_data->on_handshake) + // fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data); + // } else if(fd_data->handshake != 0){ + // TCP_SSL_DEBUG("tcp_ssl_read: handshake error: %d\n", fd_data->handshake); + // if(fd_data->on_error) + // fd_data->on_error(fd_data->arg, fd_data->tcp, fd_data->handshake); + // return fd_data->handshake; + // } + // } + + tcp_recved(tcp, p->tot_len); + fd_data->tcp_pbuf = NULL; + pbuf_free(p); + + TCP_SSL_DEBUG("tcp_ssl_read: eof: %d\n", total_bytes); + + return total_bytes; +} + +int tcp_ssl_free(struct tcp_pcb *tcp) { + TCP_SSL_DEBUG("tcp_ssl_free: 1\n"); + if(tcp == NULL) { + return -1; + } + TCP_SSL_DEBUG("tcp_ssl_free: 2\n"); + tcp_ssl_t * item = tcp_ssl_array; + TCP_SSL_DEBUG("tcp_ssl_free: 2a 0x%x\n", item); + if(item->tcp == tcp){ + TCP_SSL_DEBUG("tcp_ssl_free: 3\n"); + tcp_ssl_array = tcp_ssl_array->next; + if(item->tcp_pbuf != NULL) { + pbuf_free(item->tcp_pbuf); + } + TCP_SSL_DEBUG("tcp_ssl_free: %d\n", item->fd); + mbedtls_ssl_free(&item->ssl_ctx); + mbedtls_ssl_config_free(&item->ssl_conf); + mbedtls_ctr_drbg_free(&item->drbg_ctx); + mbedtls_entropy_free(&item->entropy_ctx); + free(item); + return 0; + } + + TCP_SSL_DEBUG("tcp_ssl_free: 4\n"); + while(item->next && item->next->tcp != tcp) + item = item->next; + + TCP_SSL_DEBUG("tcp_ssl_free: 5\n"); + if(item->next == NULL){ + return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;//item not found + } + TCP_SSL_DEBUG("tcp_ssl_free: 6\n"); + tcp_ssl_t * i = item->next; + item->next = i->next; + if(i->tcp_pbuf != NULL){ + pbuf_free(i->tcp_pbuf); + } + TCP_SSL_DEBUG("tcp_ssl_free: %d\n", i->fd); + mbedtls_ssl_free(&i->ssl_ctx); + mbedtls_ssl_config_free(&i->ssl_conf); + mbedtls_ctr_drbg_free(&i->drbg_ctx); + mbedtls_entropy_free(&i->entropy_ctx); + free(i); + + return 0; +} + +bool tcp_ssl_has(struct tcp_pcb *tcp) { + return tcp_ssl_get(tcp) != NULL; +} + +void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg) { + tcp_ssl_t * item = tcp_ssl_get(tcp); + if(item) { + item->arg = arg; + } +} + +void tcp_ssl_data(struct tcp_pcb *tcp, tcp_ssl_data_cb_t arg){ + tcp_ssl_t * item = tcp_ssl_get(tcp); + if(item) { + item->on_data = arg; + } +} + +void tcp_ssl_handshake(struct tcp_pcb *tcp, tcp_ssl_handshake_cb_t arg){ + tcp_ssl_t * item = tcp_ssl_get(tcp); + if(item) { + item->on_handshake = arg; + } +} + +void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg){ + tcp_ssl_t * item = tcp_ssl_get(tcp); + if(item) { + item->on_error = arg; + } +} diff --git a/src/tcp_mbedtls.h b/src/tcp_mbedtls.h new file mode 100644 index 00000000..20d1504a --- /dev/null +++ b/src/tcp_mbedtls.h @@ -0,0 +1,46 @@ +#ifndef LWIPR_MBEDTLS_H +#define LWIPR_MBEDTLS_H + +#include "mbedtls/platform.h" +#include "mbedtls/net.h" +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ERR_TCP_SSL_INVALID_SSL -101 +#define ERR_TCP_SSL_INVALID_TCP -102 +#define ERR_TCP_SSL_INVALID_CLIENTFD -103 +#define ERR_TCP_SSL_INVALID_CLIENTFD_DATA -104 +#define ERR_TCP_SSL_INVALID_DATA -105 + +struct tcp_pcb; +struct pbuf; +struct tcp_ssl_pcb; + +typedef void (* tcp_ssl_data_cb_t)(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len); +typedef void (* tcp_ssl_handshake_cb_t)(void *arg, struct tcp_pcb *tcp, struct tcp_ssl_pcb* ssl); +typedef void (* tcp_ssl_error_cb_t)(void *arg, struct tcp_pcb *tcp, int8_t error); + +uint8_t tcp_ssl_has_client(); +int tcp_ssl_new_client(struct tcp_pcb *tcp); +int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len); +int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p); +int tcp_ssl_free(struct tcp_pcb *tcp); +bool tcp_ssl_has(struct tcp_pcb *tcp); +void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg); +void tcp_ssl_data(struct tcp_pcb *tcp, tcp_ssl_data_cb_t arg); +void tcp_ssl_handshake(struct tcp_pcb *tcp, tcp_ssl_handshake_cb_t arg); +void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg); + +#ifdef __cplusplus +} +#endif + + +#endif // LWIPR_MBEDTLS_H From d4257e6af75aff8a778411afd4c02133048ca8d5 Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Thu, 25 Oct 2018 12:42:33 +0200 Subject: [PATCH 02/19] improved TLS support, removed some not needed debug statements. --- src/AsyncTCP.cpp | 38 +++--- src/AsyncTCP.h | 3 +- src/tcp_mbedtls.c | 300 +++++++++++++++++++++++++--------------------- src/tcp_mbedtls.h | 3 +- 4 files changed, 185 insertions(+), 159 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 3e1ede9d..9b57063a 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -215,7 +215,6 @@ static int8_t _tcp_poll(void * arg, struct tcp_pcb * pcb) { } static int8_t _tcp_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { - log_i("_tcp_recv"); lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); e->event = LWIP_TCP_RECV; e->arg = arg; @@ -229,7 +228,6 @@ static int8_t _tcp_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_ } static int8_t _tcp_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { - log_e("_tcp_sent"); lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); e->event = LWIP_TCP_SENT; e->arg = arg; @@ -520,7 +518,6 @@ AsyncClient& AsyncClient::operator=(const AsyncClient& other){ int8_t AsyncClient::_connected(void* pcb, int8_t err){ _pcb = reinterpret_cast(pcb); - log_i("error: %d", err); if(_pcb){ _rx_last_packet = millis(); _pcb_busy = false; @@ -529,12 +526,11 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){ tcp_poll(_pcb, &_tcp_poll, 1); if(_pcb_secure){ - tcp_ssl_arg(_pcb, this); - log_e("_pcb: 0x%x", _pcb); - if(tcp_ssl_new_client(_pcb) < 0){ + if(tcp_ssl_new_client(_pcb, _hostname.empty() ? NULL : _hostname.c_str()) < 0){ + log_e("closing...."); return _close(); } - + tcp_ssl_arg(_pcb, this); tcp_ssl_data(_pcb, &_s_data); tcp_ssl_handshake(_pcb, &_s_handshake); @@ -550,6 +546,7 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){ int8_t AsyncClient::_close(){ int8_t err = ERR_OK; + if(_pcb) { if(_pcb_secure){ tcp_ssl_free(_pcb); @@ -597,7 +594,6 @@ void AsyncClient::_ssl_error(int8_t err){ } int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { - log_e("_sent"); if (_pcb_secure && !_handshake_done) return ERR_OK; @@ -611,7 +607,6 @@ int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { } int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { - log_e("_recv"); if(!_pcb || pcb != _pcb){ log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); if(pb){ @@ -689,6 +684,13 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ _close(); return ERR_OK; } + // if(!_handshake_done) { + // _in_lwip_thread = true; + // tcp_ssl_handshake_step(pcb); + // _in_lwip_thread = false; + + // return ERR_OK; + // } // Everything is fine if(_poll_cb) _poll_cb(_poll_cb_arg, this); @@ -697,6 +699,9 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ void AsyncClient::_dns_found(struct ip_addr *ipaddr){ _in_lwip_thread = true; + Serial.print("ip: "); + Serial.println(ipaddr_ntoa(ipaddr)); + if(ipaddr){ connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port, _pcb_secure); } else { @@ -716,19 +721,15 @@ bool AsyncClient::operator==(const AsyncClient &other) { bool AsyncClient::connect(const char* host, uint16_t port, bool secure){ ip_addr_t addr; - Serial.print("connect ip: "); - Serial.println(secure); - err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_s_dns_found, this); if(err == ERR_OK) { - Serial.print("connect a ip: "); - Serial.println(secure); + // @ToDo: do this at one place. + _hostname = std::string(host); return connect(IPAddress(addr.u_addr.ip4.addr), port, secure); } else if(err == ERR_INPROGRESS) { - - Serial.print("connect b ip: "); - Serial.println(secure); + // @ToDo: do this at one place. + _hostname = std::string(host); _connect_port = port; _pcb_secure = secure; @@ -811,6 +812,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { //_tx_unacked_len += sent; return sent; } + log_i("add: tcp_ssl_write: %d", sent); _close(); return 0; } @@ -1041,8 +1043,6 @@ void AsyncClient::onPoll(AcConnectHandler cb, void* arg){ _poll_cb_arg = arg; } - -// void AsyncClient::_s_dns_found(const char * name, ip_addr_t * ipaddr, void * arg){ void AsyncClient::_s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg){ if(arg){ reinterpret_cast(arg)->_dns_found(ipaddr); diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index b8a417fd..b68731f0 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -50,7 +50,8 @@ struct ip_addr; class AsyncClient { protected: tcp_pcb* _pcb; - // sslclient_context* _ssl_context; + // char* _hostname; + std::string _hostname; AcConnectHandler _connect_cb; void* _connect_cb_arg; diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index db9db212..bd06a6b6 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -1,9 +1,17 @@ +#define DEBUG true +#define CONFIG_MBEDTLS_DEBUG true +#define DEBUG_LEVEL 4 + #include "tcp_mbedtls.h" #include "lwip/tcp.h" #include "mbedtls/debug.h" +#include "mbedtls/esp_debug.h" #include -#define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) +#include "mbedtls/debug.h" + +// #define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) +#define TCP_SSL_DEBUG(...) static const char pers[] = "esp32-tls"; @@ -21,6 +29,49 @@ static int handle_error(int err) return err; } +static void my_debug(void *ctx, int level, const char *file, int line, + const char *str) + { + const char *p, *basename; + (void) ctx; + + /* Extract basename from file */ + for(p = basename = file; *p != '\0'; p++) { + if(*p == '/' || *p == '\\') { + basename = p + 1; + } + } + + mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); + } + + /** + * Certificate verification callback for mbed TLS + * Here we only use it to display information on each cert in the chain + */ + static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) + { + const uint32_t buf_size = 1024; + //char *buf = new char[buf_size]; + char buf[buf_size]; + (void) data; + + mbedtls_printf("\nVerifying certificate at depth %d:\n", depth); + mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt); + mbedtls_printf("%s", buf); + + if (*flags == 0) + mbedtls_printf("No verification issue for this certificate\n"); + else + { + mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags); + mbedtls_printf("%s\n", buf); + } + + //delete[] buf; + return 0; + } + static uint8_t _tcp_ssl_has_client = 0; struct tcp_ssl_pcb { @@ -36,7 +87,7 @@ struct tcp_ssl_pcb { tcp_ssl_data_cb_t on_data; tcp_ssl_handshake_cb_t on_handshake; tcp_ssl_error_cb_t on_error; - int last_wr; + size_t last_wr; struct pbuf *tcp_pbuf; int pbuf_offset; struct tcp_ssl_pcb* next; @@ -48,20 +99,23 @@ static tcp_ssl_t * tcp_ssl_array = NULL; static int tcp_ssl_next_fd = 0; int tcp_ssl_recv(void *ctx, unsigned char *buf, size_t len) { - tcp_ssl_t *fd_data = (tcp_ssl_t*)ctx; + tcp_ssl_t *tcp_ssl = (tcp_ssl_t*)ctx; uint8_t *read_buf = NULL; uint8_t *pread_buf = NULL; u16_t recv_len = 0; - if(fd_data->tcp_pbuf == NULL || fd_data->tcp_pbuf->tot_len == 0) { - return 0; + TCP_SSL_DEBUG("tcp_ssl_recv: ctx: 0x%X, buf: 0x%X, len: %d\n", ctx, buf, len); + + if(tcp_ssl->tcp_pbuf == NULL || tcp_ssl->tcp_pbuf->tot_len == 0) { + TCP_SSL_DEBUG("tcp_ssl_recv: not yet ready to read: tcp_pbuf: 0x%X.\n", tcp_ssl->tcp_pbuf); + return MBEDTLS_ERR_SSL_WANT_READ; } - read_buf =(uint8_t*)calloc(fd_data->tcp_pbuf->len + 1, sizeof(uint8_t)); + read_buf =(uint8_t*)calloc(tcp_ssl->tcp_pbuf->len + 1, sizeof(uint8_t)); pread_buf = read_buf; if (pread_buf != NULL){ - recv_len = pbuf_copy_partial(fd_data->tcp_pbuf, read_buf, len, fd_data->pbuf_offset); - fd_data->pbuf_offset += recv_len; + recv_len = pbuf_copy_partial(tcp_ssl->tcp_pbuf, read_buf, len, tcp_ssl->pbuf_offset); + tcp_ssl->pbuf_offset += recv_len; } if (recv_len != 0) { @@ -78,7 +132,9 @@ int tcp_ssl_recv(void *ctx, unsigned char *buf, size_t len) { return recv_len; } -int tcp_ssl_send(void *ctx, const unsigned char *buf, size_t size) { +int tcp_ssl_send(void *ctx, const unsigned char *buf, size_t len) { + TCP_SSL_DEBUG("tcp_ssl_send: ctx: 0x%X, buf: 0x%X, len: %d\n", ctx, buf, len); + if(ctx == NULL) { TCP_SSL_DEBUG("tcp_ssl_send: no context set\n"); return -1; @@ -89,19 +145,44 @@ int tcp_ssl_send(void *ctx, const unsigned char *buf, size_t size) { return -1; } - tcp_ssl_t *tcp = (tcp_ssl_t*)ctx; - - size_t room = tcp_sndbuf(tcp->tcp); - size_t will_send = (room < size) ? room : size; + tcp_ssl_t *tcp_ssl = (tcp_ssl_t*)ctx; + size_t tcp_len = 0; + int err = ERR_OK; - TCP_SSL_DEBUG("len: %d, has space? %d\n", size, room); + if (tcp_sndbuf(tcp_ssl->tcp) < len) { + tcp_len = tcp_sndbuf(tcp_ssl->tcp); + if(tcp_len == 0) { + TCP_SSL_DEBUG("ax_port_write: tcp_sndbuf is zero: %d\n", len); + return ERR_MEM; + } + } else { + tcp_len = len; + } + + if (tcp_len > 2 * tcp_ssl->tcp->mss) { + tcp_len = 2 * tcp_ssl->tcp->mss; + } - int8_t ret = tcp_write(tcp->tcp, buf, will_send, 0); - if(ret == ERR_OK) { - TCP_SSL_DEBUG("oki!\n"); + err = tcp_write(tcp_ssl->tcp, buf, tcp_len, TCP_WRITE_FLAG_COPY); + if(err < ERR_OK) { + if (err == ERR_MEM) { + TCP_SSL_DEBUG("ax_port_write: No memory %d (%d)\n", tcp_len, len); + return err; + } + TCP_SSL_DEBUG("ax_port_write: tcp_write error: %d\n", err); + return err; + } else if (err == ERR_OK) { + //TCP_SSL_DEBUG("ax_port_write: tcp_output: %d / %d\n", tcp_len, len); + err = tcp_output(tcp_ssl->tcp); + if(err != ERR_OK) { + TCP_SSL_DEBUG("ax_port_write: tcp_output err: %d\n", err); + return err; + } } - return will_send; + tcp_ssl->last_wr += tcp_len; + + return tcp_len; } uint8_t tcp_ssl_has_client() { @@ -128,9 +209,7 @@ tcp_ssl_t * tcp_ssl_new(struct tcp_pcb *tcp) { new_item->tcp_pbuf = NULL; new_item->pbuf_offset = 0; new_item->next = NULL; - // new_item->ssl_ctx = NULL; - // new_item->ssl = NULL; - new_item->fd = tcp_ssl_next_fd++; + // new_item->fd = tcp_ssl_next_fd++; if(tcp_ssl_array == NULL){ tcp_ssl_array = new_item; @@ -141,7 +220,6 @@ tcp_ssl_t * tcp_ssl_new(struct tcp_pcb *tcp) { item->next = new_item; } - TCP_SSL_DEBUG("tcp_ssl_new: %d: 0x%x\n", new_item->fd, tcp); return new_item; } @@ -156,7 +234,7 @@ tcp_ssl_t* tcp_ssl_get(struct tcp_pcb *tcp) { return item; } -int tcp_ssl_new_client(struct tcp_pcb *tcp) { +int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname) { tcp_ssl_t* tcp_ssl; TCP_SSL_DEBUG("tcp_ssl_new_client\n"); @@ -166,7 +244,6 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp) { } if(tcp_ssl_get(tcp) != NULL){ - TCP_SSL_DEBUG("tcp_ssl_new_client: tcp_ssl already exists\n"); return -1; } @@ -175,7 +252,6 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp) { return -1; } - // mbedtls_entropy_init(&tcp_ssl->entropy_ctx); mbedtls_ctr_drbg_init(&tcp_ssl->drbg_ctx); mbedtls_ssl_init(&tcp_ssl->ssl_ctx); @@ -190,42 +266,50 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp) { MBEDTLS_SSL_PRESET_DEFAULT)) { TCP_SSL_DEBUG("error setting SSL config.\n"); - // tcp_ssl_free(tcp); + tcp_ssl_free(tcp); return -1; } + // @ToDo: allow setting a root CA, for now just not verify. mbedtls_ssl_conf_authmode(&tcp_ssl->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); + // mbedtls_ssl_conf_authmode(&tcp_ssl->ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL); + int ret = 0; - // @ToDo: there's no hostname at this stage, set it later. - // if((ret = mbedtls_ssl_set_hostname(&ctx->ssl_ctx, host)) != 0){ - // return handle_error(ret); - // } + // @ToDo: required? + if(hostname != NULL) { + TCP_SSL_DEBUG("setting the hostname: %s\n", hostname); + if((ret = mbedtls_ssl_set_hostname(&tcp_ssl->ssl_ctx, hostname)) != 0){ + tcp_ssl_free(tcp); + + return handle_error(ret); + } + } mbedtls_ssl_conf_rng(&tcp_ssl->ssl_conf, mbedtls_ctr_drbg_random, &tcp_ssl->drbg_ctx); + mbedtls_ssl_conf_verify(&tcp_ssl->ssl_conf, my_verify, NULL); + mbedtls_ssl_conf_dbg(&tcp_ssl->ssl_conf, my_debug, NULL); + //mbedtls_debug_set_threshold(2); + if ((ret = mbedtls_ssl_setup(&tcp_ssl->ssl_ctx, &tcp_ssl->ssl_conf)) != 0) { - // tcp_ssl_free(tcp); + tcp_ssl_free(tcp); + return handle_error(ret); } - // mbedtls_ssl_set_bio(&tcp_ssl->ssl_ctx, (void*)tcp_ssl, tcp_ssl_send, tcp_ssl_recv, NULL ); mbedtls_ssl_set_bio(&tcp_ssl->ssl_ctx, (void*)tcp_ssl, tcp_ssl_send, tcp_ssl_recv, NULL); // mbedtls_ssl_set_bio(&tcp_ssl->ssl_ctx, &tcp_ssl->fd, mbedtls_net_send, mbedtls_net_recv, NULL ); - // @ToDo: do we need this here? + // Start handshake. ret = mbedtls_ssl_handshake(&tcp_ssl->ssl_ctx); - handle_error(ret); - TCP_SSL_DEBUG("ret mbedtls_ssl_handshake: %d, want read: %d, write: %d\n", ret, MBEDTLS_ERR_SSL_WANT_READ, MBEDTLS_ERR_SSL_WANT_WRITE); - // if (ret != 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - // TCP_SSL_DEBUG("tcp_ssl_new_client: mbedtls_ssl_handshake: %d.\n", ret); - // // if(tcp_ssl->on_error) - // // tcp_ssl->on_error(tcp_ssl->arg, tcp_ssl->tcp, ret); - // } - - TCP_SSL_DEBUG("end tcp_ssl_new_client %d.\n", tcp_ssl->fd); + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + TCP_SSL_DEBUG("handshake error!\n"); + return handle_error(ret); + } - return tcp_ssl->fd; + // @ToDo: don't need the fd? + return ERR_OK; } int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) { @@ -235,7 +319,7 @@ int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) { tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp); - TCP_SSL_DEBUG("tcp_ssl_write %x\n, state: %d\n", tcp_ssl, tcp->state); + TCP_SSL_DEBUG("tcp_ssl_write %x, state: %d\n", tcp_ssl, tcp->state); if(tcp_ssl == NULL){ TCP_SSL_DEBUG("tcp_ssl_write: tcp_ssl is NULL\n"); @@ -250,10 +334,13 @@ int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) { TCP_SSL_DEBUG("tcp_ssl_write: %u -> %d (%d)\r\n", len, tcp_ssl->last_wr, rc); if (rc < 0){ - // @ToDO: ??? - // if(rc != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + if (rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE) { + TCP_SSL_DEBUG("about to call mbedtls_ssl_write\n"); + return handle_error(rc); + } + if(rc != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { TCP_SSL_DEBUG("tcp_ssl_write error: %d\r\n", rc); - // } + } return rc; } @@ -266,14 +353,15 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { if(tcp == NULL) { return -1; } - tcp_ssl_t* fd_data = NULL; + tcp_ssl_t* tcp_ssl = NULL; int read_bytes = 0; int total_bytes = 0; - uint8_t *read_buf; + static const size_t read_buf_size = 1024; + uint8_t read_buf[read_buf_size]; - fd_data = tcp_ssl_get(tcp); - if(fd_data == NULL) { + tcp_ssl = tcp_ssl_get(tcp); + if(tcp_ssl == NULL) { TCP_SSL_DEBUG("tcp_ssl_read: tcp_ssl is NULL\n"); return ERR_TCP_SSL_INVALID_CLIENTFD_DATA; } @@ -285,103 +373,47 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { TCP_SSL_DEBUG("READY TO READ SOME DATA\n"); - fd_data->tcp_pbuf = p; - fd_data->pbuf_offset = 0; - - do { - if(fd_data->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER) { - TCP_SSL_DEBUG("start handshake: %d\n", fd_data->ssl_ctx.state); - int ret = mbedtls_ssl_handshake(&fd_data->ssl_ctx); + tcp_ssl->tcp_pbuf = p; + tcp_ssl->pbuf_offset = 0; + + do { + if(tcp_ssl->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + TCP_SSL_DEBUG("start handshake: %d\n", tcp_ssl->ssl_ctx.state); + int ret = mbedtls_ssl_handshake(&tcp_ssl->ssl_ctx); + handle_error(ret); if(ret == 0) { - if(fd_data->on_handshake) - fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data); + TCP_SSL_DEBUG("Protocol is %s Ciphersuite is %s\n", mbedtls_ssl_get_version(&tcp_ssl->ssl_ctx), mbedtls_ssl_get_ciphersuite(&tcp_ssl->ssl_ctx)); + + if(tcp_ssl->on_handshake) + tcp_ssl->on_handshake(tcp_ssl->arg, tcp_ssl->tcp, tcp_ssl); } else if(ret != MBEDTLS_ERR_SSL_WANT_READ || ret != MBEDTLS_ERR_SSL_WANT_WRITE) { // if(fd_data->on_error) // fd_data->on_error(fd_data->arg, fd_data->tcp, ret); - TCP_SSL_DEBUG("handshake error: %d\n", ret); // return ret; - //return 0; + return 0; } } else { - uint8_t readb[1024]; - read_bytes = mbedtls_ssl_read(&fd_data->ssl_ctx, &readb, 1024); - TCP_SSL_DEBUG("start read: %d.\n", read_bytes); - if(read_bytes < 0) { - handle_error(read_bytes); + read_bytes = mbedtls_ssl_read(&tcp_ssl->ssl_ctx, &read_buf, read_buf_size); + TCP_SSL_DEBUG("tcp_ssl_read: read_bytes: %d\n", read_bytes); + if(read_bytes < 0) { // SSL_OK + // MBEDTLS_ERR_SSL_CONN_EOF if(read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes); } total_bytes = read_bytes; break; - } else if(read_bytes > 0) { - if(fd_data->on_data){ - fd_data->on_data(fd_data->arg, tcp, &readb, read_bytes); + } else if(read_bytes > 0){ + if(tcp_ssl->on_data){ + tcp_ssl->on_data(tcp_ssl->arg, tcp, read_buf, read_bytes); } total_bytes+= read_bytes; } } - // if(fd_data->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER) { - // TCP_SSL_DEBUG("start handshake.\n"); - // int ret = mbedtls_ssl_handshake(&fd_data->ssl_ctx); - // if(ret == 0) { - // if(fd_data->on_handshake) - // fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data); - // } else if(ret != MBEDTLS_ERR_SSL_WANT_READ || ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - // if(fd_data->on_error) - // fd_data->on_error(fd_data->arg, fd_data->tcp, ret); - // return ret; - // } - // } - // // @TODO: FIX! - // read_bytes = mbedtls_ssl_read(&fd_data->ssl_ctx, &read_buf, 0); - // TCP_SSL_DEBUG("tcp_ssl_ssl_read: read_bytes: %d (%d)\n", read_bytes, MBEDTLS_SSL_HANDSHAKE_OVER); - // if(read_bytes < 0) { - // handle_error(read_bytes); - // if(read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - // TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes); - // } - // total_bytes = read_bytes; - // break; - // } else if(read_bytes > 0){ - // if(fd_data->on_data){ - // fd_data->on_data(fd_data->arg, tcp, read_buf, read_bytes); - // } - // total_bytes+= read_bytes; - // } else { - // TCP_SSL_DEBUG("start handshake? %d.\n", fd_data->ssl_ctx.state); - // if(fd_data->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER) { - // TCP_SSL_DEBUG("start handshake.\n"); - // int ret = mbedtls_ssl_handshake(&fd_data->ssl_ctx); - // if(ret == 0) { - // if(fd_data->on_handshake) - // fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data); - // } else if(ret != MBEDTLS_ERR_SSL_WANT_READ || ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - // if(fd_data->on_error) - // fd_data->on_error(fd_data->arg, fd_data->tcp, ret); - // return ret; - // } - // } - // } - } while (p->tot_len - fd_data->pbuf_offset > 0); - - // OLD - // if(fd_data->handshake != MBEDTLS_SSL_HANDSHAKE_OVER) { - // fd_data->handshake = mbedtls_ssl_handshake(&fd_data->ssl_ctx); - // if(fd_data->handshake == 0){ - // TCP_SSL_DEBUG("tcp_ssl_read: handshake OK\n"); - // if(fd_data->on_handshake) - // fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data); - // } else if(fd_data->handshake != 0){ - // TCP_SSL_DEBUG("tcp_ssl_read: handshake error: %d\n", fd_data->handshake); - // if(fd_data->on_error) - // fd_data->on_error(fd_data->arg, fd_data->tcp, fd_data->handshake); - // return fd_data->handshake; - // } - // } + } while (p->tot_len - tcp_ssl->pbuf_offset > 0); tcp_recved(tcp, p->tot_len); - fd_data->tcp_pbuf = NULL; + tcp_ssl->tcp_pbuf = NULL; pbuf_free(p); TCP_SSL_DEBUG("tcp_ssl_read: eof: %d\n", total_bytes); @@ -390,20 +422,16 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { } int tcp_ssl_free(struct tcp_pcb *tcp) { - TCP_SSL_DEBUG("tcp_ssl_free: 1\n"); if(tcp == NULL) { return -1; } - TCP_SSL_DEBUG("tcp_ssl_free: 2\n"); tcp_ssl_t * item = tcp_ssl_array; - TCP_SSL_DEBUG("tcp_ssl_free: 2a 0x%x\n", item); if(item->tcp == tcp){ - TCP_SSL_DEBUG("tcp_ssl_free: 3\n"); tcp_ssl_array = tcp_ssl_array->next; if(item->tcp_pbuf != NULL) { pbuf_free(item->tcp_pbuf); } - TCP_SSL_DEBUG("tcp_ssl_free: %d\n", item->fd); + TCP_SSL_DEBUG("tcp_ssl_free: %x\n", item); mbedtls_ssl_free(&item->ssl_ctx); mbedtls_ssl_config_free(&item->ssl_conf); mbedtls_ctr_drbg_free(&item->drbg_ctx); @@ -412,21 +440,17 @@ int tcp_ssl_free(struct tcp_pcb *tcp) { return 0; } - TCP_SSL_DEBUG("tcp_ssl_free: 4\n"); while(item->next && item->next->tcp != tcp) item = item->next; - TCP_SSL_DEBUG("tcp_ssl_free: 5\n"); if(item->next == NULL){ return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;//item not found } - TCP_SSL_DEBUG("tcp_ssl_free: 6\n"); tcp_ssl_t * i = item->next; item->next = i->next; if(i->tcp_pbuf != NULL){ pbuf_free(i->tcp_pbuf); } - TCP_SSL_DEBUG("tcp_ssl_free: %d\n", i->fd); mbedtls_ssl_free(&i->ssl_ctx); mbedtls_ssl_config_free(&i->ssl_conf); mbedtls_ctr_drbg_free(&i->drbg_ctx); diff --git a/src/tcp_mbedtls.h b/src/tcp_mbedtls.h index 20d1504a..b9503319 100644 --- a/src/tcp_mbedtls.h +++ b/src/tcp_mbedtls.h @@ -28,9 +28,10 @@ typedef void (* tcp_ssl_handshake_cb_t)(void *arg, struct tcp_pcb *tcp, struct t typedef void (* tcp_ssl_error_cb_t)(void *arg, struct tcp_pcb *tcp, int8_t error); uint8_t tcp_ssl_has_client(); -int tcp_ssl_new_client(struct tcp_pcb *tcp); +int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname); int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len); int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p); +int tcp_ssl_handshake_step(struct tcp_pcb *tcp); int tcp_ssl_free(struct tcp_pcb *tcp); bool tcp_ssl_has(struct tcp_pcb *tcp); void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg); From eeff609d2debfadf930bca388e15ccdb387a7c0f Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Thu, 25 Oct 2018 16:13:38 +0200 Subject: [PATCH 03/19] removed some more logging. --- src/AsyncTCP.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 9b57063a..1fc31f08 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -1099,7 +1099,6 @@ int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ } void AsyncClient::_s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len){ - log_i("_s_data"); AsyncClient *c = reinterpret_cast(arg); if(c->_recv_cb) c->_recv_cb(c->_recv_cb_arg, c, data, len); @@ -1107,7 +1106,6 @@ void AsyncClient::_s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t void AsyncClient::_s_handshake(void *arg, struct tcp_pcb *tcp, struct tcp_ssl_pcb* ssl){ AsyncClient *c = reinterpret_cast(arg); - log_i("_s_handshake: done!"); c->_handshake_done = true; if(c->_connect_cb) c->_connect_cb(c->_connect_cb_arg, c); From f2127a087eb7e58e0c7cd02b773b610b5664691d Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Mon, 5 Nov 2018 22:18:27 +0100 Subject: [PATCH 04/19] getting there, seems to start working, there are still some issues with the handshake failing. --- src/AsyncTCP.h | 1 - src/tcp_mbedtls.c | 20 +++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index b68731f0..ccbc9df4 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -50,7 +50,6 @@ struct ip_addr; class AsyncClient { protected: tcp_pcb* _pcb; - // char* _hostname; std::string _hostname; AcConnectHandler _connect_cb; diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index bd06a6b6..a8910f6d 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -116,6 +116,8 @@ int tcp_ssl_recv(void *ctx, unsigned char *buf, size_t len) { if (pread_buf != NULL){ recv_len = pbuf_copy_partial(tcp_ssl->tcp_pbuf, read_buf, len, tcp_ssl->pbuf_offset); tcp_ssl->pbuf_offset += recv_len; + + TCP_SSL_DEBUG("tcp_ssl_recv: recv_len: %d, pbuf_offset: %d.\n", recv_len, tcp_ssl->pbuf_offset); } if (recv_len != 0) { @@ -129,6 +131,10 @@ int tcp_ssl_recv(void *ctx, unsigned char *buf, size_t len) { free(pread_buf); pread_buf = NULL; + if(recv_len == 0) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + return recv_len; } @@ -290,7 +296,7 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname) { mbedtls_ssl_conf_verify(&tcp_ssl->ssl_conf, my_verify, NULL); mbedtls_ssl_conf_dbg(&tcp_ssl->ssl_conf, my_debug, NULL); - //mbedtls_debug_set_threshold(2); + // mbedtls_debug_set_threshold(2); if ((ret = mbedtls_ssl_setup(&tcp_ssl->ssl_ctx, &tcp_ssl->ssl_conf)) != 0) { tcp_ssl_free(tcp); @@ -308,7 +314,6 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname) { return handle_error(ret); } - // @ToDo: don't need the fd? return ERR_OK; } @@ -386,12 +391,13 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { if(tcp_ssl->on_handshake) tcp_ssl->on_handshake(tcp_ssl->arg, tcp_ssl->tcp, tcp_ssl); - } else if(ret != MBEDTLS_ERR_SSL_WANT_READ || ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - // if(fd_data->on_error) - // fd_data->on_error(fd_data->arg, fd_data->tcp, ret); + } else if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { TCP_SSL_DEBUG("handshake error: %d\n", ret); - // return ret; - return 0; + + if(tcp_ssl->on_error) + tcp_ssl->on_error(tcp_ssl->arg, tcp_ssl->tcp, ret); + + return ret; } } else { read_bytes = mbedtls_ssl_read(&tcp_ssl->ssl_ctx, &read_buf, read_buf_size); From 3c9fbd96de2c85f4909bede2a2f62b56c22ea954 Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Tue, 20 Nov 2018 12:00:19 +0100 Subject: [PATCH 05/19] add fix for reading larger amounts of data. --- src/AsyncTCP.cpp | 20 ++++----- src/tcp_mbedtls.c | 103 +++++++++++++++++++++------------------------- 2 files changed, 55 insertions(+), 68 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 1fc31f08..483b0778 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -626,11 +626,12 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { // log_i("_recv: %d\n", pb->tot_len); int read_bytes = tcp_ssl_read(pcb, pb); if(read_bytes < 0){ - if (read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - log_e("_recv err: %d\n", read_bytes); - _close(); - } - //return read_bytes; + if (read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + log_e("_recv err: %d\n", read_bytes); + _close(); + } + + //return read_bytes; } return ERR_OK; } @@ -684,13 +685,6 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ _close(); return ERR_OK; } - // if(!_handshake_done) { - // _in_lwip_thread = true; - // tcp_ssl_handshake_step(pcb); - // _in_lwip_thread = false; - - // return ERR_OK; - // } // Everything is fine if(_poll_cb) _poll_cb(_poll_cb_arg, this); @@ -812,7 +806,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { //_tx_unacked_len += sent; return sent; } - log_i("add: tcp_ssl_write: %d", sent); + //log_i("add: tcp_ssl_write: %d", sent); _close(); return 0; } diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index a8910f6d..2fe306b4 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -7,7 +7,6 @@ #include "mbedtls/debug.h" #include "mbedtls/esp_debug.h" #include - #include "mbedtls/debug.h" // #define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) @@ -15,8 +14,7 @@ static const char pers[] = "esp32-tls"; -static int handle_error(int err) -{ +static int handle_error(int err) { if(err == -30848){ return err; } @@ -29,48 +27,45 @@ static int handle_error(int err) return err; } -static void my_debug(void *ctx, int level, const char *file, int line, - const char *str) +// static void my_debug(void *ctx, int level, const char *file, int line, const char *str) { +// const char *p, *basename; +// (void) ctx; + +// /* Extract basename from file */ +// for(p = basename = file; *p != '\0'; p++) { +// if(*p == '/' || *p == '\\') { +// basename = p + 1; +// } +// } + +// mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); +// } + +/** + * Certificate verification callback for mbed TLS + * Here we only use it to display information on each cert in the chain + */ +static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { + const uint32_t buf_size = 1024; + //char *buf = new char[buf_size]; + char buf[buf_size]; + (void) data; + + mbedtls_printf("\nVerifying certificate at depth %d:\n", depth); + mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt); + mbedtls_printf("%s", buf); + + if (*flags == 0) + mbedtls_printf("No verification issue for this certificate\n"); + else { - const char *p, *basename; - (void) ctx; - - /* Extract basename from file */ - for(p = basename = file; *p != '\0'; p++) { - if(*p == '/' || *p == '\\') { - basename = p + 1; - } - } - - mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); + mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags); + mbedtls_printf("%s\n", buf); } - /** - * Certificate verification callback for mbed TLS - * Here we only use it to display information on each cert in the chain - */ - static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) - { - const uint32_t buf_size = 1024; - //char *buf = new char[buf_size]; - char buf[buf_size]; - (void) data; - - mbedtls_printf("\nVerifying certificate at depth %d:\n", depth); - mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt); - mbedtls_printf("%s", buf); - - if (*flags == 0) - mbedtls_printf("No verification issue for this certificate\n"); - else - { - mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags); - mbedtls_printf("%s\n", buf); - } - - //delete[] buf; - return 0; - } + //delete[] buf; + return 0; +} static uint8_t _tcp_ssl_has_client = 0; @@ -104,8 +99,6 @@ int tcp_ssl_recv(void *ctx, unsigned char *buf, size_t len) { uint8_t *pread_buf = NULL; u16_t recv_len = 0; - TCP_SSL_DEBUG("tcp_ssl_recv: ctx: 0x%X, buf: 0x%X, len: %d\n", ctx, buf, len); - if(tcp_ssl->tcp_pbuf == NULL || tcp_ssl->tcp_pbuf->tot_len == 0) { TCP_SSL_DEBUG("tcp_ssl_recv: not yet ready to read: tcp_pbuf: 0x%X.\n", tcp_ssl->tcp_pbuf); return MBEDTLS_ERR_SSL_WANT_READ; @@ -115,11 +108,11 @@ int tcp_ssl_recv(void *ctx, unsigned char *buf, size_t len) { pread_buf = read_buf; if (pread_buf != NULL){ recv_len = pbuf_copy_partial(tcp_ssl->tcp_pbuf, read_buf, len, tcp_ssl->pbuf_offset); + TCP_SSL_DEBUG("tcp_ssl_recv: len: %d, recv_len: %d, pbuf_offset: %d, tcp_pbuf len: %d.\n", len, recv_len, tcp_ssl->pbuf_offset, tcp_ssl->tcp_pbuf->len); tcp_ssl->pbuf_offset += recv_len; - - TCP_SSL_DEBUG("tcp_ssl_recv: recv_len: %d, pbuf_offset: %d.\n", recv_len, tcp_ssl->pbuf_offset); } + // Note: why copy again? if (recv_len != 0) { memcpy(buf, read_buf, recv_len); } @@ -295,7 +288,7 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname) { mbedtls_ssl_conf_rng(&tcp_ssl->ssl_conf, mbedtls_ctr_drbg_random, &tcp_ssl->drbg_ctx); mbedtls_ssl_conf_verify(&tcp_ssl->ssl_conf, my_verify, NULL); - mbedtls_ssl_conf_dbg(&tcp_ssl->ssl_conf, my_debug, NULL); + // mbedtls_ssl_conf_dbg(&tcp_ssl->ssl_conf, my_debug, NULL); // mbedtls_debug_set_threshold(2); if ((ret = mbedtls_ssl_setup(&tcp_ssl->ssl_ctx, &tcp_ssl->ssl_conf)) != 0) { @@ -324,8 +317,6 @@ int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) { tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp); - TCP_SSL_DEBUG("tcp_ssl_write %x, state: %d\n", tcp_ssl, tcp->state); - if(tcp_ssl == NULL){ TCP_SSL_DEBUG("tcp_ssl_write: tcp_ssl is NULL\n"); return 0; @@ -353,8 +344,6 @@ int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) { } int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { - TCP_SSL_DEBUG("tcp_ssl_ssl_read\n"); - if(tcp == NULL) { return -1; } @@ -397,13 +386,17 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { if(tcp_ssl->on_error) tcp_ssl->on_error(tcp_ssl->arg, tcp_ssl->tcp, ret); - return ret; + break; } } else { read_bytes = mbedtls_ssl_read(&tcp_ssl->ssl_ctx, &read_buf, read_buf_size); - TCP_SSL_DEBUG("tcp_ssl_read: read_bytes: %d\n", read_bytes); + TCP_SSL_DEBUG("tcp_ssl_read: read_bytes: %d, total_bytes: %d, tot_len: %d, pbuf_offset: %d\r\n", read_bytes, total_bytes, p->tot_len, tcp_ssl->pbuf_offset); + // TCP_SSL_DEBUG("tcp_ssl_read: %s<-\n", read_buf); if(read_bytes < 0) { // SSL_OK - // MBEDTLS_ERR_SSL_CONN_EOF + if(read_bytes == MBEDTLS_ERR_SSL_WANT_READ) { + TCP_SSL_DEBUG("tcp_ssl_read: need to wait\n"); + break; + } if(read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes); } @@ -416,7 +409,7 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { total_bytes+= read_bytes; } } - } while (p->tot_len - tcp_ssl->pbuf_offset > 0); + } while (p->tot_len - tcp_ssl->pbuf_offset > 0 || read_bytes > 0); tcp_recved(tcp, p->tot_len); tcp_ssl->tcp_pbuf = NULL; From d501a90b68ede0c4e054c1f5b13db4f07f7b0a41 Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Thu, 29 Nov 2018 14:36:04 +0100 Subject: [PATCH 06/19] some code clean-up --- src/tcp_mbedtls.c | 76 +++++++++++++---------------------------------- 1 file changed, 21 insertions(+), 55 deletions(-) diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index 2fe306b4..3c073123 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -27,45 +27,29 @@ static int handle_error(int err) { return err; } -// static void my_debug(void *ctx, int level, const char *file, int line, const char *str) { -// const char *p, *basename; -// (void) ctx; - -// /* Extract basename from file */ -// for(p = basename = file; *p != '\0'; p++) { -// if(*p == '/' || *p == '\\') { -// basename = p + 1; -// } -// } - -// mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); -// } - /** * Certificate verification callback for mbed TLS * Here we only use it to display information on each cert in the chain */ -static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { - const uint32_t buf_size = 1024; - //char *buf = new char[buf_size]; - char buf[buf_size]; - (void) data; - - mbedtls_printf("\nVerifying certificate at depth %d:\n", depth); - mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt); - mbedtls_printf("%s", buf); - - if (*flags == 0) - mbedtls_printf("No verification issue for this certificate\n"); - else - { - mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags); - mbedtls_printf("%s\n", buf); - } +// static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { +// const uint32_t buf_size = 1024; +// char buf[buf_size]; +// (void) data; + +// mbedtls_printf("\nVerifying certificate at depth %d:\n", depth); +// mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt); +// mbedtls_printf("%s", buf); + +// if (*flags == 0) +// mbedtls_printf("No verification issue for this certificate\n"); +// else +// { +// mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags); +// mbedtls_printf("%s\n", buf); +// } - //delete[] buf; - return 0; -} +// return 0; +// } static uint8_t _tcp_ssl_has_client = 0; @@ -208,7 +192,6 @@ tcp_ssl_t * tcp_ssl_new(struct tcp_pcb *tcp) { new_item->tcp_pbuf = NULL; new_item->pbuf_offset = 0; new_item->next = NULL; - // new_item->fd = tcp_ssl_next_fd++; if(tcp_ssl_array == NULL){ tcp_ssl_array = new_item; @@ -275,7 +258,6 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname) { int ret = 0; - // @ToDo: required? if(hostname != NULL) { TCP_SSL_DEBUG("setting the hostname: %s\n", hostname); if((ret = mbedtls_ssl_set_hostname(&tcp_ssl->ssl_ctx, hostname)) != 0){ @@ -286,10 +268,7 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname) { } mbedtls_ssl_conf_rng(&tcp_ssl->ssl_conf, mbedtls_ctr_drbg_random, &tcp_ssl->drbg_ctx); - - mbedtls_ssl_conf_verify(&tcp_ssl->ssl_conf, my_verify, NULL); - // mbedtls_ssl_conf_dbg(&tcp_ssl->ssl_conf, my_debug, NULL); - // mbedtls_debug_set_threshold(2); + // mbedtls_ssl_conf_verify(&tcp_ssl->ssl_conf, my_verify, NULL); if ((ret = mbedtls_ssl_setup(&tcp_ssl->ssl_ctx, &tcp_ssl->ssl_conf)) != 0) { tcp_ssl_free(tcp); @@ -298,7 +277,6 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname) { } mbedtls_ssl_set_bio(&tcp_ssl->ssl_ctx, (void*)tcp_ssl, tcp_ssl_send, tcp_ssl_recv, NULL); - // mbedtls_ssl_set_bio(&tcp_ssl->ssl_ctx, &tcp_ssl->fd, mbedtls_net_send, mbedtls_net_recv, NULL ); // Start handshake. ret = mbedtls_ssl_handshake(&tcp_ssl->ssl_ctx); @@ -318,17 +296,13 @@ int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) { tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp); if(tcp_ssl == NULL){ - TCP_SSL_DEBUG("tcp_ssl_write: tcp_ssl is NULL\n"); return 0; } tcp_ssl->last_wr = 0; - TCP_SSL_DEBUG("about to call mbedtls_ssl_write\n"); int rc = mbedtls_ssl_write(&tcp_ssl->ssl_ctx, data, len); - TCP_SSL_DEBUG("tcp_ssl_write: %u -> %d (%d)\r\n", len, tcp_ssl->last_wr, rc); - if (rc < 0){ if (rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE) { TCP_SSL_DEBUG("about to call mbedtls_ssl_write\n"); @@ -356,16 +330,14 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { tcp_ssl = tcp_ssl_get(tcp); if(tcp_ssl == NULL) { - TCP_SSL_DEBUG("tcp_ssl_read: tcp_ssl is NULL\n"); return ERR_TCP_SSL_INVALID_CLIENTFD_DATA; } if(p == NULL) { - TCP_SSL_DEBUG("tcp_ssl_read:p == NULL\n"); return ERR_TCP_SSL_INVALID_DATA; } - TCP_SSL_DEBUG("READY TO READ SOME DATA\n"); + // TCP_SSL_DEBUG("READY TO READ SOME DATA\n"); tcp_ssl->tcp_pbuf = p; tcp_ssl->pbuf_offset = 0; @@ -391,13 +363,10 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { } else { read_bytes = mbedtls_ssl_read(&tcp_ssl->ssl_ctx, &read_buf, read_buf_size); TCP_SSL_DEBUG("tcp_ssl_read: read_bytes: %d, total_bytes: %d, tot_len: %d, pbuf_offset: %d\r\n", read_bytes, total_bytes, p->tot_len, tcp_ssl->pbuf_offset); - // TCP_SSL_DEBUG("tcp_ssl_read: %s<-\n", read_buf); if(read_bytes < 0) { // SSL_OK if(read_bytes == MBEDTLS_ERR_SSL_WANT_READ) { - TCP_SSL_DEBUG("tcp_ssl_read: need to wait\n"); break; - } - if(read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + } else if(read_bytes != MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes); } total_bytes = read_bytes; @@ -415,8 +384,6 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { tcp_ssl->tcp_pbuf = NULL; pbuf_free(p); - TCP_SSL_DEBUG("tcp_ssl_read: eof: %d\n", total_bytes); - return total_bytes; } @@ -430,7 +397,6 @@ int tcp_ssl_free(struct tcp_pcb *tcp) { if(item->tcp_pbuf != NULL) { pbuf_free(item->tcp_pbuf); } - TCP_SSL_DEBUG("tcp_ssl_free: %x\n", item); mbedtls_ssl_free(&item->ssl_ctx); mbedtls_ssl_config_free(&item->ssl_conf); mbedtls_ctr_drbg_free(&item->drbg_ctx); From c9dd60883460869acba5c1dba1f57816bc48ed08 Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Thu, 29 Nov 2018 14:37:17 +0100 Subject: [PATCH 07/19] more code clean-up. --- src/tcp_mbedtls.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index 3c073123..4bdb723b 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -1,13 +1,8 @@ -#define DEBUG true -#define CONFIG_MBEDTLS_DEBUG true -#define DEBUG_LEVEL 4 - #include "tcp_mbedtls.h" #include "lwip/tcp.h" #include "mbedtls/debug.h" #include "mbedtls/esp_debug.h" #include -#include "mbedtls/debug.h" // #define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) #define TCP_SSL_DEBUG(...) From 52e550beb6bab9890099c445dffe14b4bb443055 Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Wed, 9 Jan 2019 13:01:16 +0100 Subject: [PATCH 08/19] revert IDF changes, so it works with the latest stable IDF. --- src/AsyncTCP.cpp | 85 ++++++++++++++++++------------------------------ src/AsyncTCP.h | 10 +++--- 2 files changed, 37 insertions(+), 58 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 483b0778..6e7ddf6c 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -256,7 +256,7 @@ static void _tcp_error(void * arg, int8_t err) { #include "lwip/priv/tcpip_priv.h" typedef struct { - struct tcpip_api_call_data call; + struct tcpip_api_call call; tcp_pcb * pcb; int8_t err; union { @@ -279,7 +279,7 @@ typedef struct { }; } tcp_api_call_t; -static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){ +static err_t _tcp_output_api(struct tcpip_api_call *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_output(msg->pcb); return msg->err; @@ -288,11 +288,11 @@ static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){ static esp_err_t _tcp_output(tcp_pcb * pcb) { tcp_api_call_t msg; msg.pcb = pcb; - tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_tcp_output_api, (struct tcpip_api_call*)&msg); return msg.err; } -static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){ +static err_t _tcp_write_api(struct tcpip_api_call *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags); return msg->err; @@ -304,11 +304,11 @@ static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_ msg.write.data = data; msg.write.size = size; msg.write.apiflags = apiflags; - tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_tcp_write_api, (struct tcpip_api_call*)&msg); return msg.err; } -static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){ +static err_t _tcp_recved_api(struct tcpip_api_call *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = 0; tcp_recved(msg->pcb, msg->received); @@ -319,11 +319,11 @@ static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len) { tcp_api_call_t msg; msg.pcb = pcb; msg.received = len; - tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call*)&msg); return msg.err; } -static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg){ +static err_t _tcp_connect_api(struct tcpip_api_call *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_connect(msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb); return msg->err; @@ -335,11 +335,11 @@ static esp_err_t _tcp_connect(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port, tc msg.connect.addr = addr; msg.connect.port = port; msg.connect.cb = cb; - tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call*)&msg); return msg.err; } -static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){ +static err_t _tcp_close_api(struct tcpip_api_call *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_close(msg->pcb); return msg->err; @@ -349,11 +349,11 @@ static esp_err_t _tcp_close(tcp_pcb * pcb) { tcp_api_call_t msg; msg.pcb = pcb; //ets_printf("close 0x%08x\n", (uint32_t)pcb); - tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_tcp_close_api, (struct tcpip_api_call*)&msg); return msg.err; } -static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){ +static err_t _tcp_abort_api(struct tcpip_api_call *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = 0; tcp_abort(msg->pcb); @@ -364,11 +364,11 @@ static esp_err_t _tcp_abort(tcp_pcb * pcb) { tcp_api_call_t msg; msg.pcb = pcb; //ets_printf("abort 0x%08x\n", (uint32_t)pcb); - tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call*)&msg); return msg.err; } -static err_t _tcp_bind_api(struct tcpip_api_call_data *api_call_msg){ +static err_t _tcp_bind_api(struct tcpip_api_call *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_bind(msg->pcb, msg->bind.addr, msg->bind.port); return msg->err; @@ -379,11 +379,11 @@ static esp_err_t _tcp_bind(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port) { msg.pcb = pcb; msg.bind.addr = addr; msg.bind.port = port; - tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call*)&msg); return msg.err; } -static err_t _tcp_listen_api(struct tcpip_api_call_data *api_call_msg){ +static err_t _tcp_listen_api(struct tcpip_api_call *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = 0; msg->pcb = tcp_listen_with_backlog(msg->pcb, msg->backlog); @@ -394,7 +394,7 @@ static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) { tcp_api_call_t msg; msg.pcb = pcb; msg.backlog = backlog?backlog:0xFF; - tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg); + tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call*)&msg); return msg.pcb; } #define _tcp_listen(p) _tcp_listen_with_backlog(p, 0xFF); @@ -565,7 +565,7 @@ int8_t AsyncClient::_close(){ err = abort(); } _pcb = NULL; - // _tcp_clear_events(this); + _tcp_clear_events(this); if(_discard_cb) _discard_cb(_discard_cb_arg, this); } @@ -608,13 +608,12 @@ int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { if(!_pcb || pcb != _pcb){ - log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - if(pb){ - pbuf_free(pb); - } - return ERR_OK; - } - + log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + if(pb){ + pbuf_free(pb); + } + return ERR_OK; + } _in_lwip_thread = false; if(pb == NULL){ return _close(); @@ -691,7 +690,7 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ return ERR_OK; } -void AsyncClient::_dns_found(struct ip_addr *ipaddr){ +void AsyncClient::_dns_found(ip_addr_t *ipaddr){ _in_lwip_thread = true; Serial.print("ip: "); Serial.println(ipaddr_ntoa(ipaddr)); @@ -1037,20 +1036,12 @@ void AsyncClient::onPoll(AcConnectHandler cb, void* arg){ _poll_cb_arg = arg; } -void AsyncClient::_s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg){ - if(arg){ - reinterpret_cast(arg)->_dns_found(ipaddr); - } else { - log_e("Bad Arg: 0x%08x", arg); - } +void AsyncClient::_s_dns_found(const char * name, ip_addr_t * ipaddr, void * arg){ + reinterpret_cast(arg)->_dns_found(ipaddr); } int8_t AsyncClient::_s_poll(void * arg, struct tcp_pcb * pcb) { - if(arg && pcb){ - reinterpret_cast(arg)->_poll(pcb); - } else { - log_e("Bad Args: 0x%08x 0x%08x", arg, pcb); - } + reinterpret_cast(arg)->_poll(pcb); return ERR_OK; } @@ -1059,7 +1050,7 @@ int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, i reinterpret_cast(arg)->_recv(pcb, pb, err); } else { if(pb){ - pbuf_free(pb); + pbuf_free(pb); } log_e("Bad Args: 0x%08x 0x%08x", arg, pcb); } @@ -1067,28 +1058,16 @@ int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, i } int8_t AsyncClient::_s_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { - if(arg && pcb){ - reinterpret_cast(arg)->_sent(pcb, len); - } else { - log_e("Bad Args: 0x%08x 0x%08x", arg, pcb); - } + reinterpret_cast(arg)->_sent(pcb, len); return ERR_OK; } void AsyncClient::_s_error(void * arg, int8_t err) { - if(arg){ - reinterpret_cast(arg)->_error(err); - } else { - log_e("Bad Arg: 0x%08x", arg); - } + reinterpret_cast(arg)->_error(err); } int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ - if(arg && pcb){ - reinterpret_cast(arg)->_connected(pcb, err); - } else { - log_e("Bad Args: 0x%08x 0x%08x", arg, pcb); - } + reinterpret_cast(arg)->_connected(pcb, err); return ERR_OK; } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index ccbc9df4..87d5f312 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -45,7 +45,7 @@ typedef std::function AcPacketHandle typedef std::function AcTimeoutHandler; struct tcp_pcb; -struct ip_addr; +struct _ip_addr; class AsyncClient { protected: @@ -87,7 +87,7 @@ class AsyncClient { void _ssl_error(int8_t err); int8_t _poll(tcp_pcb* pcb); int8_t _sent(tcp_pcb* pcb, uint16_t len); - void _dns_found(struct ip_addr *ipaddr); + void _dns_found(struct _ip_addr *ipaddr); static void _s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len); static void _s_handshake(void *arg, struct tcp_pcb *tcp, struct tcp_ssl_pcb* ssl); static void _s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err); @@ -116,13 +116,13 @@ class AsyncClient { bool canSend();//ack is not pending size_t space(); - size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending + size_t add(const char* data, size_t size, uint8_t apiflags=0);//add for sending bool send();//send all data added with the method above size_t ack(size_t len); //ack data that you have not acked using the method below void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData size_t write(const char* data); - size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true + size_t write(const char* data, size_t size, uint8_t apiflags=0); //only when canSend() == true uint8_t state(); bool connecting(); @@ -169,7 +169,7 @@ class AsyncClient { static void _s_error(void *arg, int8_t err); static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len); static int8_t _s_connected(void* arg, void* tpcb, int8_t err); - static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg); + static void _s_dns_found(const char *name, struct _ip_addr *ipaddr, void *arg); bool _in_lwip_thread; }; From 001ae064576da7dcf7067d175e2eae231ec86a5b Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Thu, 10 Jan 2019 12:07:42 +0100 Subject: [PATCH 09/19] Not a fan of defines, but to keep things in line with the esp8266 version added all SSL stuff between defines. In order to enable SSL add -DASYNC_TCP_SSL_ENABLED to your build flags. --- src/AsyncTCP.cpp | 64 ++++++++++++++++++++++++++++++++++++++--------- src/AsyncTCP.h | 13 ++++++++++ src/tcp_mbedtls.c | 4 +++ src/tcp_mbedtls.h | 3 +++ 4 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 6e7ddf6c..f4a4fad8 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -421,6 +421,10 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) , _timeout_cb(0) , _timeout_cb_arg(0) , _pcb_busy(false) +#if ASYNC_TCP_SSL_ENABLED +, _pcb_secure(false) +, _handshake_done(true) +#endif // ASYNC_TCP_SSL_ENABLED , _pcb_sent_at(0) , _close_pcb(false) , _ack_pcb(true) @@ -449,7 +453,11 @@ AsyncClient::~AsyncClient(){ _close(); } +#if ASYNC_TCP_SSL_ENABLED bool AsyncClient::connect(IPAddress ip, uint16_t port, bool secure){ +#else +bool AsyncClient::connect(IPAddress ip, uint16_t port){ +#endif // ASYNC_TCP_SSL_ENABLED if (_pcb){ log_w("already connected, state %d", _pcb->state); return false; @@ -469,19 +477,16 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port, bool secure){ return false; } - Serial.print("connect res ip: "); - Serial.println(secure); - +#if ASYNC_TCP_SSL_ENABLED _pcb_secure = secure; _handshake_done = !secure; +#endif // ASYNC_TCP_SSL_ENABLED tcp_arg(pcb, this); tcp_err(pcb, &_tcp_error); if(_in_lwip_thread){ - log_i("tcp_connect-1: _in_lwip_thread: %d", _in_lwip_thread); tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected); } else { - log_i("tcp_connect-2: _in_lwip_thread: %d", _in_lwip_thread); _tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected); } return true; @@ -500,6 +505,7 @@ AsyncClient& AsyncClient::operator=(const AsyncClient& other){ tcp_err(_pcb, &_tcp_error); tcp_poll(_pcb, &_tcp_poll, 1); +#if ASYNC_TCP_SSL_ENABLED if(tcp_ssl_has(_pcb)){ _pcb_secure = true; _handshake_done = false; @@ -511,6 +517,7 @@ AsyncClient& AsyncClient::operator=(const AsyncClient& other){ _pcb_secure = false; _handshake_done = true; } +#endif // ASYNC_TCP_SSL_ENABLED } return *this; } @@ -524,7 +531,7 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){ tcp_recv(_pcb, &_tcp_recv); tcp_sent(_pcb, &_tcp_sent); tcp_poll(_pcb, &_tcp_poll, 1); - +#if ASYNC_TCP_SSL_ENABLED if(_pcb_secure){ if(tcp_ssl_new_client(_pcb, _hostname.empty() ? NULL : _hostname.c_str()) < 0){ log_e("closing...."); @@ -536,11 +543,18 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){ tcp_ssl_handshake(_pcb, &_s_handshake); tcp_ssl_err(_pcb, &_s_ssl_error); } +#endif // ASYNC_TCP_SSL_ENABLED } + _in_lwip_thread = true; +#if ASYNC_TCP_SSL_ENABLED if(!_pcb_secure && _connect_cb) +#else + if(_connect_cb) +#endif // ASYNC_TCP_SSL_ENABLED _connect_cb(_connect_cb_arg, this); _in_lwip_thread = false; + return ERR_OK; } @@ -548,9 +562,11 @@ int8_t AsyncClient::_close(){ int8_t err = ERR_OK; if(_pcb) { +#if ASYNC_TCP_SSL_ENABLED if(_pcb_secure){ tcp_ssl_free(_pcb); } +#endif // ASYNC_TCP_SSL_ENABLED tcp_arg(_pcb, NULL); tcp_sent(_pcb, NULL); tcp_recv(_pcb, NULL); @@ -588,14 +604,18 @@ void AsyncClient::_error(int8_t err) { _discard_cb(_discard_cb_arg, this); } +#if ASYNC_TCP_SSL_ENABLED void AsyncClient::_ssl_error(int8_t err){ if(_error_cb) _error_cb(_error_cb_arg, this, err+64); } +#endif // ASYNC_TCP_SSL_ENABLED int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { +#if ASYNC_TCP_SSL_ENABLED if (_pcb_secure && !_handshake_done) return ERR_OK; +#endif // ASYNC_TCP_SSL_ENABLED _in_lwip_thread = false; _rx_last_packet = millis(); @@ -621,6 +641,7 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { while(pb != NULL){ _rx_last_packet = millis(); +#if ASYNC_TCP_SSL_ENABLED if(_pcb_secure){ // log_i("_recv: %d\n", pb->tot_len); int read_bytes = tcp_ssl_read(pcb, pb); @@ -634,6 +655,7 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { } return ERR_OK; } +#endif // ASYNC_TCP_SSL_ENABLED //we should not ack before we assimilate the data //log_i("%u", pb->len); //Serial.write((const uint8_t *)pb->payload, pb->len); @@ -680,10 +702,12 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ _close(); return ERR_OK; } +#if ASYNC_TCP_SSL_ENABLED if(_pcb_secure && !_handshake_done && (now - _rx_last_packet) >= 2000){ _close(); return ERR_OK; } +#endif // ASYNC_TCP_SSL_ENABLED // Everything is fine if(_poll_cb) _poll_cb(_poll_cb_arg, this); @@ -696,7 +720,11 @@ void AsyncClient::_dns_found(ip_addr_t *ipaddr){ Serial.println(ipaddr_ntoa(ipaddr)); if(ipaddr){ +#if ASYNC_TCP_SSL_ENABLED connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port, _pcb_secure); +#else + connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port); +#endif // ASYNC_TCP_SSL_ENABLED } else { log_e("dns fail"); if(_error_cb) @@ -711,22 +739,29 @@ bool AsyncClient::operator==(const AsyncClient &other) { return _pcb == other._pcb; } +#if ASYNC_TCP_SSL_ENABLED bool AsyncClient::connect(const char* host, uint16_t port, bool secure){ +#else +bool AsyncClient::connect(const char* host, uint16_t port){ +#endif // ASYNC_TCP_SSL_ENABLED ip_addr_t addr; err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_s_dns_found, this); if(err == ERR_OK) { - // @ToDo: do this at one place. - _hostname = std::string(host); + _hostname = host; +#if ASYNC_TCP_SSL_ENABLED return connect(IPAddress(addr.u_addr.ip4.addr), port, secure); +#else + return connect(IPAddress(addr.u_addr.ip4.addr), port); +#endif // ASYNC_TCP_SSL_ENABLED } else if(err == ERR_INPROGRESS) { - // @ToDo: do this at one place. - _hostname = std::string(host); - + _hostname = host; _connect_port = port; +#if ASYNC_TCP_SSL_ENABLED _pcb_secure = secure; _handshake_done = !secure; +#endif // ASYNC_TCP_SSL_ENABLED return true; } log_e("error: %d", err); @@ -798,6 +833,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { size_t room = space(); if(!room) return 0; +#if ASYNC_TCP_SSL_ENABLED if(_pcb_secure){ int sent = tcp_ssl_write(_pcb, (uint8_t*)data, size); if(sent >= 0){ @@ -809,6 +845,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { _close(); return 0; } +#endif // ASYNC_TCP_SSL_ENABLED size_t will_send = (room < size) ? room : size; int8_t err = ERR_OK; if(_in_lwip_thread){ @@ -822,9 +859,10 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { } bool AsyncClient::send(){ +#if ASYNC_TCP_SSL_ENABLED if(_pcb_secure) return true; - +#endif // ASYNC_TCP_SSL_ENABLED int8_t err = ERR_OK; if(_in_lwip_thread){ err = tcp_output(_pcb); @@ -1071,6 +1109,7 @@ int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ return ERR_OK; } +#if ASYNC_TCP_SSL_ENABLED void AsyncClient::_s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len){ AsyncClient *c = reinterpret_cast(arg); if(c->_recv_cb) @@ -1087,6 +1126,7 @@ void AsyncClient::_s_handshake(void *arg, struct tcp_pcb *tcp, struct tcp_ssl_pc void AsyncClient::_s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err){ reinterpret_cast(arg)->_ssl_error(err); } +#endif // ASYNC_TCP_SSL_ENABLED const char * AsyncClient::errorToString(int8_t error){ switch(error){ diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 87d5f312..f2aecbdc 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -24,6 +24,7 @@ #include "IPAddress.h" #include +#include #include extern "C" { #include "freertos/semphr.h" @@ -70,8 +71,10 @@ class AsyncClient { void* _poll_cb_arg; bool _pcb_busy; +#if ASYNC_TCP_SSL_ENABLED bool _pcb_secure; bool _handshake_done; +#endif // ASYNC_TCP_SSL_ENABLED uint32_t _pcb_sent_at; bool _close_pcb; bool _ack_pcb; @@ -84,13 +87,17 @@ class AsyncClient { int8_t _close(); int8_t _connected(void* pcb, int8_t err); void _error(int8_t err); +#if ASYNC_TCP_SSL_ENABLED void _ssl_error(int8_t err); +#endif // ASYNC_TCP_SSL_ENABLED int8_t _poll(tcp_pcb* pcb); int8_t _sent(tcp_pcb* pcb, uint16_t len); void _dns_found(struct _ip_addr *ipaddr); +#if ASYNC_TCP_SSL_ENABLED static void _s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len); static void _s_handshake(void *arg, struct tcp_pcb *tcp, struct tcp_ssl_pcb* ssl); static void _s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err); +#endif // ASYNC_TCP_SSL_ENABLED public: AsyncClient* prev; @@ -107,8 +114,14 @@ class AsyncClient { bool operator!=(const AsyncClient &other) { return !(*this == other); } + +#if ASYNC_TCP_SSL_ENABLED bool connect(IPAddress ip, uint16_t port, bool secure = false); bool connect(const char* host, uint16_t port, bool secure = false); +#else + bool connect(IPAddress ip, uint16_t port); + bool connect(const char* host, uint16_t port); +#endif // ASYNC_TCP_SSL_ENABLED void close(bool now = false); void stop(); int8_t abort(); diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index 4bdb723b..155b5d37 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -1,3 +1,5 @@ +#if ASYNC_TCP_SSL_ENABLED + #include "tcp_mbedtls.h" #include "lwip/tcp.h" #include "mbedtls/debug.h" @@ -451,3 +453,5 @@ void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg){ item->on_error = arg; } } + +#endif // ASYNC_TCP_SSL_ENABLED \ No newline at end of file diff --git a/src/tcp_mbedtls.h b/src/tcp_mbedtls.h index b9503319..42c7487f 100644 --- a/src/tcp_mbedtls.h +++ b/src/tcp_mbedtls.h @@ -1,6 +1,8 @@ #ifndef LWIPR_MBEDTLS_H #define LWIPR_MBEDTLS_H +#if ASYNC_TCP_SSL_ENABLED + #include "mbedtls/platform.h" #include "mbedtls/net.h" #include "mbedtls/debug.h" @@ -45,3 +47,4 @@ void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg); #endif // LWIPR_MBEDTLS_H +#endif // ASYNC_TCP_SSL_ENABLED From 9f7a918a3e014cafabeea384e5116986d66f586e Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Fri, 11 Jan 2019 11:45:04 +0100 Subject: [PATCH 10/19] clean-up --- src/AsyncTCP.cpp | 2 -- src/AsyncTCP.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index f4a4fad8..d8cbbcda 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -716,8 +716,6 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ void AsyncClient::_dns_found(ip_addr_t *ipaddr){ _in_lwip_thread = true; - Serial.print("ip: "); - Serial.println(ipaddr_ntoa(ipaddr)); if(ipaddr){ #if ASYNC_TCP_SSL_ENABLED diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index f2aecbdc..baf7e4de 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,6 +22,7 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ +#include "Arduino.h" #include "IPAddress.h" #include #include From 518767335f786eb3487aebd32c16e0fe89f63244 Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Fri, 11 Jan 2019 11:49:26 +0100 Subject: [PATCH 11/19] merge origin/idf-update into mbed-tls, as it's now part of the latest released version of arduino-esp32... --- src/AsyncTCP.cpp | 85 ++++++++++++++++++++++++++++++------------------ src/AsyncTCP.h | 10 +++--- 2 files changed, 58 insertions(+), 37 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index d8cbbcda..4caab4aa 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -256,7 +256,7 @@ static void _tcp_error(void * arg, int8_t err) { #include "lwip/priv/tcpip_priv.h" typedef struct { - struct tcpip_api_call call; + struct tcpip_api_call_data call; tcp_pcb * pcb; int8_t err; union { @@ -279,7 +279,7 @@ typedef struct { }; } tcp_api_call_t; -static err_t _tcp_output_api(struct tcpip_api_call *api_call_msg){ +static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_output(msg->pcb); return msg->err; @@ -288,11 +288,11 @@ static err_t _tcp_output_api(struct tcpip_api_call *api_call_msg){ static esp_err_t _tcp_output(tcp_pcb * pcb) { tcp_api_call_t msg; msg.pcb = pcb; - tcpip_api_call(_tcp_output_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg); return msg.err; } -static err_t _tcp_write_api(struct tcpip_api_call *api_call_msg){ +static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags); return msg->err; @@ -304,11 +304,11 @@ static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_ msg.write.data = data; msg.write.size = size; msg.write.apiflags = apiflags; - tcpip_api_call(_tcp_write_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg); return msg.err; } -static err_t _tcp_recved_api(struct tcpip_api_call *api_call_msg){ +static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = 0; tcp_recved(msg->pcb, msg->received); @@ -319,11 +319,11 @@ static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len) { tcp_api_call_t msg; msg.pcb = pcb; msg.received = len; - tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg); return msg.err; } -static err_t _tcp_connect_api(struct tcpip_api_call *api_call_msg){ +static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_connect(msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb); return msg->err; @@ -335,11 +335,11 @@ static esp_err_t _tcp_connect(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port, tc msg.connect.addr = addr; msg.connect.port = port; msg.connect.cb = cb; - tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg); return msg.err; } -static err_t _tcp_close_api(struct tcpip_api_call *api_call_msg){ +static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_close(msg->pcb); return msg->err; @@ -349,11 +349,11 @@ static esp_err_t _tcp_close(tcp_pcb * pcb) { tcp_api_call_t msg; msg.pcb = pcb; //ets_printf("close 0x%08x\n", (uint32_t)pcb); - tcpip_api_call(_tcp_close_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg); return msg.err; } -static err_t _tcp_abort_api(struct tcpip_api_call *api_call_msg){ +static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = 0; tcp_abort(msg->pcb); @@ -364,11 +364,11 @@ static esp_err_t _tcp_abort(tcp_pcb * pcb) { tcp_api_call_t msg; msg.pcb = pcb; //ets_printf("abort 0x%08x\n", (uint32_t)pcb); - tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg); return msg.err; } -static err_t _tcp_bind_api(struct tcpip_api_call *api_call_msg){ +static err_t _tcp_bind_api(struct tcpip_api_call_data *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = tcp_bind(msg->pcb, msg->bind.addr, msg->bind.port); return msg->err; @@ -379,11 +379,11 @@ static esp_err_t _tcp_bind(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port) { msg.pcb = pcb; msg.bind.addr = addr; msg.bind.port = port; - tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg); return msg.err; } -static err_t _tcp_listen_api(struct tcpip_api_call *api_call_msg){ +static err_t _tcp_listen_api(struct tcpip_api_call_data *api_call_msg){ tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = 0; msg->pcb = tcp_listen_with_backlog(msg->pcb, msg->backlog); @@ -394,7 +394,7 @@ static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) { tcp_api_call_t msg; msg.pcb = pcb; msg.backlog = backlog?backlog:0xFF; - tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call*)&msg); + tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg); return msg.pcb; } #define _tcp_listen(p) _tcp_listen_with_backlog(p, 0xFF); @@ -581,7 +581,7 @@ int8_t AsyncClient::_close(){ err = abort(); } _pcb = NULL; - _tcp_clear_events(this); + // _tcp_clear_events(this); if(_discard_cb) _discard_cb(_discard_cb_arg, this); } @@ -628,12 +628,13 @@ int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { if(!_pcb || pcb != _pcb){ - log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - if(pb){ - pbuf_free(pb); - } - return ERR_OK; - } + log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + if(pb){ + pbuf_free(pb); + } + return ERR_OK; + } + _in_lwip_thread = false; if(pb == NULL){ return _close(); @@ -714,7 +715,7 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ return ERR_OK; } -void AsyncClient::_dns_found(ip_addr_t *ipaddr){ +void AsyncClient::_dns_found(struct ip_addr *ipaddr){ _in_lwip_thread = true; if(ipaddr){ @@ -1072,12 +1073,20 @@ void AsyncClient::onPoll(AcConnectHandler cb, void* arg){ _poll_cb_arg = arg; } -void AsyncClient::_s_dns_found(const char * name, ip_addr_t * ipaddr, void * arg){ - reinterpret_cast(arg)->_dns_found(ipaddr); +void AsyncClient::_s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg){ + if(arg){ + reinterpret_cast(arg)->_dns_found(ipaddr); + } else { + log_e("Bad Arg: 0x%08x", arg); + } } int8_t AsyncClient::_s_poll(void * arg, struct tcp_pcb * pcb) { - reinterpret_cast(arg)->_poll(pcb); + if(arg && pcb){ + reinterpret_cast(arg)->_poll(pcb); + } else { + log_e("Bad Args: 0x%08x 0x%08x", arg, pcb); + } return ERR_OK; } @@ -1086,7 +1095,7 @@ int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, i reinterpret_cast(arg)->_recv(pcb, pb, err); } else { if(pb){ - pbuf_free(pb); + pbuf_free(pb); } log_e("Bad Args: 0x%08x 0x%08x", arg, pcb); } @@ -1094,16 +1103,28 @@ int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, i } int8_t AsyncClient::_s_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { - reinterpret_cast(arg)->_sent(pcb, len); + if(arg && pcb){ + reinterpret_cast(arg)->_sent(pcb, len); + } else { + log_e("Bad Args: 0x%08x 0x%08x", arg, pcb); + } return ERR_OK; } void AsyncClient::_s_error(void * arg, int8_t err) { - reinterpret_cast(arg)->_error(err); + if(arg){ + reinterpret_cast(arg)->_error(err); + } else { + log_e("Bad Arg: 0x%08x", arg); + } } int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ - reinterpret_cast(arg)->_connected(pcb, err); + if(arg && pcb){ + reinterpret_cast(arg)->_connected(pcb, err); + } else { + log_e("Bad Args: 0x%08x 0x%08x", arg, pcb); + } return ERR_OK; } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index baf7e4de..2ade8590 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -47,7 +47,7 @@ typedef std::function AcPacketHandle typedef std::function AcTimeoutHandler; struct tcp_pcb; -struct _ip_addr; +struct ip_addr; class AsyncClient { protected: @@ -93,7 +93,7 @@ class AsyncClient { #endif // ASYNC_TCP_SSL_ENABLED int8_t _poll(tcp_pcb* pcb); int8_t _sent(tcp_pcb* pcb, uint16_t len); - void _dns_found(struct _ip_addr *ipaddr); + void _dns_found(struct ip_addr *ipaddr); #if ASYNC_TCP_SSL_ENABLED static void _s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len); static void _s_handshake(void *arg, struct tcp_pcb *tcp, struct tcp_ssl_pcb* ssl); @@ -130,13 +130,13 @@ class AsyncClient { bool canSend();//ack is not pending size_t space(); - size_t add(const char* data, size_t size, uint8_t apiflags=0);//add for sending + size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending bool send();//send all data added with the method above size_t ack(size_t len); //ack data that you have not acked using the method below void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData size_t write(const char* data); - size_t write(const char* data, size_t size, uint8_t apiflags=0); //only when canSend() == true + size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true uint8_t state(); bool connecting(); @@ -183,7 +183,7 @@ class AsyncClient { static void _s_error(void *arg, int8_t err); static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len); static int8_t _s_connected(void* arg, void* tpcb, int8_t err); - static void _s_dns_found(const char *name, struct _ip_addr *ipaddr, void *arg); + static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg); bool _in_lwip_thread; }; From d631d7d1ecd359afd28f84bc6e23665e33d82bbb Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Tue, 15 Jan 2019 18:07:39 +0100 Subject: [PATCH 12/19] add some dummy functions so we can compile when the ESP Async WebServer library is also used. --- src/AsyncTCP.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 2ade8590..3c73f61f 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -188,6 +188,10 @@ class AsyncClient { bool _in_lwip_thread; }; +#if ASYNC_TCP_SSL_ENABLED +typedef std::function AcSSlFileHandler; +#endif + class AsyncServer { protected: uint16_t _port; @@ -204,6 +208,11 @@ class AsyncServer { AsyncServer(uint16_t port); ~AsyncServer(); void onClient(AcConnectHandler cb, void* arg); +#if ASYNC_TCP_SSL_ENABLED + // Dummy, so it compiles with ESP Async WebServer library enabled. + void onSslFileRequest(AcSSlFileHandler cb, void* arg) {}; + void beginSecure(const char *cert, const char *private_key_file, const char *password) {}; +#endif void begin(); void end(); void setNoDelay(bool nodelay); From 78f952eaccc1c6ac00caf23a6d63cb12968ba643 Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Thu, 17 Jan 2019 22:59:27 +0100 Subject: [PATCH 13/19] allow setting a root CA. --- src/AsyncTCP.cpp | 10 ++++++++-- src/AsyncTCP.h | 3 +++ src/tcp_mbedtls.c | 31 ++++++++++++++++++++++--------- src/tcp_mbedtls.h | 2 +- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index ab909d7e..6bfa73ef 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -408,7 +408,6 @@ static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) { /* Async TCP Client */ - AsyncClient::AsyncClient(tcp_pcb* pcb) : _connect_cb(0) , _connect_cb_arg(0) @@ -426,6 +425,8 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) , _timeout_cb_arg(0) , _pcb_busy(false) #if ASYNC_TCP_SSL_ENABLED +, _root_ca(NULL) +, _root_ca_len(0) , _pcb_secure(false) , _handshake_done(true) #endif // ASYNC_TCP_SSL_ENABLED @@ -496,6 +497,11 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){ return true; } +void AsyncClient::setRootCa(const char* rootca, const size_t len) { + _root_ca = (char*)rootca; + _root_ca_len = len; +} + AsyncClient& AsyncClient::operator=(const AsyncClient& other){ if (_pcb) _close(); @@ -537,7 +543,7 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){ tcp_poll(_pcb, &_tcp_poll, 1); #if ASYNC_TCP_SSL_ENABLED if(_pcb_secure){ - if(tcp_ssl_new_client(_pcb, _hostname.empty() ? NULL : _hostname.c_str()) < 0){ + if(tcp_ssl_new_client(_pcb, _hostname.empty() ? NULL : _hostname.c_str(), _root_ca, _root_ca_len) < 0){ log_e("closing...."); return _close(); } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 3c73f61f..117f7ff6 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -73,6 +73,8 @@ class AsyncClient { bool _pcb_busy; #if ASYNC_TCP_SSL_ENABLED + size_t _root_ca_len; + char* _root_ca; bool _pcb_secure; bool _handshake_done; #endif // ASYNC_TCP_SSL_ENABLED @@ -119,6 +121,7 @@ class AsyncClient { #if ASYNC_TCP_SSL_ENABLED bool connect(IPAddress ip, uint16_t port, bool secure = false); bool connect(const char* host, uint16_t port, bool secure = false); + void setRootCa(const char* rootca, const size_t len); #else bool connect(IPAddress ip, uint16_t port); bool connect(const char* host, uint16_t port); diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index 155b5d37..0a653ac7 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -6,8 +6,8 @@ #include "mbedtls/esp_debug.h" #include -// #define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) -#define TCP_SSL_DEBUG(...) +#define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) +// #define TCP_SSL_DEBUG(...) static const char pers[] = "esp32-tls"; @@ -55,6 +55,7 @@ struct tcp_ssl_pcb { int fd; mbedtls_ssl_context ssl_ctx; mbedtls_ssl_config ssl_conf; + mbedtls_x509_crt ca_cert; mbedtls_ctr_drbg_context drbg_ctx; mbedtls_entropy_context entropy_ctx; uint8_t type; @@ -213,11 +214,9 @@ tcp_ssl_t* tcp_ssl_get(struct tcp_pcb *tcp) { return item; } -int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname) { +int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname, const char* root_ca, const size_t root_ca_len) { tcp_ssl_t* tcp_ssl; - TCP_SSL_DEBUG("tcp_ssl_new_client\n"); - if(tcp == NULL) { return -1; } @@ -249,12 +248,26 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname) { return -1; } - // @ToDo: allow setting a root CA, for now just not verify. - mbedtls_ssl_conf_authmode(&tcp_ssl->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); - // mbedtls_ssl_conf_authmode(&tcp_ssl->ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL); - int ret = 0; + if(root_ca != NULL && root_ca_len > 0) { + TCP_SSL_DEBUG("setting the root ca.\n"); + + mbedtls_x509_crt_init(&tcp_ssl->ca_cert); + + mbedtls_ssl_conf_authmode(&tcp_ssl->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); + + ret = mbedtls_x509_crt_parse(&tcp_ssl->ca_cert, (const unsigned char *)root_ca, root_ca_len); + if( ret < 0 ){ + TCP_SSL_DEBUG(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); + return handle_error(ret); + } + + mbedtls_ssl_conf_ca_chain(&tcp_ssl->ssl_conf, &tcp_ssl->ca_cert, NULL); + } else { + mbedtls_ssl_conf_authmode(&tcp_ssl->ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL); + } + if(hostname != NULL) { TCP_SSL_DEBUG("setting the hostname: %s\n", hostname); if((ret = mbedtls_ssl_set_hostname(&tcp_ssl->ssl_ctx, hostname)) != 0){ diff --git a/src/tcp_mbedtls.h b/src/tcp_mbedtls.h index 42c7487f..ff0c9a87 100644 --- a/src/tcp_mbedtls.h +++ b/src/tcp_mbedtls.h @@ -30,7 +30,7 @@ typedef void (* tcp_ssl_handshake_cb_t)(void *arg, struct tcp_pcb *tcp, struct t typedef void (* tcp_ssl_error_cb_t)(void *arg, struct tcp_pcb *tcp, int8_t error); uint8_t tcp_ssl_has_client(); -int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname); +int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname, const char* root_ca, const size_t root_ca_len); int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len); int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p); int tcp_ssl_handshake_step(struct tcp_pcb *tcp); From 0879ba248d1afd51a36fe2deba35d179bddfa90e Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Thu, 17 Jan 2019 23:00:30 +0100 Subject: [PATCH 14/19] oops, set debug disabled as default again. --- src/tcp_mbedtls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index 0a653ac7..9748614b 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -6,8 +6,8 @@ #include "mbedtls/esp_debug.h" #include -#define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) -// #define TCP_SSL_DEBUG(...) +// #define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) +#define TCP_SSL_DEBUG(...) static const char pers[] = "esp32-tls"; From ef5035738f84e3f89ac71b467626ee3620aa0650 Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Fri, 18 Jan 2019 13:28:45 +0100 Subject: [PATCH 15/19] add ASYNC_TCP_SSL_ENABLED around setRootCa call. --- src/AsyncTCP.cpp | 2 ++ src/tcp_mbedtls.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 6bfa73ef..1fe71191 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -497,10 +497,12 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){ return true; } +#if ASYNC_TCP_SSL_ENABLED void AsyncClient::setRootCa(const char* rootca, const size_t len) { _root_ca = (char*)rootca; _root_ca_len = len; } +#endif // ASYNC_TCP_SSL_ENABLED AsyncClient& AsyncClient::operator=(const AsyncClient& other){ if (_pcb) diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index 9748614b..55ec9cc8 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -356,7 +356,7 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { if(tcp_ssl->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER) { TCP_SSL_DEBUG("start handshake: %d\n", tcp_ssl->ssl_ctx.state); int ret = mbedtls_ssl_handshake(&tcp_ssl->ssl_ctx); - handle_error(ret); + //handle_error(ret); if(ret == 0) { TCP_SSL_DEBUG("Protocol is %s Ciphersuite is %s\n", mbedtls_ssl_get_version(&tcp_ssl->ssl_ctx), mbedtls_ssl_get_ciphersuite(&tcp_ssl->ssl_ctx)); From 3fa9abf6059190078a58e4284ca8906b35485a1b Mon Sep 17 00:00:00 2001 From: Maarten Fremouw Date: Sat, 2 Mar 2019 12:24:22 +0100 Subject: [PATCH 16/19] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 023849bf..8a11cea5 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,6 @@ This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ES ## AsyncClient and AsyncServer The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. + +## TLS support +Support for TLS is added using mbed TLS, for now only the client part is supported. You can enable this by adding the flag ASYNC_TCP_SSL_ENABLED to your build flags (-DASYNC_TCP_SSL_ENABLED). If you'd like to set a root certificate you can use the setRootCa function on AsyncClient. Feel free to add support for the server side as well :-) From 5e06389b732b31a0b97625444fdf633f2ab179f7 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Tue, 16 Apr 2019 13:59:49 -0700 Subject: [PATCH 17/19] add support for pre-shared key TLS cipher suites --- README.md | 4 ++ src/AsyncTCP.cpp | 19 ++++++++-- src/AsyncTCP.h | 3 ++ src/tcp_mbedtls.c | 96 +++++++++++++++++++++++++++++++++++++++++++---- src/tcp_mbedtls.h | 1 + 5 files changed, 112 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 8a11cea5..2d6b743b 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,7 @@ The base classes on which everything else is built. They expose all possible sce ## TLS support Support for TLS is added using mbed TLS, for now only the client part is supported. You can enable this by adding the flag ASYNC_TCP_SSL_ENABLED to your build flags (-DASYNC_TCP_SSL_ENABLED). If you'd like to set a root certificate you can use the setRootCa function on AsyncClient. Feel free to add support for the server side as well :-) + +In addition to the regular certificate based cipher suites there is also support for Pre-Shared Key +cipher suites. Use `setPsk` to define the PSK identifier and PSK itself. The PSK needs to be +provided in the form of a hex string (and easy way to generate a PSK is to use md5sum). diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 1fe71191..aaaeb512 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -429,6 +429,8 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) , _root_ca_len(0) , _pcb_secure(false) , _handshake_done(true) +, _psk_ident(0) +, _psk(0) #endif // ASYNC_TCP_SSL_ENABLED , _pcb_sent_at(0) , _close_pcb(false) @@ -502,6 +504,11 @@ void AsyncClient::setRootCa(const char* rootca, const size_t len) { _root_ca = (char*)rootca; _root_ca_len = len; } + +void AsyncClient::setPsk(const char* psk_ident, const char* psk) { + _psk_ident = psk_ident; + _psk = psk; +} #endif // ASYNC_TCP_SSL_ENABLED AsyncClient& AsyncClient::operator=(const AsyncClient& other){ @@ -545,11 +552,17 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){ tcp_poll(_pcb, &_tcp_poll, 1); #if ASYNC_TCP_SSL_ENABLED if(_pcb_secure){ - if(tcp_ssl_new_client(_pcb, _hostname.empty() ? NULL : _hostname.c_str(), _root_ca, _root_ca_len) < 0){ + bool err = false; + if(_root_ca) { + err = tcp_ssl_new_client(_pcb, _hostname.empty() ? NULL : _hostname.c_str(), _root_ca, _root_ca_len) < 0; + } else { + err = tcp_ssl_new_psk_client(_pcb, _psk_ident, _psk) < 0; + } + if (err) { log_e("closing...."); return _close(); } - + tcp_ssl_arg(_pcb, this); tcp_ssl_data(_pcb, &_s_data); tcp_ssl_handshake(_pcb, &_s_handshake); @@ -663,7 +676,7 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { log_e("_recv err: %d\n", read_bytes); _close(); } - + //return read_bytes; } return ERR_OK; diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 117f7ff6..8117a63f 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -77,6 +77,8 @@ class AsyncClient { char* _root_ca; bool _pcb_secure; bool _handshake_done; + const char* _psk_ident; + const char* _psk; #endif // ASYNC_TCP_SSL_ENABLED uint32_t _pcb_sent_at; bool _close_pcb; @@ -122,6 +124,7 @@ class AsyncClient { bool connect(IPAddress ip, uint16_t port, bool secure = false); bool connect(const char* host, uint16_t port, bool secure = false); void setRootCa(const char* rootca, const size_t len); + void setPsk(const char* psk_ident, const char* psk); #else bool connect(IPAddress ip, uint16_t port); bool connect(const char* host, uint16_t port); diff --git a/src/tcp_mbedtls.c b/src/tcp_mbedtls.c index 55ec9cc8..fc06d72b 100644 --- a/src/tcp_mbedtls.c +++ b/src/tcp_mbedtls.c @@ -7,7 +7,7 @@ #include // #define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) -#define TCP_SSL_DEBUG(...) +#define TCP_SSL_DEBUG(...) static const char pers[] = "esp32-tls"; @@ -139,7 +139,7 @@ int tcp_ssl_send(void *ctx, const unsigned char *buf, size_t len) { } else { tcp_len = len; } - + if (tcp_len > 2 * tcp_ssl->tcp->mss) { tcp_len = 2 * tcp_ssl->tcp->mss; } @@ -243,7 +243,7 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname, const char* ro MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) { TCP_SSL_DEBUG("error setting SSL config.\n"); - + tcp_ssl_free(tcp); return -1; } @@ -267,7 +267,7 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname, const char* ro } else { mbedtls_ssl_conf_authmode(&tcp_ssl->ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL); } - + if(hostname != NULL) { TCP_SSL_DEBUG("setting the hostname: %s\n", hostname); if((ret = mbedtls_ssl_set_hostname(&tcp_ssl->ssl_ctx, hostname)) != 0){ @@ -282,7 +282,87 @@ int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname, const char* ro if ((ret = mbedtls_ssl_setup(&tcp_ssl->ssl_ctx, &tcp_ssl->ssl_conf)) != 0) { tcp_ssl_free(tcp); - + + return handle_error(ret); + } + + mbedtls_ssl_set_bio(&tcp_ssl->ssl_ctx, (void*)tcp_ssl, tcp_ssl_send, tcp_ssl_recv, NULL); + + // Start handshake. + ret = mbedtls_ssl_handshake(&tcp_ssl->ssl_ctx); + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + TCP_SSL_DEBUG("handshake error!\n"); + return handle_error(ret); + } + + return ERR_OK; +} + +// Open an SSL connection using a PSK (pre-shared-key) cipher suite. +int tcp_ssl_new_psk_client(struct tcp_pcb *tcp, const char* psk_ident, const char* pskey) { + tcp_ssl_t* tcp_ssl; + + if(tcp == NULL) return -1; + if(tcp_ssl_get(tcp) != NULL) return -1; + + tcp_ssl = tcp_ssl_new(tcp); + if(tcp_ssl == NULL) return -1; + + mbedtls_entropy_init(&tcp_ssl->entropy_ctx); + mbedtls_ctr_drbg_init(&tcp_ssl->drbg_ctx); + mbedtls_ssl_init(&tcp_ssl->ssl_ctx); + mbedtls_ssl_config_init(&tcp_ssl->ssl_conf); + + mbedtls_ctr_drbg_seed(&tcp_ssl->drbg_ctx, mbedtls_entropy_func, + &tcp_ssl->entropy_ctx, (const unsigned char*)pers, strlen(pers)); + + if(mbedtls_ssl_config_defaults(&tcp_ssl->ssl_conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) { + TCP_SSL_DEBUG("error setting SSL config.\n"); + + tcp_ssl_free(tcp); + return -1; + } + + int ret = 0; + + TCP_SSL_DEBUG("setting the pre-shared key.\n"); + // convert PSK from hex string to binary + if ((strlen(pskey) & 1) != 0 || strlen(pskey) > 2*MBEDTLS_PSK_MAX_LEN) { + TCP_SSL_DEBUG(" failed\n ! pre-shared key not valid hex or too long\n\n"); + return -1; + } + unsigned char psk[MBEDTLS_PSK_MAX_LEN]; + size_t psk_len = strlen(pskey)/2; + for (int j=0; j= '0' && c <= '9') c -= '0'; + else if (c >= 'A' && c <= 'F') c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') c -= 'a' - 10; + else return -1; + psk[j/2] = c<<4; + c = pskey[j+1]; + if (c >= '0' && c <= '9') c -= '0'; + else if (c >= 'A' && c <= 'F') c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') c -= 'a' - 10; + else return -1; + psk[j/2] |= c; + } + // set mbedtls config + ret = mbedtls_ssl_conf_psk(&tcp_ssl->ssl_conf, psk, psk_len, + (const unsigned char *)psk_ident, strlen(psk_ident)); + if (ret != 0) { + TCP_SSL_DEBUG(" failed\n ! mbedtls_ssl_conf_psk returned -0x%x\n\n", -ret); + return handle_error(ret); + } + + mbedtls_ssl_conf_rng(&tcp_ssl->ssl_conf, mbedtls_ctr_drbg_random, &tcp_ssl->drbg_ctx); + + if ((ret = mbedtls_ssl_setup(&tcp_ssl->ssl_ctx, &tcp_ssl->ssl_conf)) != 0) { + tcp_ssl_free(tcp); + return handle_error(ret); } @@ -302,7 +382,7 @@ int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) { if(tcp == NULL) { return -1; } - + tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp); if(tcp_ssl == NULL){ @@ -351,7 +431,7 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { tcp_ssl->tcp_pbuf = p; tcp_ssl->pbuf_offset = 0; - + do { if(tcp_ssl->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER) { TCP_SSL_DEBUG("start handshake: %d\n", tcp_ssl->ssl_ctx.state); @@ -467,4 +547,4 @@ void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg){ } } -#endif // ASYNC_TCP_SSL_ENABLED \ No newline at end of file +#endif // ASYNC_TCP_SSL_ENABLED diff --git a/src/tcp_mbedtls.h b/src/tcp_mbedtls.h index ff0c9a87..492c70bb 100644 --- a/src/tcp_mbedtls.h +++ b/src/tcp_mbedtls.h @@ -31,6 +31,7 @@ typedef void (* tcp_ssl_error_cb_t)(void *arg, struct tcp_pcb *tcp, int8_t error uint8_t tcp_ssl_has_client(); int tcp_ssl_new_client(struct tcp_pcb *tcp, const char* hostname, const char* root_ca, const size_t root_ca_len); +int tcp_ssl_new_psk_client(struct tcp_pcb *tcp, const char* psk_ident, const char* psk); int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len); int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p); int tcp_ssl_handshake_step(struct tcp_pcb *tcp); From f286e8adb1feb33659245a669b10e8c2336c0bfb Mon Sep 17 00:00:00 2001 From: Franz Auernigg Date: Thu, 1 Oct 2020 01:41:45 +0200 Subject: [PATCH 18/19] enable async tcp for c and cpp compiler --- component.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/component.mk b/component.mk index bb5bb161..65af2463 100644 --- a/component.mk +++ b/component.mk @@ -1,3 +1,5 @@ COMPONENT_ADD_INCLUDEDIRS := src COMPONENT_SRCDIRS := src CXXFLAGS += -fno-rtti +CXXFLAGS += -DASYNC_TCP_SSL_ENABLED=1 +CPPFLAGS += -DASYNC_TCP_SSL_ENABLED=1 \ No newline at end of file From 27261ed517af5a13bfe04d9b7e55878ea17493f7 Mon Sep 17 00:00:00 2001 From: Franz Auernigg Date: Thu, 1 Oct 2020 01:42:15 +0200 Subject: [PATCH 19/19] fix compiler warning init order --- src/AsyncTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index aaaeb512..2d007132 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -425,8 +425,8 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) , _timeout_cb_arg(0) , _pcb_busy(false) #if ASYNC_TCP_SSL_ENABLED -, _root_ca(NULL) , _root_ca_len(0) +, _root_ca(NULL) , _pcb_secure(false) , _handshake_done(true) , _psk_ident(0)