Skip to content

Commit bcb16e7

Browse files
author
blue-2357
committed
Support self signed certificates (#291)
* Support self signed certificates Fix for espressif/arduino-esp32#265 mbedtls_ssl_conf_authmode was defined before mbedtls_ssl_config_defaults causing several bugs when no CA certificate is defined. * Implement Arduino's log facility Replace printf by ESP log handling * Remove \n from debug messages log_ doesn't need \n to break line.
1 parent daf90c5 commit bcb16e7

File tree

1 file changed

+44
-142
lines changed

1 file changed

+44
-142
lines changed
+44-142
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,55 @@
11
/* Provide SSL/TLS functions to ESP32 with Arduino IDE
22
*
3-
* Adapted from the ssl_client1 example in mbedtls.
3+
* Adapted from the ssl_client1 example of mbedtls.
44
*
55
* Original Copyright (C) 2006-2015, ARM Limited, All Rights Reserved, Apache 2.0 License.
66
* Additions Copyright (C) 2017 Evandro Luis Copercini, Apache 2.0 License.
77
*/
88

99
#include "Arduino.h"
10+
#include <esp32-hal-log.h>
1011
#include <lwip/sockets.h>
1112
#include <lwip/err.h>
1213
#include <lwip/sockets.h>
1314
#include <lwip/sys.h>
1415
#include <lwip/netdb.h>
15-
1616
#include "ssl_client.h"
1717

18-
1918
const char *pers = "esp32-tls";
2019

21-
#define DEBUG //Comment to supress debug messages
22-
23-
#ifdef DEBUG
24-
#define DEBUG_PRINT(...) printf( __VA_ARGS__ )
25-
#else
26-
#define DEBUG_PRINT(x)
27-
#endif
28-
29-
#ifdef CONFIG_MBEDTLS_DEBUG
30-
31-
#define MBEDTLS_DEBUG_LEVEL 4
32-
33-
/* mbedtls debug function that translates mbedTLS debug output
34-
to ESP_LOGx debug output.
35-
36-
MBEDTLS_DEBUG_LEVEL 4 means all mbedTLS debug output gets sent here,
37-
and then filtered to the ESP logging mechanism.
38-
*/
39-
static void mbedtls_debug(void *ctx, int level,
40-
const char *file, int line,
41-
const char *str)
42-
{
43-
const char *MBTAG = "mbedtls";
44-
char *file_sep;
45-
46-
/* Shorten 'file' from the whole file path to just the filename
47-
48-
This is a bit wasteful because the macros are compiled in with
49-
the full _FILE_ path in each case.
50-
*/
51-
file_sep = rindex(file, '/');
52-
if (file_sep) {
53-
file = file_sep + 1;
54-
}
55-
56-
switch (level) {
57-
case 1:
58-
printf( "%s:%d %s \n", file, line, str);
59-
break;
60-
case 2:
61-
case 3:
62-
printf( "%s:%d %s \n", file, line, str);
63-
case 4:
64-
printf( "%s:%d %s \n", file, line, str);
65-
break;
66-
default:
67-
printf( "Unexpected log level %d: %s \n", level, str);
68-
break;
69-
}
70-
}
71-
72-
#endif
73-
74-
7520
static int handle_error(int err)
7621
{
7722
#ifdef MBEDTLS_ERROR_C
7823
char error_buf[100];
79-
8024
mbedtls_strerror(err, error_buf, 100);
81-
printf("\n%s\n", error_buf);
25+
log_e("%s", error_buf);
8226
#endif
83-
printf("\nMbedTLS message code: %d\n", err);
27+
log_e("MbedTLS message code: %d", err);
8428
return err;
8529
}
8630

8731

88-
8932
void ssl_init(sslclient_context *ssl_client)
9033
{
91-
/*
92-
* Initialize the RNG and the session data
93-
*/
94-
9534
mbedtls_ssl_init(&ssl_client->ssl_ctx);
9635
mbedtls_ssl_config_init(&ssl_client->ssl_conf);
97-
9836
mbedtls_ctr_drbg_init(&ssl_client->drbg_ctx);
9937
}
10038

10139

102-
10340
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)
10441
{
10542
char buf[512];
10643
int ret, flags, len, timeout;
10744
int enable = 1;
108-
DEBUG_PRINT("Free heap before TLS %u\n", xPortGetFreeHeapSize());
109-
45+
log_i("Free heap before TLS %u", xPortGetFreeHeapSize());
11046

47+
log_i("Starting socket");
11148
ssl_client->socket = -1;
112-
49+
11350
ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
11451
if (ssl_client->socket < 0) {
115-
printf("\r\nERROR opening socket\r\n");
52+
log_e("ERROR opening socket");
11653
return ssl_client->socket;
11754
}
11855

@@ -129,69 +66,61 @@ int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t
12966
lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
13067
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
13168
} else {
132-
printf("\r\nConnect to Server failed!\r\n");
69+
log_e("Connect to Server failed!");
13370
return -1;
134-
13571
}
13672

13773
fcntl( ssl_client->socket, F_SETFL, fcntl( ssl_client->socket, F_GETFL, 0 ) | O_NONBLOCK );
13874

139-
140-
DEBUG_PRINT( "Seeding the random number generator\n");
75+
log_i("Seeding the random number generator");
14176
mbedtls_entropy_init(&ssl_client->entropy_ctx);
14277

14378
ret = mbedtls_ctr_drbg_seed(&ssl_client->drbg_ctx, mbedtls_entropy_func,
14479
&ssl_client->entropy_ctx, (const unsigned char *) pers, strlen(pers));
145-
146-
147-
148-
14980
if (ret < 0) {
15081
return handle_error(ret);
15182
}
15283

84+
log_i("Setting up the SSL/TLS structure...");
85+
86+
if ((ret = mbedtls_ssl_config_defaults(&ssl_client->ssl_conf,
87+
MBEDTLS_SSL_IS_CLIENT,
88+
MBEDTLS_SSL_TRANSPORT_STREAM,
89+
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
90+
return handle_error(ret);
91+
}
15392

15493
/* MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and
15594
MBEDTLS_SSL_VERIFY_NONE if not.
15695
*/
15796
if (rootCABuff != NULL) {
158-
DEBUG_PRINT( "Loading CA cert\n");
97+
log_i("Loading CA cert");
15998
mbedtls_x509_crt_init(&ssl_client->ca_cert);
16099
mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
161100
ret = mbedtls_x509_crt_parse(&ssl_client->ca_cert, (const unsigned char *)rootCABuff, strlen(rootCABuff) + 1);
162101
mbedtls_ssl_conf_ca_chain(&ssl_client->ssl_conf, &ssl_client->ca_cert, NULL);
163102
//mbedtls_ssl_conf_verify(&ssl_client->ssl_ctx, my_verify, NULL );
164103
if (ret < 0) {
165104
return handle_error(ret);
166-
167-
168-
169-
170105
}
171106
} else {
172-
173107
mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE);
108+
log_i("WARNING: Use certificates for a more secure communication!");
174109
}
175110

176111
if (cli_cert != NULL && cli_key != NULL) {
177112
mbedtls_x509_crt_init(&ssl_client->client_cert);
178113
mbedtls_pk_init(&ssl_client->client_key);
179114

180-
DEBUG_PRINT( "Loading CRT cert\n");
115+
log_i("Loading CRT cert");
181116

182117
ret = mbedtls_x509_crt_parse(&ssl_client->client_cert, (const unsigned char *)cli_cert, strlen(cli_cert) + 1);
183-
184-
185-
186-
187118
if (ret < 0) {
188119
return handle_error(ret);
189120
}
190121

191-
DEBUG_PRINT( "Loading private key\n");
122+
log_i("Loading private key");
192123
ret = mbedtls_pk_parse_key(&ssl_client->client_key, (const unsigned char *)cli_key, strlen(cli_key) + 1, NULL, 0);
193-
194-
195124

196125
if (ret != 0) {
197126
return handle_error(ret);
@@ -203,89 +132,66 @@ int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t
203132
/*
204133
// TODO: implement match CN verification
205134
206-
DEBUG_PRINT( "Setting hostname for TLS session...\n");
135+
log_i("Setting hostname for TLS session...");
207136
208137
// Hostname set here should match CN in server certificate
209138
if((ret = mbedtls_ssl_set_hostname(&ssl_client->ssl_ctx, host)) != 0)
210139
{
211140
return handle_error(ret);
212-
213-
}
214-
*/
215141
216-
DEBUG_PRINT( "Setting up the SSL/TLS structure...\n");
217-
218-
if ((ret = mbedtls_ssl_config_defaults(&ssl_client->ssl_conf,
219-
MBEDTLS_SSL_IS_CLIENT,
220-
MBEDTLS_SSL_TRANSPORT_STREAM,
221-
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
222-
return handle_error(ret);
223-
224-
}
142+
}
143+
*/
225144

226145
mbedtls_ssl_conf_rng(&ssl_client->ssl_conf, mbedtls_ctr_drbg_random, &ssl_client->drbg_ctx);
227-
#ifdef CONFIG_MBEDTLS_DEBUG
228-
mbedtls_debug_set_threshold(MBEDTLS_DEBUG_LEVEL);
229-
mbedtls_ssl_conf_dbg(&ssl_client->ssl_conf, mbedtls_debug, NULL);
230-
#endif
231146

232147
if ((ret = mbedtls_ssl_setup(&ssl_client->ssl_ctx, &ssl_client->ssl_conf)) != 0) {
233148
return handle_error(ret);
234-
235149
}
236150

237151
mbedtls_ssl_set_bio(&ssl_client->ssl_ctx, &ssl_client->socket, mbedtls_net_send, mbedtls_net_recv, NULL );
238152

239-
DEBUG_PRINT( "Performing the SSL/TLS handshake...\n");
153+
log_i("Performing the SSL/TLS handshake...");
240154

241155
while ((ret = mbedtls_ssl_handshake(&ssl_client->ssl_ctx)) != 0) {
242-
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) {
156+
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) { //workaround for bug: https://github.com/espressif/esp-idf/issues/434
243157
return handle_error(ret);
244-
245-
246-
247-
248158
}
249159
delay(10);
250160
vPortYield();
251161
}
252162

253163

254164
if (cli_cert != NULL && cli_key != NULL) {
255-
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));
165+
log_i("Protocol is %s Ciphersuite is %s", mbedtls_ssl_get_version(&ssl_client->ssl_ctx), mbedtls_ssl_get_ciphersuite(&ssl_client->ssl_ctx));
256166
if ((ret = mbedtls_ssl_get_record_expansion(&ssl_client->ssl_ctx)) >= 0) {
257-
DEBUG_PRINT("Record expansion is %d\n", ret);
167+
log_i("Record expansion is %d", ret);
258168
} else {
259-
DEBUG_PRINT("Record expansion is unknown (compression)\n");
260-
169+
log_i("Record expansion is unknown (compression)");
261170
}
262171
}
263172

264-
265-
DEBUG_PRINT( "Verifying peer X.509 certificate...\n");
173+
log_i("Verifying peer X.509 certificate...");
266174

267175
if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0) {
268-
printf( "Failed to verify peer certificate!\n");
176+
log_e("Failed to verify peer certificate!");
269177
bzero(buf, sizeof(buf));
270178
mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags);
271-
printf( "verification info: %s\n", buf);
179+
log_e("verification info: %s", buf);
272180
stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue.
273181
return handle_error(ret);
274182
} else {
275-
DEBUG_PRINT( "Certificate verified.\n");
183+
log_i("Certificate verified.");
276184
}
277185

278-
279-
280-
DEBUG_PRINT("Free heap after TLS %u\n", xPortGetFreeHeapSize());
186+
log_i("Free heap after TLS %u", xPortGetFreeHeapSize());
281187

282188
return ssl_client->socket;
283189
}
284190

285191

286192
void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key)
287193
{
288-
DEBUG_PRINT( "\nCleaning SSL connection.\n");
194+
log_i("Cleaning SSL connection.");
289195

290196
if (ssl_client->socket >= 0) {
291197
close(ssl_client->socket);
@@ -313,47 +219,43 @@ void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, cons
313219

314220
int data_to_read(sslclient_context *ssl_client)
315221
{
316-
317222
int ret, res;
318223
ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, NULL, 0);
319-
//printf("RET: %i\n",ret); //for low level debug
224+
//log_e("RET: %i",ret); //for low level debug
320225
res = mbedtls_ssl_get_bytes_avail(&ssl_client->ssl_ctx);
321-
//printf("RES: %i\n",res);
322-
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0 && ret != -76) { //RC:76 sockets is not connected
226+
//log_e("RES: %i",res);
227+
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0 && ret != -76) {
323228
return handle_error(ret);
324229
}
325230

326231
return res;
327232
}
328233

329234

330-
331235
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len)
332236
{
333-
//DEBUG_PRINT( "Writing HTTP request...\n"); //for low level debug
237+
//log_i("Writing HTTP request..."); //for low level debug
334238
int ret = -1;
335239

336240
while ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0) {
337-
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) { //RC:76 sockets is not connected
241+
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != -76) {
338242
return handle_error(ret);
339-
340243
}
341244
}
342245

343246
len = ret;
344-
//DEBUG_PRINT( "%d bytes written\n", len); //for low level debug
247+
//log_i("%d bytes written", len); //for low level debug
345248
return ret;
346249
}
347250

348251

349-
350252
int get_ssl_receive(sslclient_context *ssl_client, uint8_t *data, int length)
351253
{
352-
//DEBUG_PRINT( "Reading HTTP response...\n"); //for low level debug
254+
//log_i( "Reading HTTP response..."); //for low level debug
353255
int ret = -1;
354256

355257
ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, data, length);
356258

357-
//DEBUG_PRINT( "%d bytes readed\n", ret); //for low level debug
259+
//log_i( "%d bytes readed", ret); //for low level debug
358260
return ret;
359261
}

0 commit comments

Comments
 (0)