From e30447449feac1588945dd544d39405a4ba0fa20 Mon Sep 17 00:00:00 2001 From: copercini Date: Fri, 10 Mar 2017 11:52:50 -0300 Subject: [PATCH] WiFiSecureClient fixes and improvements (#255) * Add CA certificate in example SHA1 fingerprint is broken now: more info: https://shattered.io * Best error handling When occur an error in WiFiClientSecure library just return the error message and clean the context avoiding crash - fix for https://github.com/espressif/arduino-esp32/issues/211 Translate MbedTLS error codes in messages for best understanding * Declarate certificates as const mbedtls_pk_parse_key needs a const unsigned char * certificate. In old implementation the certificate was declarated as char * so first it converts to unsigned and after to const. When we convert signed to unsigned it may result in a +1 larger output. Fix issue https://github.com/espressif/arduino-esp32/issues/223 --- .../WiFiClientSecure/WiFiClientSecure.ino | 85 ++++-- .../WiFiClientSecure/src/WiFiClientSecure.cpp | 35 ++- .../WiFiClientSecure/src/WiFiClientSecure.h | 16 +- libraries/WiFiClientSecure/src/ssl_client.cpp | 278 ++++++++++-------- libraries/WiFiClientSecure/src/ssl_client.h | 4 +- 5 files changed, 246 insertions(+), 172 deletions(-) diff --git a/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino b/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino index 72edf966..25ad5342 100644 --- a/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino +++ b/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino @@ -8,14 +8,47 @@ #include -char ssid[] = "your_network_name"; // your network SSID (name of wifi network) -char pass[] = "your_password"; // your network password +const char* ssid = "your-ssid"; // your network SSID (name of wifi network) +const char* password = "your-password"; // your network password -char server[] = "www.howsmyssl.com"; // Server URL -// You can use x.509 certificates if you want -//unsigned char test_ca_cert[] = ""; //For the usage of verifying server -//unsigned char test_client_key[] = ""; //For the usage of verifying client -//unsigned char test_client_cert[] = ""; //For the usage of verifying client +const char* server = "www.howsmyssl.com"; // Server URL + +// www.howsmyssl.com CA certificate, to verify the server +// change it to your server CA certificate +// SHA1 fingerprint is broken now! + +const char* test_ca_cert = \ +"-----BEGIN CERTIFICATE-----\n" \ +"MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n" \ +"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \ +"DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n" \ +"SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n" \ +"GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" \ +"AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n" \ +"q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n" \ +"SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n" \ +"Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n" \ +"a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n" \ +"/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n" \ +"AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n" \ +"CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n" \ +"bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n" \ +"c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n" \ +"VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n" \ +"ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n" \ +"MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n" \ +"Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n" \ +"AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n" \ +"uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n" \ +"wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n" \ +"X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n" \ +"PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n" \ +"KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n" \ +"-----END CERTIFICATE-----\n"; + +// You can use x.509 client certificates if you want +//const char* test_client_key = ""; //to verify the client +//const char* test_client_cert = ""; //to verify the client WiFiClientSecure client; @@ -27,7 +60,7 @@ void setup() { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); - WiFi.begin(ssid, pass); + WiFi.begin(ssid, password); // attempt to connect to Wifi network: while (WiFi.status() != WL_CONNECTED) { @@ -38,39 +71,43 @@ void setup() { Serial.print("Connected to "); Serial.println(ssid); + + client.setCACert(test_ca_cert); + //client.setCertificate(certificateBuff); // for client verification + //client.setPrivateKey(privateKeyBuff); // for client verification Serial.println("\nStarting connection to server..."); - if (client.connect(server, 443)) { //client.connect(server, 443, test_ca_cert, test_client_cert, test_client_key) + if (!client.connect(server, 443)) + Serial.println("Connection failed!"); + else { Serial.println("Connected to server!"); // Make a HTTP request: client.println("GET https://www.howsmyssl.com/a/check HTTP/1.0"); client.println("Host: www.howsmyssl.com"); client.println("Connection: close"); client.println(); - } - else - Serial.println("Connection failed!"); Serial.print("Waiting for response "); //WiFiClientSecure uses a non blocking implementation while (!client.available()){ delay(50); // Serial.print("."); } - // if there are incoming bytes available - // from the server, read them and print them: - while (client.available()) { - char c = client.read(); - Serial.write(c); - } + // if there are incoming bytes available + // from the server, read them and print them: + while (client.available()) { + char c = client.read(); + Serial.write(c); + } - // if the server's disconnected, stop the client: - if (!client.connected()) { - Serial.println(); - Serial.println("disconnecting from server."); - client.stop(); + // if the server's disconnected, stop the client: + if (!client.connected()) { + Serial.println(); + Serial.println("disconnecting from server."); + client.stop(); + } } } void loop() { // do nothing -} \ No newline at end of file +} diff --git a/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp b/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp index a3da66d2..d215c837 100644 --- a/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp +++ b/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp @@ -39,7 +39,7 @@ WiFiClientSecure::WiFiClientSecure() _CA_cert = NULL; _cert = NULL; _private_key = NULL; - next = NULL; + next = NULL; } @@ -58,7 +58,7 @@ WiFiClientSecure::WiFiClientSecure(int sock) _CA_cert = NULL; _cert = NULL; _private_key = NULL; - next = NULL; + next = NULL; } WiFiClientSecure::~WiFiClientSecure() @@ -76,34 +76,37 @@ WiFiClientSecure &WiFiClientSecure::operator=(const WiFiClientSecure &other) void WiFiClientSecure::stop() { - if (_connected && sslclient->socket >= 0) { - stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key); + if (sslclient->socket >= 0) { + close(sslclient->socket); sslclient->socket = -1; _connected = false; } + stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key); } int WiFiClientSecure::connect(IPAddress ip, uint16_t port) { - return connect(ip, port, _CA_cert, _cert, _private_key); + return connect(ip, port, _CA_cert, _cert, _private_key); } int WiFiClientSecure::connect(const char *host, uint16_t port) { - return connect(host, port, _CA_cert, _cert, _private_key); + return connect(host, port, _CA_cert, _cert, _private_key); } -int WiFiClientSecure::connect(IPAddress ip, uint16_t port, unsigned char *_CA_cert, unsigned char *_cert, unsigned char *_private_key) +int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key) { int ret = start_ssl_client(sslclient, ip, port, _CA_cert, _cert, _private_key); if (ret < 0) { log_e("lwip_connect_r: %d", errno); + stop(); + return 0; } _connected = true; return 1; } -int WiFiClientSecure::connect(const char *host, uint16_t port, unsigned char *_CA_cert, unsigned char *_cert, unsigned char *_private_key) +int WiFiClientSecure::connect(const char *host, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key) { struct hostent *server; server = gethostbyname(host); @@ -137,7 +140,7 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size) } int res = send_ssl_data(sslclient, buf, size); if (res < 0) { - log_e("%d", errno); + stop(); res = 0; } @@ -150,8 +153,8 @@ int WiFiClientSecure::read(uint8_t *buf, size_t size) return -1; } int res = get_ssl_receive(sslclient, buf, size); - if (res < 0 && errno != EWOULDBLOCK) { - printf("%d", errno); + if (res < 0) { + stop(); } return res; @@ -163,7 +166,9 @@ int WiFiClientSecure::available() return 0; } int res = data_to_read(sslclient); - + if (res < 0 ) { + stop(); + } return res; } @@ -175,17 +180,17 @@ uint8_t WiFiClientSecure::connected() return _connected; } -void WiFiClientSecure::setCACert(unsigned char *rootCA) +void WiFiClientSecure::setCACert (const char *rootCA) { _CA_cert = rootCA; } -void WiFiClientSecure::setCertificate (unsigned char *client_ca) +void WiFiClientSecure::setCertificate (const char *client_ca) { _cert = client_ca; } -void WiFiClientSecure::setPrivateKey (unsigned char *private_key) +void WiFiClientSecure::setPrivateKey (const char *private_key) { _private_key = private_key; } diff --git a/libraries/WiFiClientSecure/src/WiFiClientSecure.h b/libraries/WiFiClientSecure/src/WiFiClientSecure.h index a3d7fc6c..f0f0a7bd 100644 --- a/libraries/WiFiClientSecure/src/WiFiClientSecure.h +++ b/libraries/WiFiClientSecure/src/WiFiClientSecure.h @@ -31,9 +31,9 @@ protected: bool _connected; sslclient_context *sslclient; - unsigned char *_CA_cert; - unsigned char *_cert; - unsigned char *_private_key; + const char *_CA_cert; + const char *_cert; + const char *_private_key; public: WiFiClientSecure *next; @@ -42,8 +42,8 @@ public: ~WiFiClientSecure(); int connect(IPAddress ip, uint16_t port); int connect(const char *host, uint16_t port); - int connect(IPAddress ip, uint16_t port, unsigned char *rootCABuff, unsigned char *cli_cert, unsigned char *cli_key); - int connect(const char *host, uint16_t port, unsigned char *rootCABuff, unsigned char *cli_cert, unsigned char *cli_key); + int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key); + int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key); size_t write(uint8_t data); size_t write(const uint8_t *buf, size_t size); int available(); @@ -57,9 +57,9 @@ public: void stop(); uint8_t connected(); - void setCACert(unsigned char *rootCA); - void setCertificate(unsigned char *client_ca); - void setPrivateKey (unsigned char *private_key); + void setCACert(const char *rootCA); + void setCertificate(const char *client_ca); + void setPrivateKey (const char *private_key); operator bool() { diff --git a/libraries/WiFiClientSecure/src/ssl_client.cpp b/libraries/WiFiClientSecure/src/ssl_client.cpp index 90d7b081..72294b24 100644 --- a/libraries/WiFiClientSecure/src/ssl_client.cpp +++ b/libraries/WiFiClientSecure/src/ssl_client.cpp @@ -72,6 +72,18 @@ static void mbedtls_debug(void *ctx, int level, #endif +static int handle_error(int err) +{ +#ifdef MBEDTLS_ERROR_C + char error_buf[100]; + + mbedtls_strerror(err, error_buf, 100); + printf("\n%s\n", error_buf); +#endif + printf("\nMbedTLS message code: %d\n", err); + return err; +} + void ssl_init(sslclient_context *ssl_client) @@ -88,7 +100,7 @@ void ssl_init(sslclient_context *ssl_client) -int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, unsigned char *rootCABuff, unsigned char *cli_cert, unsigned char *cli_key) +int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key) { char buf[512]; int ret, flags, len, timeout; @@ -96,88 +108,99 @@ int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t DEBUG_PRINT("Free heap before TLS %u\n", xPortGetFreeHeapSize()); - do { - ssl_client->socket = -1; - ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (ssl_client->socket < 0) { - printf("\r\nERROR opening socket\r\n"); - return ssl_client->socket; - } + ssl_client->socket = -1; + + ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (ssl_client->socket < 0) { + printf("\r\nERROR opening socket\r\n"); + return ssl_client->socket; + } - struct sockaddr_in serv_addr; - memset(&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = ipAddress; - serv_addr.sin_port = htons(port); + struct sockaddr_in serv_addr; + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = ipAddress; + serv_addr.sin_port = htons(port); - if (lwip_connect(ssl_client->socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) { - timeout = 30000; - lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); - lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); - lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); - lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); - } else { - printf("\r\nConnect to Server failed!\r\n"); - ret = -1; - break; - } + if (lwip_connect(ssl_client->socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) { + timeout = 30000; + lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); + lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); + } else { + printf("\r\nConnect to Server failed!\r\n"); + return -1; + + } - fcntl( ssl_client->socket, F_SETFL, fcntl( ssl_client->socket, F_GETFL, 0 ) | O_NONBLOCK ); + fcntl( ssl_client->socket, F_SETFL, fcntl( ssl_client->socket, F_GETFL, 0 ) | O_NONBLOCK ); - DEBUG_PRINT( "Seeding the random number generator\n"); - mbedtls_entropy_init(&ssl_client->entropy_ctx); + DEBUG_PRINT( "Seeding the random number generator\n"); + mbedtls_entropy_init(&ssl_client->entropy_ctx); - if ((ret = mbedtls_ctr_drbg_seed(&ssl_client->drbg_ctx, mbedtls_entropy_func, - &ssl_client->entropy_ctx, (const unsigned char *) pers, strlen(pers))) != 0) { - printf( "mbedtls_ctr_drbg_seed returned %d \n", ret); - break; - } + ret = mbedtls_ctr_drbg_seed(&ssl_client->drbg_ctx, mbedtls_entropy_func, + &ssl_client->entropy_ctx, (const unsigned char *) pers, strlen(pers)); + + + + + if (ret < 0) { + return handle_error(ret); + } - /* MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and + /* MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and MBEDTLS_SSL_VERIFY_NONE if not. */ - if (rootCABuff != NULL) { - DEBUG_PRINT( "Loading CA cert\n"); - mbedtls_x509_crt_init(&ssl_client->ca_cert); - mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); - ret = mbedtls_x509_crt_parse(&ssl_client->ca_cert, (const unsigned char *)rootCABuff, strlen((const char *)rootCABuff) + 1); - mbedtls_ssl_conf_ca_chain(&ssl_client->ssl_conf, &ssl_client->ca_cert, NULL); - //mbedtls_ssl_conf_verify(&ssl_client->ssl_ctx, my_verify, NULL ); - if (ret < 0) { - printf( "CA cert: mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - break; - } - } else { - mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); + if (rootCABuff != NULL) { + DEBUG_PRINT( "Loading CA cert\n"); + mbedtls_x509_crt_init(&ssl_client->ca_cert); + mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); + ret = mbedtls_x509_crt_parse(&ssl_client->ca_cert, (const unsigned char *)rootCABuff, strlen(rootCABuff) + 1); + mbedtls_ssl_conf_ca_chain(&ssl_client->ssl_conf, &ssl_client->ca_cert, NULL); + //mbedtls_ssl_conf_verify(&ssl_client->ssl_ctx, my_verify, NULL ); + if (ret < 0) { + return handle_error(ret); + + + + + } + } else { + + mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); + } + + if (cli_cert != NULL && cli_key != NULL) { + mbedtls_x509_crt_init(&ssl_client->client_cert); + mbedtls_pk_init(&ssl_client->client_key); + + DEBUG_PRINT( "Loading CRT cert\n"); + + ret = mbedtls_x509_crt_parse(&ssl_client->client_cert, (const unsigned char *)cli_cert, strlen(cli_cert) + 1); + + + + + if (ret < 0) { + return handle_error(ret); } - if (cli_cert != NULL && cli_key != NULL) { - mbedtls_x509_crt_init(&ssl_client->client_cert); - mbedtls_pk_init(&ssl_client->client_key); + DEBUG_PRINT( "Loading private key\n"); + ret = mbedtls_pk_parse_key(&ssl_client->client_key, (const unsigned char *)cli_key, strlen(cli_key) + 1, NULL, 0); + + - DEBUG_PRINT( "Loading CRT cert\n"); - - ret = mbedtls_x509_crt_parse(&ssl_client->client_cert, (const unsigned char *)cli_cert, strlen((const char *)cli_cert) + 1); - - if (ret < 0) { - printf( "CRT cert: mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - break; - } - - DEBUG_PRINT( "Loading private key\n"); - ret = mbedtls_pk_parse_key(&ssl_client->client_key, (const unsigned char *)cli_key, strlen((const char *)cli_key) + 1, NULL, 0); - - if (ret < 0) { - printf( "PRIVATE KEY: mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - break; - } - - mbedtls_ssl_conf_own_cert(&ssl_client->ssl_conf, &ssl_client->client_cert, &ssl_client->client_key); + if (ret != 0) { + return handle_error(ret); } - /* + mbedtls_ssl_conf_own_cert(&ssl_client->ssl_conf, &ssl_client->client_cert, &ssl_client->client_key); + } + + /* // TODO: implement match CN verification DEBUG_PRINT( "Setting hostname for TLS session...\n"); @@ -185,69 +208,74 @@ int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t // Hostname set here should match CN in server certificate if((ret = mbedtls_ssl_set_hostname(&ssl_client->ssl_ctx, host)) != 0) { - printf( "mbedtls_ssl_set_hostname returned -0x%x\n", -ret); - break; + return handle_error(ret); + } */ - DEBUG_PRINT( "Setting up the SSL/TLS structure...\n"); + DEBUG_PRINT( "Setting up the SSL/TLS structure...\n"); - if ((ret = mbedtls_ssl_config_defaults(&ssl_client->ssl_conf, - MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - printf( "mbedtls_ssl_config_defaults returned %d\n", ret); - break; - } + if ((ret = mbedtls_ssl_config_defaults(&ssl_client->ssl_conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + return handle_error(ret); + + } - mbedtls_ssl_conf_rng(&ssl_client->ssl_conf, mbedtls_ctr_drbg_random, &ssl_client->drbg_ctx); + mbedtls_ssl_conf_rng(&ssl_client->ssl_conf, mbedtls_ctr_drbg_random, &ssl_client->drbg_ctx); #ifdef CONFIG_MBEDTLS_DEBUG - mbedtls_debug_set_threshold(MBEDTLS_DEBUG_LEVEL); - mbedtls_ssl_conf_dbg(&ssl_client->ssl_conf, mbedtls_debug, NULL); + mbedtls_debug_set_threshold(MBEDTLS_DEBUG_LEVEL); + mbedtls_ssl_conf_dbg(&ssl_client->ssl_conf, mbedtls_debug, NULL); #endif - if ((ret = mbedtls_ssl_setup(&ssl_client->ssl_ctx, &ssl_client->ssl_conf)) != 0) { - printf( "mbedtls_ssl_setup returned -0x%x\n\n", -ret); - break; + if ((ret = mbedtls_ssl_setup(&ssl_client->ssl_ctx, &ssl_client->ssl_conf)) != 0) { + return handle_error(ret); + + } + + mbedtls_ssl_set_bio(&ssl_client->ssl_ctx, &ssl_client->socket, mbedtls_net_send, mbedtls_net_recv, NULL ); + + DEBUG_PRINT( "Performing the SSL/TLS handshake...\n"); + + while ((ret = mbedtls_ssl_handshake(&ssl_client->ssl_ctx)) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) { + return handle_error(ret); + + + + } + delay(10); + vPortYield(); + } - mbedtls_ssl_set_bio(&ssl_client->ssl_ctx, &ssl_client->socket, mbedtls_net_send, mbedtls_net_recv, NULL ); - DEBUG_PRINT( "Performing the SSL/TLS handshake...\n"); - - while ((ret = mbedtls_ssl_handshake(&ssl_client->ssl_ctx)) != 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) { - printf( "mbedtls_ssl_handshake returned -0x%x\n", -ret); - break; - } - delay(10); - vPortYield(); + if (cli_cert != NULL && cli_key != NULL) { + DEBUG_PRINT("Protocol is %s \nCiphersuite is %s\n", mbedtls_ssl_get_version(&ssl_client->ssl_ctx), mbedtls_ssl_get_ciphersuite(&ssl_client->ssl_ctx)); + if ((ret = mbedtls_ssl_get_record_expansion(&ssl_client->ssl_ctx)) >= 0) { + DEBUG_PRINT("Record expansion is %d\n", ret); + } else { + DEBUG_PRINT("Record expansion is unknown (compression)\n"); + } + } - if (cli_cert != NULL && cli_key != NULL) { - DEBUG_PRINT("Protocol is %s \nCiphersuite is %s\n", mbedtls_ssl_get_version(&ssl_client->ssl_ctx), mbedtls_ssl_get_ciphersuite(&ssl_client->ssl_ctx)); - if ((ret = mbedtls_ssl_get_record_expansion(&ssl_client->ssl_ctx)) >= 0) { - DEBUG_PRINT("Record expansion is %d\n", ret); - } else { - DEBUG_PRINT("Record expansion is unknown (compression)\n"); - } - } + DEBUG_PRINT( "Verifying peer X.509 certificate...\n"); + if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0) { + printf( "Failed to verify peer certificate!\n"); + bzero(buf, sizeof(buf)); + mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); + printf( "verification info: %s\n", buf); + stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue. + return handle_error(ret); + } else { + DEBUG_PRINT( "Certificate verified.\n"); + } - DEBUG_PRINT( "Verifying peer X.509 certificate...\n"); - - if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0) { - printf( "Failed to verify peer certificate!\n"); - bzero(buf, sizeof(buf)); - mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); - printf( "verification info: %s\n", buf); - stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue. - } else { - DEBUG_PRINT( "Certificate verified.\n"); - } - - } while (0); + DEBUG_PRINT("Free heap after TLS %u\n", xPortGetFreeHeapSize()); @@ -255,11 +283,15 @@ int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t } -void stop_ssl_socket(sslclient_context *ssl_client, unsigned char *rootCABuff, unsigned char *cli_cert, unsigned char *cli_key) +void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key) { DEBUG_PRINT( "\nCleaning SSL connection.\n"); - close(ssl_client->socket); - ssl_client->socket = -1; + + if (ssl_client->socket >= 0) { + close(ssl_client->socket); + ssl_client->socket = -1; + } + mbedtls_ssl_free(&ssl_client->ssl_ctx); mbedtls_ssl_config_free(&ssl_client->ssl_conf); mbedtls_ctr_drbg_free(&ssl_client->drbg_ctx); @@ -287,8 +319,8 @@ int data_to_read(sslclient_context *ssl_client) //printf("RET: %i\n",ret); //for low level debug res = mbedtls_ssl_get_bytes_avail(&ssl_client->ssl_ctx); //printf("RES: %i\n",res); - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0 && ret != -76) { - printf("MbedTLS error %i", ret); + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0 && ret != -76) { //RC:76 sockets is not connected + return handle_error(ret); } return res; @@ -302,9 +334,9 @@ int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t l int ret = -1; while ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) { - printf( "mbedtls_ssl_write returned -0x%x\n", -ret); - break; + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) { //RC:76 sockets is not connected + return handle_error(ret); + } } diff --git a/libraries/WiFiClientSecure/src/ssl_client.h b/libraries/WiFiClientSecure/src/ssl_client.h index a4300572..dfa97048 100644 --- a/libraries/WiFiClientSecure/src/ssl_client.h +++ b/libraries/WiFiClientSecure/src/ssl_client.h @@ -28,8 +28,8 @@ typedef struct sslclient_context { void ssl_init(sslclient_context *ssl_client); -int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, unsigned char *rootCABuff, unsigned char *cli_cert, unsigned char *cli_key); -void stop_ssl_socket(sslclient_context *ssl_client, unsigned char *rootCABuff, unsigned char *cli_cert, unsigned char *cli_key); +int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key); +void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key); int data_to_read(sslclient_context *ssl_client); int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len); int get_ssl_receive(sslclient_context *ssl_client, uint8_t *data, int length);