1 /*
2 * coap_mbedtls.c -- Mbed TLS Datagram Transport Layer Support for libcoap
3 *
4 * Copyright (C) 2019-2021 Jon Shallow <supjps-libcoap@jpshallow.com>
5 * 2019 Jitin George <jitin@espressif.com>
6 *
7 * SPDX-License-Identifier: BSD-2-Clause
8 *
9 * This file is part of the CoAP library libcoap. Please see README for terms
10 * of use.
11 */
12
13 /*
14 * Naming used to prevent confusion between coap sessions, mbedtls sessions etc.
15 * when reading the code.
16 *
17 * c_context A coap_context_t *
18 * c_session A coap_session_t *
19 * m_context A coap_mbedtls_context_t * (held in c_context->dtls_context)
20 * m_env A coap_mbedtls_env_t * (held in c_session->tls)
21 */
22
23 #include "coap3/coap_internal.h"
24
25 #ifdef HAVE_MBEDTLS
26
27 /*
28 * This code can be conditionally compiled to remove some components if
29 * they are not required to make a lighter footprint - all based on how
30 * the mbedtls library has been built. These are not defined within the
31 * libcoap environment.
32 *
33 * MBEDTLS_SSL_SRV_C - defined for server side functionality
34 * MBEDTLS_SSL_CLI_C - defined for client side functionality
35 * MBEDTLS_SSL_PROTO_DTLS - defined for DTLS support
36 * MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED - defined if PSK is to be supported
37 * or MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED - defined if PSK is to be supported
38 *
39 * Note: TLS is not currently supported until additional code is added
40 */
41
42 #include <mbedtls/version.h>
43 #include <mbedtls/platform.h>
44 #include <mbedtls/net_sockets.h>
45 #include <mbedtls/ssl.h>
46 #include <mbedtls/entropy.h>
47 #include <mbedtls/ctr_drbg.h>
48 #include <mbedtls/error.h>
49 #include <mbedtls/certs.h>
50 #include <mbedtls/timing.h>
51 #include <mbedtls/ssl_cookie.h>
52 #include <mbedtls/oid.h>
53 #include <mbedtls/debug.h>
54 #include <mbedtls/sha256.h>
55 #if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG)
56 #include <mbedtls/esp_debug.h>
57 #endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */
58 #include <errno.h>
59
60 #define mbedtls_malloc(a) malloc(a)
61 #define mbedtls_realloc(a,b) realloc(a,b)
62 #define mbedtls_strdup(a) strdup(a)
63 #define mbedtls_strndup(a,b) strndup(a,b)
64
65 #ifndef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
66 /* definition changed in later mbedtls code versions */
67 #ifdef MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED
68 #define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
69 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
70 #endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
71
72 #ifdef _WIN32
73 #define strcasecmp _stricmp
74 #endif
75
76 #define IS_PSK (1 << 0)
77 #define IS_PKI (1 << 1)
78 #define IS_CLIENT (1 << 6)
79 #define IS_SERVER (1 << 7)
80
81 typedef struct coap_ssl_t {
82 const uint8_t *pdu;
83 unsigned pdu_len;
84 unsigned peekmode;
85 } coap_ssl_t;
86
87 /*
88 * This structure encapsulates the Mbed TLS session object.
89 * It handles both TLS and DTLS.
90 * c_session->tls points to this.
91 */
92 typedef struct coap_mbedtls_env_t {
93 mbedtls_ssl_context ssl;
94 mbedtls_entropy_context entropy;
95 mbedtls_ctr_drbg_context ctr_drbg;
96 mbedtls_ssl_config conf;
97 mbedtls_timing_delay_context timer;
98 mbedtls_x509_crt cacert;
99 mbedtls_x509_crt public_cert;
100 mbedtls_pk_context private_key;
101 mbedtls_ssl_cookie_ctx cookie_ctx;
102 /* If not set, need to do do_mbedtls_handshake */
103 int established;
104 int seen_client_hello;
105 coap_tick_t last_timeout;
106 unsigned int retry_scalar;
107 coap_ssl_t coap_ssl_data;
108 } coap_mbedtls_env_t;
109
110 typedef struct pki_sni_entry {
111 char *sni;
112 coap_dtls_key_t pki_key;
113 mbedtls_x509_crt cacert;
114 mbedtls_x509_crt public_cert;
115 mbedtls_pk_context private_key;
116 } pki_sni_entry;
117
118 typedef struct psk_sni_entry {
119 char* sni;
120 coap_dtls_spsk_info_t psk_info;
121 } psk_sni_entry;
122
123 typedef struct coap_mbedtls_context_t {
124 coap_dtls_pki_t setup_data;
125 size_t pki_sni_count;
126 pki_sni_entry *pki_sni_entry_list;
127 size_t psk_sni_count;
128 psk_sni_entry *psk_sni_entry_list;
129 char *root_ca_file;
130 char *root_ca_path;
131 int psk_pki_enabled;
132 } coap_mbedtls_context_t;
133
134 typedef enum coap_enc_method_t {
135 COAP_ENC_PSK,
136 COAP_ENC_PKI,
137 } coap_enc_method_t;
138
coap_dgram_read(void * ctx,unsigned char * out,size_t outl)139 static int coap_dgram_read(void *ctx, unsigned char *out, size_t outl)
140 {
141 ssize_t ret = 0;
142 coap_session_t *c_session = (coap_session_t *)ctx;
143 coap_ssl_t *data;
144
145 if (!c_session->tls) {
146 errno = EAGAIN;
147 return MBEDTLS_ERR_SSL_WANT_READ;
148 }
149 data = &((coap_mbedtls_env_t *)c_session->tls)->coap_ssl_data;
150
151 if (out != NULL) {
152 if (data->pdu_len > 0) {
153 if (outl < data->pdu_len) {
154 memcpy(out, data->pdu, outl);
155 ret = outl;
156 data->pdu += outl;
157 data->pdu_len -= outl;
158 }
159 else {
160 memcpy(out, data->pdu, data->pdu_len);
161 ret = data->pdu_len;
162 if (!data->peekmode) {
163 data->pdu_len = 0;
164 data->pdu = NULL;
165 }
166 }
167 }
168 else {
169 ret = MBEDTLS_ERR_SSL_WANT_READ;
170 errno = EAGAIN;
171 }
172 }
173 return ret;
174 }
175
176 /*
177 * return +ve data amount
178 * 0 no more
179 * -1 error (error in errno)
180 */
181 /* callback function given to mbedtls for sending data over socket */
182 static int
coap_dgram_write(void * ctx,const unsigned char * send_buffer,size_t send_buffer_length)183 coap_dgram_write(void *ctx, const unsigned char *send_buffer,
184 size_t send_buffer_length)
185 {
186 ssize_t result = -1;
187 coap_session_t *c_session = (coap_session_t *)ctx;
188
189 if (c_session) {
190 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
191 result = coap_session_send(c_session, send_buffer, send_buffer_length);
192 if (result != (ssize_t)send_buffer_length) {
193 coap_log(LOG_WARNING, "coap_network_send failed (%zd != %zu)\n",
194 result, send_buffer_length);
195 result = 0;
196 }
197 else if (m_env) {
198 coap_tick_t now;
199 coap_ticks(&now);
200 m_env->last_timeout = now;
201 }
202 } else {
203 result = 0;
204 }
205 return result;
206 }
207
208 #if defined(MBEDTLS_SSL_PROTO_DTLS) && defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && defined(MBEDTLS_SSL_SRV_C)
209 /*
210 * Server side PSK callback
211 */
psk_server_callback(void * p_info,mbedtls_ssl_context * ssl,const unsigned char * name,size_t name_len)212 static int psk_server_callback(void *p_info, mbedtls_ssl_context *ssl,
213 const unsigned char *name, size_t name_len )
214 {
215 coap_session_t *c_session = (coap_session_t *)p_info;
216 uint8_t buf[128];
217 size_t psk_len;
218 coap_dtls_spsk_t *setup_data;
219 coap_mbedtls_env_t *m_env;
220
221 coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n",
222 (int)name_len, name);
223
224 if (c_session == NULL || c_session->context == NULL ||
225 c_session->context->get_server_psk == NULL) {
226 return -1;
227 }
228 m_env = (coap_mbedtls_env_t *)c_session->tls;
229 setup_data = &c_session->context->spsk_setup_data;
230
231 if (setup_data->validate_id_call_back) {
232 coap_bin_const_t lidentity;
233 lidentity.length = name_len;
234 lidentity.s = (const uint8_t*)name;
235 const coap_bin_const_t *psk_key =
236 setup_data->validate_id_call_back(&lidentity,
237 c_session,
238 setup_data->id_call_back_arg);
239
240 if (psk_key == NULL)
241 return -1;
242 mbedtls_ssl_set_hs_psk(ssl, psk_key->s, psk_key->length);
243 coap_session_refresh_psk_key(c_session, psk_key);
244 m_env->seen_client_hello = 1;
245 return 0;
246 }
247
248 psk_len = c_session->context->get_server_psk(c_session,
249 (const uint8_t*)name,
250 name_len,
251 (uint8_t*)buf, sizeof(buf));
252 m_env->seen_client_hello = 1;
253 mbedtls_ssl_set_hs_psk(ssl, buf, psk_len);
254 return 0;
255 }
256 #endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && MBEDTLS_SSL_SRV_C */
257
258 static char*
get_san_or_cn_from_cert(mbedtls_x509_crt * crt)259 get_san_or_cn_from_cert(mbedtls_x509_crt *crt)
260 {
261 if (crt) {
262 mbedtls_asn1_named_data * cn_data;
263
264 if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
265 mbedtls_asn1_sequence *seq = &crt->subject_alt_names;
266 while (seq && seq->buf.p == NULL) {
267 seq = seq->next;
268 }
269 if (seq) {
270 /* Return the Subject Alt Name */
271 return mbedtls_strndup((const char *)seq->buf.p,
272 seq->buf.len);
273 }
274 }
275
276 cn_data = mbedtls_asn1_find_named_data(&crt->subject,
277 MBEDTLS_OID_AT_CN,
278 MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN));
279 if (cn_data) {
280 /* Return the Common Name */
281 return mbedtls_strndup((const char *)cn_data->val.p,
282 cn_data->val.len);
283 }
284 }
285 return NULL;
286 }
287
288 static char *
get_error_string(int ret)289 get_error_string(int ret) {
290 static char buf[128] = {0};
291 mbedtls_strerror(ret, buf, sizeof(buf)-1);
292 return buf;
293 }
294
295 /*
296 * return 0 All OK
297 * -ve Error Code
298 */
299 static int
cert_verify_callback_mbedtls(void * data,mbedtls_x509_crt * crt,int depth,uint32_t * flags)300 cert_verify_callback_mbedtls(void *data, mbedtls_x509_crt *crt,
301 int depth, uint32_t *flags)
302 {
303 coap_session_t *c_session = (coap_session_t*)data;
304 coap_mbedtls_context_t *m_context =
305 (coap_mbedtls_context_t *)c_session->context->dtls_context;
306 coap_dtls_pki_t *setup_data = &m_context->setup_data;
307 char *cn = NULL;
308
309 if (*flags == 0)
310 return 0;
311
312 cn = get_san_or_cn_from_cert(crt);
313
314 if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) {
315 if (setup_data->allow_expired_certs) {
316 *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
317 coap_log(LOG_INFO,
318 " %s: %s: overridden: '%s' depth %d\n",
319 coap_session_str(c_session),
320 "The certificate has expired", cn ? cn : "?", depth);
321 }
322 }
323 if (*flags & MBEDTLS_X509_BADCERT_FUTURE) {
324 if (setup_data->allow_expired_certs) {
325 *flags &= ~MBEDTLS_X509_BADCERT_FUTURE;
326 coap_log(LOG_INFO,
327 " %s: %s: overridden: '%s' depth %d\n",
328 coap_session_str(c_session),
329 "The certificate has a future date", cn ? cn : "?", depth);
330 }
331 }
332 if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) {
333 if (setup_data->allow_bad_md_hash) {
334 *flags &= ~MBEDTLS_X509_BADCERT_BAD_MD;
335 coap_log(LOG_INFO,
336 " %s: %s: overridden: '%s' depth %d\n",
337 coap_session_str(c_session),
338 "The certificate has a bad MD hash", cn ? cn : "?", depth);
339 }
340 }
341 if (*flags & MBEDTLS_X509_BADCERT_BAD_KEY) {
342 if (setup_data->allow_short_rsa_length) {
343 *flags &= ~MBEDTLS_X509_BADCERT_BAD_KEY;
344 coap_log(LOG_INFO,
345 " %s: %s: overridden: '%s' depth %d\n",
346 coap_session_str(c_session),
347 "The certificate has a short RSA length", cn ? cn : "?", depth);
348 }
349 }
350 if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
351 uint32_t lflags;
352 int self_signed = !mbedtls_x509_crt_verify(crt, crt, NULL, NULL, &lflags,
353 NULL, NULL);
354 if (self_signed && depth == 0) {
355 if (setup_data->allow_self_signed &&
356 !setup_data->check_common_ca) {
357 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
358 coap_log(LOG_INFO,
359 " %s: %s: overridden: '%s' depth %d\n",
360 coap_session_str(c_session),
361 "Self-signed",
362 cn ? cn : "?", depth);
363 }
364 }
365 else {
366 if (!setup_data->verify_peer_cert) {
367 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
368 coap_log(LOG_INFO,
369 " %s: %s: overridden: '%s' depth %d\n",
370 coap_session_str(c_session),
371 "The certificate's CA does not match", cn ? cn : "?", depth);
372 }
373 }
374 }
375 if (*flags & MBEDTLS_X509_BADCRL_EXPIRED) {
376 if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) {
377 *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
378 coap_log(LOG_INFO,
379 " %s: %s: overridden: '%s' depth %d\n",
380 coap_session_str(c_session),
381 "The certificate's CRL has expired", cn ? cn : "?", depth);
382 }
383 else if (!setup_data->check_cert_revocation) {
384 *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
385 }
386 }
387 if (*flags & MBEDTLS_X509_BADCRL_FUTURE) {
388 if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) {
389 *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
390 coap_log(LOG_INFO,
391 " %s: %s: overridden: '%s' depth %d\n",
392 coap_session_str(c_session),
393 "The certificate's CRL has a future date", cn ? cn : "?", depth);
394 }
395 else if (!setup_data->check_cert_revocation) {
396 *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
397 }
398 }
399 if (setup_data->cert_chain_validation &&
400 depth > (setup_data->cert_chain_verify_depth + 1)) {
401 *flags |= MBEDTLS_X509_BADCERT_OTHER;
402 coap_log(LOG_WARNING,
403 " %s: %s: '%s' depth %d\n",
404 coap_session_str(c_session),
405 "The certificate's verify depth is too long",
406 cn ? cn : "?", depth);
407 }
408
409 if (*flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
410 *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
411 }
412 if (setup_data->validate_cn_call_back) {
413 if (!setup_data->validate_cn_call_back(cn,
414 crt->raw.p,
415 crt->raw.len,
416 c_session,
417 depth,
418 *flags == 0,
419 setup_data->cn_call_back_arg)) {
420 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
421 }
422 }
423 if (*flags != 0) {
424 char buf[128];
425 char *tcp;
426 int ret = mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags);
427
428 if (ret >= 0) {
429 tcp = strchr(buf, '\n');
430 while (tcp) {
431 *tcp = '\000';
432 coap_log(LOG_WARNING,
433 " %s: %s: issue 0x%x: '%s' depth %d\n",
434 coap_session_str(c_session),
435 buf, *flags, cn ? cn : "?", depth);
436 tcp = strchr(tcp+1, '\n');
437 }
438 }
439 else {
440 coap_log(LOG_ERR, "mbedtls_x509_crt_verify_info returned -0x%x: '%s'\n",
441 -ret, get_error_string(ret));
442 }
443 }
444
445 if (cn)
446 mbedtls_free(cn);
447
448 return 0;
449 }
450
451 static int
setup_pki_credentials(mbedtls_x509_crt * cacert,mbedtls_x509_crt * public_cert,mbedtls_pk_context * private_key,coap_mbedtls_env_t * m_env,coap_mbedtls_context_t * m_context,coap_session_t * c_session,coap_dtls_pki_t * setup_data,coap_dtls_role_t role)452 setup_pki_credentials(mbedtls_x509_crt *cacert,
453 mbedtls_x509_crt *public_cert,
454 mbedtls_pk_context *private_key,
455 coap_mbedtls_env_t *m_env,
456 coap_mbedtls_context_t *m_context,
457 coap_session_t *c_session,
458 coap_dtls_pki_t *setup_data,
459 coap_dtls_role_t role)
460 {
461 int ret;
462
463 if (setup_data->is_rpk_not_cert) {
464 coap_log(LOG_ERR,
465 "RPK Support not available in Mbed TLS\n");
466 return -1;
467 }
468 switch (setup_data->pki_key.key_type) {
469 case COAP_PKI_KEY_PEM:
470 if (setup_data->pki_key.key.pem.public_cert &&
471 setup_data->pki_key.key.pem.public_cert[0] &&
472 setup_data->pki_key.key.pem.private_key &&
473 setup_data->pki_key.key.pem.private_key[0]) {
474
475 mbedtls_x509_crt_init(public_cert);
476 mbedtls_pk_init(private_key);
477
478 ret = mbedtls_x509_crt_parse_file(public_cert,
479 setup_data->pki_key.key.pem.public_cert);
480 if (ret < 0) {
481 coap_log(LOG_ERR, "mbedtls_x509_crt_parse_file returned -0x%x: '%s'\n",
482 -ret, get_error_string(ret));
483 return ret;
484 }
485
486 ret = mbedtls_pk_parse_keyfile(private_key,
487 setup_data->pki_key.key.pem.private_key, NULL);
488 if (ret < 0) {
489 coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x: '%s'\n",
490 -ret, get_error_string(ret));
491 return ret;
492 }
493
494 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
495 if (ret < 0) {
496 coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
497 -ret, get_error_string(ret));
498 return ret;
499 }
500 }
501 else if (role == COAP_DTLS_ROLE_SERVER) {
502 coap_log(LOG_ERR,
503 "***setup_pki: (D)TLS: No Server Certificate + Private "
504 "Key defined\n");
505 return -1;
506 }
507
508 if (setup_data->pki_key.key.pem.ca_file &&
509 setup_data->pki_key.key.pem.ca_file[0]) {
510 mbedtls_x509_crt_init(cacert);
511 ret = mbedtls_x509_crt_parse_file(cacert,
512 setup_data->pki_key.key.pem.ca_file);
513 if (ret < 0) {
514 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
515 -ret, get_error_string(ret));
516 return ret;
517 }
518 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
519 }
520 break;
521 case COAP_PKI_KEY_PEM_BUF:
522 if (setup_data->pki_key.key.pem_buf.public_cert &&
523 setup_data->pki_key.key.pem_buf.public_cert_len &&
524 setup_data->pki_key.key.pem_buf.private_key &&
525 setup_data->pki_key.key.pem_buf.private_key_len) {
526 uint8_t *buffer;
527 size_t length;
528
529 mbedtls_x509_crt_init(public_cert);
530 mbedtls_pk_init(private_key);
531
532 length = setup_data->pki_key.key.pem_buf.public_cert_len;
533 if (setup_data->pki_key.key.pem_buf.public_cert[length-1] != '\000') {
534 /* Need to allocate memory to add in NULL terminator */
535 buffer = mbedtls_malloc(length + 1);
536 if (!buffer) {
537 coap_log(LOG_ERR, "mbedtls_malloc failed\n");
538 return MBEDTLS_ERR_SSL_ALLOC_FAILED;
539 }
540 memcpy(buffer, setup_data->pki_key.key.pem_buf.public_cert, length);
541 buffer[length] = '\000';
542 length++;
543 ret = mbedtls_x509_crt_parse(public_cert, buffer, length);
544 mbedtls_free(buffer);
545 }
546 else {
547 ret = mbedtls_x509_crt_parse(public_cert,
548 setup_data->pki_key.key.pem_buf.public_cert,
549 setup_data->pki_key.key.pem_buf.public_cert_len);
550 }
551 if (ret < 0) {
552 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
553 -ret, get_error_string(ret));
554 return ret;
555 }
556
557 length = setup_data->pki_key.key.pem_buf.private_key_len;
558 if (setup_data->pki_key.key.pem_buf.private_key[length-1] != '\000') {
559 /* Need to allocate memory to add in NULL terminator */
560 buffer = mbedtls_malloc(length + 1);
561 if (!buffer) {
562 coap_log(LOG_ERR, "mbedtls_malloc failed\n");
563 return MBEDTLS_ERR_SSL_ALLOC_FAILED;
564 }
565 memcpy(buffer, setup_data->pki_key.key.pem_buf.private_key, length);
566 buffer[length] = '\000';
567 length++;
568 ret = mbedtls_pk_parse_key(private_key, buffer, length, NULL, 0);
569 mbedtls_free(buffer);
570 }
571 else {
572 ret = mbedtls_pk_parse_key(private_key,
573 setup_data->pki_key.key.pem_buf.private_key,
574 setup_data->pki_key.key.pem_buf.private_key_len, NULL, 0);
575 }
576 if (ret < 0) {
577 coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x: '%s'\n",
578 -ret, get_error_string(ret));
579 return ret;
580 }
581
582 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
583 if (ret < 0) {
584 coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
585 -ret, get_error_string(ret));
586 return ret;
587 }
588 } else if (role == COAP_DTLS_ROLE_SERVER) {
589 coap_log(LOG_ERR,
590 "***setup_pki: (D)TLS: No Server Certificate + Private "
591 "Key defined\n");
592 return -1;
593 }
594
595 if (setup_data->pki_key.key.pem_buf.ca_cert &&
596 setup_data->pki_key.key.pem_buf.ca_cert_len) {
597 uint8_t *buffer;
598 size_t length;
599
600 mbedtls_x509_crt_init(cacert);
601 length = setup_data->pki_key.key.pem_buf.ca_cert_len;
602 if (setup_data->pki_key.key.pem_buf.ca_cert[length-1] != '\000') {
603 /* Need to allocate memory to add in NULL terminator */
604 buffer = mbedtls_malloc(length + 1);
605 if (!buffer) {
606 coap_log(LOG_ERR, "mbedtls_malloc failed\n");
607 return MBEDTLS_ERR_SSL_ALLOC_FAILED;
608 }
609 memcpy(buffer, setup_data->pki_key.key.pem_buf.ca_cert, length);
610 buffer[length] = '\000';
611 length++;
612 ret = mbedtls_x509_crt_parse(cacert, buffer, length);
613 mbedtls_free(buffer);
614 }
615 else {
616 ret = mbedtls_x509_crt_parse(cacert,
617 setup_data->pki_key.key.pem_buf.ca_cert,
618 setup_data->pki_key.key.pem_buf.ca_cert_len);
619 }
620 if (ret < 0) {
621 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
622 -ret, get_error_string(ret));
623 return ret;
624 }
625 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
626 }
627 break;
628 case COAP_PKI_KEY_ASN1:
629 if (setup_data->pki_key.key.asn1.public_cert &&
630 setup_data->pki_key.key.asn1.public_cert_len &&
631 setup_data->pki_key.key.asn1.private_key &&
632 setup_data->pki_key.key.asn1.private_key_len > 0) {
633
634 mbedtls_x509_crt_init(public_cert);
635 mbedtls_pk_init(private_key);
636 ret = mbedtls_x509_crt_parse(public_cert,
637 (const unsigned char *)setup_data->pki_key.key.asn1.public_cert,
638 setup_data->pki_key.key.asn1.public_cert_len);
639 if (ret < 0) {
640 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
641 -ret, get_error_string(ret));
642 return ret;
643 }
644
645 ret = mbedtls_pk_parse_key(private_key,
646 (const unsigned char *)setup_data->pki_key.key.asn1.private_key,
647 setup_data->pki_key.key.asn1.private_key_len, NULL, 0);
648 if (ret < 0) {
649 coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x: '%s'\n",
650 -ret, get_error_string(ret));
651 return ret;
652 }
653
654 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
655 if (ret < 0) {
656 coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
657 -ret, get_error_string(ret));
658 return ret;
659 }
660 } else if (role == COAP_DTLS_ROLE_SERVER) {
661 coap_log(LOG_ERR,
662 "***setup_pki: (D)TLS: No Server Certificate + Private "
663 "Key defined\n");
664 return -1;
665 }
666
667 if (setup_data->pki_key.key.asn1.ca_cert &&
668 setup_data->pki_key.key.asn1.ca_cert_len > 0) {
669 mbedtls_x509_crt_init(cacert);
670 ret = mbedtls_x509_crt_parse(cacert,
671 (const unsigned char *)setup_data->pki_key.key.asn1.ca_cert,
672 setup_data->pki_key.key.asn1.ca_cert_len);
673 if (ret < 0) {
674 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
675 -ret, get_error_string(ret));
676 return ret;
677 }
678 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
679 }
680 break;
681
682 case COAP_PKI_KEY_PKCS11:
683 coap_log(LOG_ERR,
684 "***setup_pki: (D)TLS: PKCS11 not currently supported\n");
685 return -1;
686
687 default:
688 coap_log(LOG_ERR,
689 "***setup_pki: (D)TLS: Unknown key type %d\n",
690 setup_data->pki_key.key_type);
691 return -1;
692 }
693
694 if (m_context->root_ca_file) {
695 ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_file);
696 if (ret < 0) {
697 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
698 -ret, get_error_string(ret));
699 return ret;
700 }
701 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
702 }
703 if (m_context->root_ca_path) {
704 ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_path);
705 if (ret < 0) {
706 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
707 -ret, get_error_string(ret));
708 return ret;
709 }
710 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
711 }
712
713 mbedtls_ssl_conf_cert_req_ca_list(&m_env->conf,
714 setup_data->check_common_ca ?
715 MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED :
716 MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED);
717 mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->verify_peer_cert ?
718 MBEDTLS_SSL_VERIFY_REQUIRED :
719 MBEDTLS_SSL_VERIFY_NONE);
720 /*
721 * Verify Peer.
722 * Need to do all checking, even if setup_data->verify_peer_cert is not set
723 */
724 mbedtls_ssl_conf_verify(&m_env->conf,
725 cert_verify_callback_mbedtls, c_session);
726
727 return 0;
728 }
729
730 #if defined(MBEDTLS_SSL_SRV_C)
731 /*
732 * PKI SNI callback.
733 */
734 static int
pki_sni_callback(void * p_info,mbedtls_ssl_context * ssl,const unsigned char * uname,size_t name_len)735 pki_sni_callback(void *p_info, mbedtls_ssl_context *ssl,
736 const unsigned char *uname, size_t name_len)
737 {
738 unsigned int i;
739 coap_dtls_pki_t sni_setup_data;
740 coap_session_t *c_session = (coap_session_t *)p_info;
741 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
742 coap_mbedtls_context_t *m_context =
743 (coap_mbedtls_context_t *)c_session->context->dtls_context;
744 int ret = 0;
745 char *name;
746
747 name = mbedtls_malloc(name_len+1);
748 if (!name)
749 return -1;
750
751 memcpy(name, uname, name_len);
752 name[name_len] = '\000';
753
754 /* Is this a cached entry? */
755 for (i = 0; i < m_context->pki_sni_count; i++) {
756 if (strcasecmp(name, m_context->pki_sni_entry_list[i].sni) == 0) {
757 break;
758 }
759 }
760 if (i == m_context->pki_sni_count) {
761 /*
762 * New PKI SNI request
763 */
764 coap_dtls_key_t *new_entry;
765 pki_sni_entry *pki_sni_entry_list;
766
767 new_entry =
768 m_context->setup_data.validate_sni_call_back(name,
769 m_context->setup_data.sni_call_back_arg);
770 if (!new_entry) {
771 mbedtls_free(name);
772 return -1;
773 }
774
775 pki_sni_entry_list = mbedtls_realloc(m_context->pki_sni_entry_list,
776 (i+1)*sizeof(pki_sni_entry));
777
778 if (pki_sni_entry_list == NULL) {
779 mbedtls_free(name);
780 return -1;
781 }
782 m_context->pki_sni_entry_list = pki_sni_entry_list;
783 memset(&m_context->pki_sni_entry_list[i], 0,
784 sizeof(m_context->pki_sni_entry_list[i]));
785 m_context->pki_sni_entry_list[i].sni = name;
786 m_context->pki_sni_entry_list[i].pki_key = *new_entry;
787 sni_setup_data = m_context->setup_data;
788 sni_setup_data.pki_key = *new_entry;
789 if ((ret = setup_pki_credentials(&m_context->pki_sni_entry_list[i].cacert,
790 &m_context->pki_sni_entry_list[i].public_cert,
791 &m_context->pki_sni_entry_list[i].private_key,
792 m_env,
793 m_context,
794 c_session,
795 &sni_setup_data, COAP_DTLS_ROLE_SERVER)) < 0) {
796 mbedtls_free(name);
797 return -1;
798 }
799 /* name has been absorbed into pki_sni_entry_list[].sni entry */
800 m_context->pki_sni_count++;
801 }
802 else {
803 mbedtls_free(name);
804 }
805
806 mbedtls_ssl_set_hs_ca_chain(ssl, &m_context->pki_sni_entry_list[i].cacert,
807 NULL);
808 return mbedtls_ssl_set_hs_own_cert(ssl,
809 &m_context->pki_sni_entry_list[i].public_cert,
810 &m_context->pki_sni_entry_list[i].private_key);
811 }
812
813 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
814 /*
815 * PSK SNI callback.
816 */
817 static int
psk_sni_callback(void * p_info,mbedtls_ssl_context * ssl,const unsigned char * uname,size_t name_len)818 psk_sni_callback(void *p_info, mbedtls_ssl_context *ssl,
819 const unsigned char *uname, size_t name_len)
820 {
821 unsigned int i;
822 coap_session_t *c_session = (coap_session_t *)p_info;
823 coap_mbedtls_context_t *m_context =
824 (coap_mbedtls_context_t *)c_session->context->dtls_context;
825 char *name;
826
827 name = mbedtls_malloc(name_len+1);
828 if (!name)
829 return -1;
830
831 memcpy(name, uname, name_len);
832 name[name_len] = '\000';
833
834 /* Is this a cached entry? */
835 for (i = 0; i < m_context->psk_sni_count; i++) {
836 if (strcasecmp(name, m_context->psk_sni_entry_list[i].sni) == 0) {
837 break;
838 }
839 }
840 if (i == m_context->psk_sni_count) {
841 /*
842 * New PSK SNI request
843 */
844 const coap_dtls_spsk_info_t *new_entry;
845 psk_sni_entry *psk_sni_entry_list;
846
847 new_entry =
848 c_session->context->spsk_setup_data.validate_sni_call_back(name,
849 c_session,
850 c_session->context->spsk_setup_data.sni_call_back_arg);
851 if (!new_entry) {
852 mbedtls_free(name);
853 return -1;
854 }
855
856 psk_sni_entry_list = mbedtls_realloc(m_context->psk_sni_entry_list,
857 (i+1)*sizeof(psk_sni_entry));
858
859 if (psk_sni_entry_list == NULL) {
860 mbedtls_free(name);
861 return -1;
862 }
863 m_context->psk_sni_entry_list = psk_sni_entry_list;
864 m_context->psk_sni_entry_list[i].sni = name;
865 m_context->psk_sni_entry_list[i].psk_info = *new_entry;
866 /* name has been absorbed into psk_sni_entry_list[].sni entry */
867 m_context->psk_sni_count++;
868 }
869 else {
870 mbedtls_free(name);
871 }
872
873 coap_session_refresh_psk_hint(c_session,
874 &m_context->psk_sni_entry_list[i].psk_info.hint);
875 coap_session_refresh_psk_key(c_session,
876 &m_context->psk_sni_entry_list[i].psk_info.key);
877 return mbedtls_ssl_set_hs_psk(ssl,
878 m_context->psk_sni_entry_list[i].psk_info.key.s,
879 m_context->psk_sni_entry_list[i].psk_info.key.length);
880 }
881 #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
882
setup_server_ssl_session(coap_session_t * c_session,coap_mbedtls_env_t * m_env)883 static int setup_server_ssl_session(coap_session_t *c_session,
884 coap_mbedtls_env_t *m_env)
885 {
886 coap_mbedtls_context_t *m_context =
887 (coap_mbedtls_context_t *)c_session->context->dtls_context;
888 int ret = 0;
889 m_context->psk_pki_enabled |= IS_SERVER;
890
891 mbedtls_ssl_cookie_init(&m_env->cookie_ctx);
892 if ((ret = mbedtls_ssl_config_defaults(&m_env->conf,
893 MBEDTLS_SSL_IS_SERVER,
894 c_session->proto == COAP_PROTO_DTLS ?
895 MBEDTLS_SSL_TRANSPORT_DATAGRAM :
896 MBEDTLS_SSL_TRANSPORT_STREAM,
897 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
898 coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x: '%s'\n",
899 -ret, get_error_string(ret));
900 goto fail;
901 }
902
903 mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg);
904
905 #if defined(MBEDTLS_SSL_PROTO_DTLS)
906 mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS,
907 COAP_DTLS_RETRANSMIT_TOTAL_MS);
908
909 if (m_context->psk_pki_enabled & IS_PSK) {
910 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
911 mbedtls_ssl_conf_psk_cb(&m_env->conf, psk_server_callback, c_session);
912 if (c_session->context->spsk_setup_data.validate_sni_call_back) {
913 mbedtls_ssl_conf_sni(&m_env->conf, psk_sni_callback, c_session);
914 }
915 #else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
916 coap_log(LOG_WARNING, "PSK not enabled in Mbed TLS library\n");
917 #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
918 }
919 #endif /* MBEDTLS_SSL_PROTO_DTLS */
920
921 if (m_context->psk_pki_enabled & IS_PKI) {
922 ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert,
923 &m_env->private_key, m_env, m_context,
924 c_session, &m_context->setup_data,
925 COAP_DTLS_ROLE_SERVER);
926 if (ret < 0) {
927 coap_log(LOG_ERR, "PKI setup failed\n");
928 return ret;
929 }
930 if (m_context->setup_data.validate_sni_call_back) {
931 mbedtls_ssl_conf_sni(&m_env->conf, pki_sni_callback, c_session);
932 }
933 }
934
935 if ((ret = mbedtls_ssl_cookie_setup(&m_env->cookie_ctx,
936 mbedtls_ctr_drbg_random,
937 &m_env->ctr_drbg)) != 0) {
938 coap_log(LOG_ERR, "mbedtls_ssl_cookie_setup: returned -0x%x: '%s'\n",
939 -ret, get_error_string(ret));
940 goto fail;
941 }
942
943 #if defined(MBEDTLS_SSL_PROTO_DTLS)
944 mbedtls_ssl_conf_dtls_cookies(&m_env->conf, mbedtls_ssl_cookie_write,
945 mbedtls_ssl_cookie_check,
946 &m_env->cookie_ctx );
947 #if MBEDTLS_VERSION_NUMBER >= 0x02100100
948 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
949 #endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
950 #endif /* MBEDTLS_SSL_PROTO_DTLS */
951 fail:
952 return ret;
953 }
954 #endif /* MBEDTLS_SSL_SRV_C */
955
956 static int *psk_ciphers = NULL;
957 static int *pki_ciphers = NULL;
958 static int processed_ciphers = 0;
959
960 static void
set_ciphersuites(mbedtls_ssl_config * conf,coap_enc_method_t method)961 set_ciphersuites(mbedtls_ssl_config *conf, coap_enc_method_t method)
962 {
963 if (!processed_ciphers) {
964 const int *list = mbedtls_ssl_list_ciphersuites();
965 const int *base = list;
966 int *psk_list;
967 int *pki_list;
968 int psk_count = 1; /* account for empty terminator */
969 int pki_count = 1;
970
971 while (*list) {
972 const mbedtls_ssl_ciphersuite_t *cur =
973 mbedtls_ssl_ciphersuite_from_id(*list);
974
975 if (cur) {
976 if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) {
977 /* Minimum of TLS1.2 required - skip */
978 }
979 else if (mbedtls_ssl_ciphersuite_uses_psk(cur)) {
980 psk_count++;
981 }
982 else {
983 pki_count++;
984 }
985 }
986 list++;
987 }
988 list = base;
989
990 psk_ciphers = mbedtls_malloc(psk_count * sizeof(psk_ciphers[0]));
991 if (psk_ciphers == NULL) {
992 coap_log(LOG_ERR, "set_ciphers: mbedtls_malloc with count %d failed\n", psk_count);
993 return;
994 }
995 pki_ciphers = mbedtls_malloc(pki_count * sizeof(pki_ciphers[0]));
996 if (pki_ciphers == NULL) {
997 coap_log(LOG_ERR, "set_ciphers: mbedtls_malloc with count %d failed\n", pki_count);
998 return;
999 }
1000
1001 psk_list = psk_ciphers;
1002 pki_list = pki_ciphers;
1003
1004 while (*list) {
1005 const mbedtls_ssl_ciphersuite_t *cur =
1006 mbedtls_ssl_ciphersuite_from_id(*list);
1007 if (cur) {
1008 if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) {
1009 /* Minimum of TLS1.2 required - skip */
1010 }
1011 else if (mbedtls_ssl_ciphersuite_uses_psk(cur)) {
1012 *psk_list = *list;
1013 psk_list++;
1014 }
1015 else {
1016 *pki_list = *list;
1017 pki_list++;
1018 }
1019 }
1020 list++;
1021 }
1022 /* zero terminate */
1023 *psk_list = 0;
1024 *pki_list = 0;
1025 processed_ciphers = 1;
1026 }
1027 mbedtls_ssl_conf_ciphersuites(conf, method == COAP_ENC_PSK ? psk_ciphers : pki_ciphers);
1028 }
1029
setup_client_ssl_session(coap_session_t * c_session,coap_mbedtls_env_t * m_env)1030 static int setup_client_ssl_session(coap_session_t *c_session,
1031 coap_mbedtls_env_t *m_env)
1032 {
1033 int ret;
1034
1035 coap_mbedtls_context_t *m_context =
1036 (coap_mbedtls_context_t *)c_session->context->dtls_context;
1037
1038 m_context->psk_pki_enabled |= IS_CLIENT;
1039
1040 if ((ret = mbedtls_ssl_config_defaults(&m_env->conf,
1041 MBEDTLS_SSL_IS_CLIENT,
1042 c_session->proto == COAP_PROTO_DTLS ?
1043 MBEDTLS_SSL_TRANSPORT_DATAGRAM :
1044 MBEDTLS_SSL_TRANSPORT_STREAM,
1045 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
1046 coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x: '%s'\n",
1047 -ret, get_error_string(ret));
1048 goto fail;
1049 }
1050
1051 #if defined(MBEDTLS_SSL_PROTO_DTLS)
1052 mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS,
1053 COAP_DTLS_RETRANSMIT_TOTAL_MS);
1054 #endif /* MBEDTLS_SSL_PROTO_DTLS */
1055
1056 mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
1057 mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg);
1058
1059 if (m_context->psk_pki_enabled & IS_PSK) {
1060 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1061 uint8_t identity[64];
1062 size_t identity_len;
1063 uint8_t psk_key[64];
1064 size_t psk_len;
1065 size_t max_identity_len = sizeof(identity);
1066
1067 coap_log(LOG_INFO, "Setting PSK key\n");
1068 psk_len = c_session->context->get_client_psk(c_session,
1069 NULL,
1070 0,
1071 identity,
1072 &identity_len,
1073 max_identity_len,
1074 psk_key,
1075 sizeof(psk_key));
1076 assert(identity_len <= sizeof(identity));
1077 mbedtls_ssl_conf_psk(&m_env->conf, (const unsigned char *)psk_key,
1078 psk_len, (const unsigned char *)identity,
1079 identity_len);
1080 if (c_session->cpsk_setup_data.client_sni) {
1081 mbedtls_ssl_set_hostname(&m_env->ssl,
1082 c_session->cpsk_setup_data.client_sni);
1083 }
1084 /* Identity Hint currently not supported in Mbed TLS so code removed */
1085
1086 set_ciphersuites(&m_env->conf, COAP_ENC_PSK);
1087 #else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1088 coap_log(LOG_WARNING, "PSK not enabled in Mbed TLS library\n");
1089 #endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1090 }
1091 else if ((m_context->psk_pki_enabled & IS_PKI) ||
1092 (m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
1093 /*
1094 * If neither PSK or PKI have been set up, use PKI basics.
1095 * This works providing COAP_PKI_KEY_PEM has a value of 0.
1096 */
1097 mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
1098 ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert,
1099 &m_env->private_key, m_env, m_context,
1100 c_session, &m_context->setup_data,
1101 COAP_DTLS_ROLE_CLIENT);
1102 if (ret < 0) {
1103 coap_log(LOG_ERR, "PKI setup failed\n");
1104 return ret;
1105 }
1106 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN)
1107 if (c_session->proto == COAP_PROTO_TLS) {
1108 const char *alpn_list[] = { "coap", NULL };
1109
1110 ret = mbedtls_ssl_conf_alpn_protocols(&m_env->conf, alpn_list);
1111 if (ret != 0) {
1112 coap_log(LOG_ERR, "ALPN setup failed %d)\n", ret);
1113 }
1114 }
1115 #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN */
1116 if (m_context->setup_data.client_sni) {
1117 mbedtls_ssl_set_hostname(&m_env->ssl, m_context->setup_data.client_sni);
1118 }
1119 #if defined(MBEDTLS_SSL_PROTO_DTLS)
1120 #if MBEDTLS_VERSION_NUMBER >= 0x02100100
1121 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1122 #endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1123 #endif /* MBEDTLS_SSL_PROTO_DTLS */
1124 set_ciphersuites(&m_env->conf, COAP_ENC_PKI);
1125 }
1126 return 0;
1127
1128 fail:
1129 return ret;
1130 }
1131
mbedtls_cleanup(coap_mbedtls_env_t * m_env)1132 static void mbedtls_cleanup(coap_mbedtls_env_t *m_env)
1133 {
1134 if (!m_env) {
1135 return;
1136 }
1137
1138 mbedtls_x509_crt_free(&m_env->cacert);
1139 mbedtls_x509_crt_free(&m_env->public_cert);
1140 mbedtls_pk_free(&m_env->private_key);
1141 mbedtls_entropy_free(&m_env->entropy);
1142 mbedtls_ssl_config_free(&m_env->conf);
1143 mbedtls_ctr_drbg_free(&m_env->ctr_drbg);
1144 mbedtls_ssl_free(&m_env->ssl);
1145 mbedtls_ssl_cookie_free(&m_env->cookie_ctx);
1146 }
1147
1148 static void
coap_dtls_free_mbedtls_env(coap_mbedtls_env_t * m_env)1149 coap_dtls_free_mbedtls_env(coap_mbedtls_env_t *m_env) {
1150 if (m_env) {
1151 mbedtls_cleanup(m_env);
1152 mbedtls_free(m_env);
1153 }
1154 }
1155
1156 static const char *
report_mbedtls_alert(unsigned char alert)1157 report_mbedtls_alert(unsigned char alert) {
1158 switch (alert) {
1159 case MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC: return ": Bad Record MAC";
1160 case MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE: return ": Handshake failure";
1161 case MBEDTLS_SSL_ALERT_MSG_NO_CERT: return ": No Certificate provided";
1162 case MBEDTLS_SSL_ALERT_MSG_BAD_CERT: return ": Certificate is bad";
1163 case MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA: return ": CA is unknown";
1164 case MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED: return ": Access was denied";
1165 case MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR: return ": Decrypt error";
1166 default: return "";
1167 }
1168 }
1169
1170 /*
1171 * return -1 failure
1172 * 0 not completed
1173 * 1 established
1174 */
do_mbedtls_handshake(coap_session_t * c_session,coap_mbedtls_env_t * m_env)1175 static int do_mbedtls_handshake(coap_session_t *c_session,
1176 coap_mbedtls_env_t *m_env) {
1177 int ret;
1178 int alert;
1179
1180 ret = mbedtls_ssl_handshake(&m_env->ssl);
1181 switch (ret) {
1182 case 0:
1183 m_env->established = 1;
1184 coap_log(LOG_DEBUG, "* %s: Mbed TLS established\n",
1185 coap_session_str(c_session));
1186 ret = 1;
1187 break;
1188 case MBEDTLS_ERR_SSL_WANT_READ:
1189 case MBEDTLS_ERR_SSL_WANT_WRITE:
1190 errno = EAGAIN;
1191 ret = 0;
1192 break;
1193 case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
1194 coap_log(LOG_DEBUG, "hello verification requested\n");
1195 goto reset;
1196 case MBEDTLS_ERR_SSL_INVALID_MAC:
1197 goto fail;
1198 case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE:
1199 alert = MBEDTLS_SSL_ALERT_MSG_NO_CERT;
1200 goto fail_alert;
1201 case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO:
1202 alert = MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE;
1203 goto fail_alert;
1204 case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
1205 goto fail;
1206 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
1207 if (m_env->ssl.in_msg[1] != MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)
1208 coap_log(LOG_WARNING, "***%s: Alert '%d'%s\n",
1209 coap_session_str(c_session), m_env->ssl.in_msg[1],
1210 report_mbedtls_alert(m_env->ssl.in_msg[1]));
1211 /* Fall through */
1212 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1213 c_session->dtls_event = COAP_EVENT_DTLS_CLOSED;
1214 ret = -1;
1215 break;
1216 default:
1217 coap_log(LOG_WARNING,
1218 "do_mbedtls_handshake: session establish "
1219 "returned -0x%x: '%s'\n",
1220 -ret, get_error_string(ret));
1221 ret = -1;
1222 break;
1223 }
1224 return ret;
1225
1226 fail_alert:
1227 mbedtls_ssl_send_alert_message(&m_env->ssl,
1228 MBEDTLS_SSL_ALERT_LEVEL_FATAL,
1229 alert);
1230 fail:
1231 c_session->dtls_event = COAP_EVENT_DTLS_ERROR;
1232 coap_log(LOG_WARNING,
1233 "do_mbedtls_handshake: session establish "
1234 "returned '%s'\n",
1235 get_error_string(ret));
1236 reset:
1237 mbedtls_ssl_session_reset(&m_env->ssl);
1238 return -1;
1239 }
1240
1241 static void
mbedtls_debug_out(void * ctx COAP_UNUSED,int level,const char * file,int line,const char * str)1242 mbedtls_debug_out(void *ctx COAP_UNUSED, int level,
1243 const char *file, int line, const char *str) {
1244 int log_level;
1245 /*
1246 * 0 No debug
1247 * 1 Error
1248 * 2 State change
1249 * 3 Informational
1250 * 4 Verbose
1251 */
1252 switch (level) {
1253 case 4:
1254 case 3:
1255 case 2:
1256 log_level = COAP_LOG_CIPHERS;
1257 break;
1258 case 1:
1259 log_level = LOG_ERR;
1260 break;
1261 case 0:
1262 default:
1263 log_level = 0;
1264 break;
1265 }
1266 coap_log(log_level, "%s:%04d: %s", file, line, str);
1267 }
1268
coap_dtls_new_mbedtls_env(coap_session_t * c_session,coap_dtls_role_t role)1269 static coap_mbedtls_env_t *coap_dtls_new_mbedtls_env(coap_session_t *c_session,
1270 coap_dtls_role_t role)
1271 {
1272 int ret = 0;
1273 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1274
1275 if (m_env)
1276 return m_env;
1277
1278 m_env = (coap_mbedtls_env_t *)mbedtls_malloc(sizeof(coap_mbedtls_env_t));
1279 if (!m_env) {
1280 return NULL;
1281 }
1282 memset(m_env, 0, sizeof(coap_mbedtls_env_t));
1283
1284 mbedtls_ssl_init(&m_env->ssl);
1285 mbedtls_ctr_drbg_init(&m_env->ctr_drbg);
1286 mbedtls_ssl_config_init(&m_env->conf);
1287 mbedtls_entropy_init(&m_env->entropy);
1288
1289 #if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG)
1290 mbedtls_esp_enable_debug_log(&m_env->conf, CONFIG_MBEDTLS_DEBUG_LEVEL);
1291 #endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */
1292 if ((ret = mbedtls_ctr_drbg_seed(&m_env->ctr_drbg,
1293 mbedtls_entropy_func, &m_env->entropy, NULL, 0)) != 0) {
1294 coap_log(LOG_ERR, "mbedtls_ctr_drbg_seed returned -0x%x: '%s'\n",
1295 -ret, get_error_string(ret));
1296 goto fail;
1297 }
1298
1299 if (role == COAP_DTLS_ROLE_CLIENT) {
1300 if (setup_client_ssl_session(c_session, m_env) != 0) {
1301 goto fail;
1302 }
1303 #if defined(MBEDTLS_SSL_SRV_C)
1304 } else if (role == COAP_DTLS_ROLE_SERVER) {
1305 if (setup_server_ssl_session(c_session, m_env) != 0) {
1306 goto fail;
1307 }
1308 #endif /* MBEDTLS_SSL_SRV_C */
1309 } else {
1310 goto fail;
1311 }
1312
1313 mbedtls_ssl_conf_min_version(&m_env->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
1314 MBEDTLS_SSL_MINOR_VERSION_3);
1315
1316 if ((ret = mbedtls_ssl_setup(&m_env->ssl, &m_env->conf)) != 0) {
1317 goto fail;
1318 }
1319 mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_dgram_write,
1320 coap_dgram_read, NULL);
1321 mbedtls_ssl_set_timer_cb(&m_env->ssl, &m_env->timer,
1322 mbedtls_timing_set_delay,
1323 mbedtls_timing_get_delay);
1324
1325 mbedtls_ssl_conf_dbg(&m_env->conf, mbedtls_debug_out, stdout);
1326 return m_env;
1327
1328 fail:
1329 if (m_env) {
1330 mbedtls_free(m_env);
1331 }
1332 return NULL;
1333 }
1334
coap_dtls_is_supported(void)1335 int coap_dtls_is_supported(void) {
1336 #if defined(MBEDTLS_SSL_PROTO_DTLS)
1337 return 1;
1338 #else /* !MBEDTLS_SSL_PROTO_DTLS */
1339 coap_log(LOG_EMERG,
1340 "libcoap not compiled for DTLS with Mbed TLS"
1341 " - update Mbed TLS to include DTLS\n");
1342 return 0;
1343 #endif /* !MBEDTLS_SSL_PROTO_DTLS */
1344 }
1345
coap_tls_is_supported(void)1346 int coap_tls_is_supported(void)
1347 {
1348 return 0;
1349 }
1350
coap_dtls_new_context(coap_context_t * c_context)1351 void *coap_dtls_new_context(coap_context_t *c_context)
1352 {
1353 coap_mbedtls_context_t *m_context;
1354 (void)c_context;
1355
1356 m_context = (coap_mbedtls_context_t *)mbedtls_malloc(sizeof(coap_mbedtls_context_t));
1357 if (m_context) {
1358 memset(m_context, 0, sizeof(coap_mbedtls_context_t));
1359 }
1360 return m_context;
1361 }
1362
1363 /*
1364 * return 0 failed
1365 * 1 passed
1366 */
1367 int
coap_dtls_context_set_spsk(coap_context_t * c_context,coap_dtls_spsk_t * setup_data)1368 coap_dtls_context_set_spsk(coap_context_t *c_context,
1369 coap_dtls_spsk_t *setup_data
1370 ) {
1371 coap_mbedtls_context_t *m_context =
1372 ((coap_mbedtls_context_t *)c_context->dtls_context);
1373
1374 #if !defined(MBEDTLS_SSL_SRV_C)
1375 coap_log(LOG_EMERG, "coap_context_set_spsk:"
1376 " libcoap not compiled for Server Mode for Mbed TLS"
1377 " - update Mbed TLS to include Server Mode\n");
1378 return 0;
1379 #endif /* !MBEDTLS_SSL_SRV_C */
1380 if (!m_context || !setup_data)
1381 return 0;
1382
1383 m_context->psk_pki_enabled |= IS_PSK;
1384 return 1;
1385 }
1386
1387 /*
1388 * return 0 failed
1389 * 1 passed
1390 */
1391 int
coap_dtls_context_set_cpsk(coap_context_t * c_context,coap_dtls_cpsk_t * setup_data)1392 coap_dtls_context_set_cpsk(coap_context_t *c_context,
1393 coap_dtls_cpsk_t *setup_data
1394 ) {
1395 #if !defined(MBEDTLS_SSL_CLI_C)
1396 coap_log(LOG_EMERG, "coap_context_set_spsk:"
1397 " libcoap not compiled for Client Mode for Mbed TLS"
1398 " - update Mbed TLS to include Client Mode\n");
1399 return 0;
1400 #endif /* !MBEDTLS_SSL_CLI_C */
1401 coap_mbedtls_context_t *m_context =
1402 ((coap_mbedtls_context_t *)c_context->dtls_context);
1403
1404 if (!m_context || !setup_data)
1405 return 0;
1406
1407 if (setup_data->validate_ih_call_back) {
1408 coap_log(LOG_WARNING,
1409 "CoAP Client with Mbed TLS does not support Identity Hint selection\n");
1410 }
1411 m_context->psk_pki_enabled |= IS_PSK;
1412 return 1;
1413 }
1414
coap_dtls_context_set_pki(coap_context_t * c_context,const coap_dtls_pki_t * setup_data,const coap_dtls_role_t role COAP_UNUSED)1415 int coap_dtls_context_set_pki(coap_context_t *c_context,
1416 const coap_dtls_pki_t *setup_data,
1417 const coap_dtls_role_t role COAP_UNUSED)
1418 {
1419 coap_mbedtls_context_t *m_context =
1420 ((coap_mbedtls_context_t *)c_context->dtls_context);
1421
1422 m_context->setup_data = *setup_data;
1423 if (!m_context->setup_data.verify_peer_cert) {
1424 /* Needs to be clear so that no CA DNs are transmitted */
1425 m_context->setup_data.check_common_ca = 0;
1426 /* Allow all of these but warn if issue */
1427 m_context->setup_data.allow_self_signed = 1;
1428 m_context->setup_data.allow_expired_certs = 1;
1429 m_context->setup_data.cert_chain_validation = 1;
1430 m_context->setup_data.cert_chain_verify_depth = 10;
1431 m_context->setup_data.check_cert_revocation = 1;
1432 m_context->setup_data.allow_no_crl = 1;
1433 m_context->setup_data.allow_expired_crl = 1;
1434 m_context->setup_data.allow_bad_md_hash = 1;
1435 m_context->setup_data.allow_short_rsa_length = 1;
1436 }
1437 m_context->psk_pki_enabled |= IS_PKI;
1438 return 1;
1439 }
1440
coap_dtls_context_set_pki_root_cas(coap_context_t * c_context,const char * ca_file,const char * ca_path)1441 int coap_dtls_context_set_pki_root_cas(coap_context_t *c_context,
1442 const char *ca_file,
1443 const char *ca_path)
1444 {
1445 coap_mbedtls_context_t *m_context =
1446 ((coap_mbedtls_context_t *)c_context->dtls_context);
1447
1448 if (!m_context) {
1449 coap_log(LOG_WARNING,
1450 "coap_context_set_pki_root_cas: (D)TLS environment "
1451 "not set up\n");
1452 return 0;
1453 }
1454
1455 if (ca_file == NULL && ca_path == NULL) {
1456 coap_log(LOG_WARNING,
1457 "coap_context_set_pki_root_cas: ca_file and/or ca_path "
1458 "not defined\n");
1459 return 0;
1460 }
1461 if (m_context->root_ca_file) {
1462 mbedtls_free(m_context->root_ca_file);
1463 m_context->root_ca_file = NULL;
1464 }
1465
1466 if (ca_file) {
1467 m_context->root_ca_file = mbedtls_strdup(ca_file);
1468 }
1469
1470 if (m_context->root_ca_path) {
1471 mbedtls_free(m_context->root_ca_path);
1472 m_context->root_ca_path = NULL;
1473 }
1474
1475 if (ca_path) {
1476 m_context->root_ca_path = mbedtls_strdup(ca_path);
1477 }
1478 return 1;
1479 }
1480
coap_dtls_context_check_keys_enabled(coap_context_t * c_context)1481 int coap_dtls_context_check_keys_enabled(coap_context_t *c_context)
1482 {
1483 coap_mbedtls_context_t *m_context =
1484 ((coap_mbedtls_context_t *)c_context->dtls_context);
1485 return m_context->psk_pki_enabled ? 1 : 0;
1486 }
1487
coap_dtls_free_context(void * dtls_context)1488 void coap_dtls_free_context(void *dtls_context)
1489 {
1490 coap_mbedtls_context_t *m_context = (coap_mbedtls_context_t *)dtls_context;
1491 unsigned int i;
1492
1493 for (i = 0; i < m_context->pki_sni_count; i++) {
1494 mbedtls_free(m_context->pki_sni_entry_list[i].sni);
1495
1496 mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].public_cert);
1497
1498 mbedtls_pk_free(&m_context->pki_sni_entry_list[i].private_key);
1499
1500 mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].cacert);
1501 }
1502 if (m_context->pki_sni_entry_list)
1503 mbedtls_free(m_context->pki_sni_entry_list);
1504
1505 for (i = 0; i < m_context->psk_sni_count; i++) {
1506 mbedtls_free(m_context->psk_sni_entry_list[i].sni);
1507 }
1508 if (m_context->psk_sni_entry_list)
1509 mbedtls_free(m_context->psk_sni_entry_list);
1510
1511 if (m_context->root_ca_path)
1512 mbedtls_free(m_context->root_ca_path);
1513 if (m_context->root_ca_file)
1514 mbedtls_free(m_context->root_ca_file);
1515
1516 mbedtls_free(m_context);
1517 }
1518
coap_dtls_new_client_session(coap_session_t * c_session)1519 void *coap_dtls_new_client_session(coap_session_t *c_session)
1520 {
1521 #if !defined(MBEDTLS_SSL_CLI_C)
1522 (void)c_session;
1523 coap_log(LOG_EMERG, "coap_dtls_new_client_session:"
1524 " libcoap not compiled for Client Mode for Mbed TLS"
1525 " - update Mbed TLS to include Client Mode\n");
1526 return NULL;
1527 #else /* MBEDTLS_SSL_CLI_C */
1528 coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session,
1529 COAP_DTLS_ROLE_CLIENT);
1530 int ret;
1531
1532 if (m_env) {
1533 coap_tick_t now;
1534 coap_ticks(&now);
1535 m_env->last_timeout = now;
1536 ret = do_mbedtls_handshake(c_session, m_env);
1537 if (ret == -1) {
1538 coap_dtls_free_mbedtls_env(m_env);
1539 return NULL;
1540 }
1541 }
1542 return m_env;
1543 #endif /* MBEDTLS_SSL_CLI_C */
1544 }
1545
coap_dtls_new_server_session(coap_session_t * c_session)1546 void *coap_dtls_new_server_session(coap_session_t *c_session)
1547 {
1548 coap_mbedtls_env_t *m_env =
1549 (coap_mbedtls_env_t *)c_session->tls;
1550 if (m_env) {
1551 #if defined(MBEDTLS_SSL_PROTO_DTLS)
1552 #if MBEDTLS_VERSION_NUMBER >= 0x02100100
1553 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1554 #endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1555 #endif /* MBEDTLS_SSL_PROTO_DTLS */
1556 }
1557 return m_env;
1558 }
1559
coap_dtls_free_session(coap_session_t * c_session)1560 void coap_dtls_free_session(coap_session_t *c_session)
1561 {
1562 if (c_session && c_session->context && c_session->tls) {
1563 coap_dtls_free_mbedtls_env(c_session->tls);
1564 c_session->tls = NULL;
1565 coap_handle_event(c_session->context, COAP_EVENT_DTLS_CLOSED, c_session);
1566 }
1567 return;
1568 }
1569
coap_dtls_session_update_mtu(coap_session_t * c_session)1570 void coap_dtls_session_update_mtu(coap_session_t *c_session)
1571 {
1572 #if defined(MBEDTLS_SSL_PROTO_DTLS)
1573 coap_mbedtls_env_t *m_env =
1574 (coap_mbedtls_env_t *)c_session->tls;
1575 if (m_env) {
1576 #if MBEDTLS_VERSION_NUMBER >= 0x02100100
1577 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1578 #endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1579 }
1580 #endif /* MBEDTLS_SSL_PROTO_DTLS */
1581 }
1582
coap_dtls_send(coap_session_t * c_session,const uint8_t * data,size_t data_len)1583 int coap_dtls_send(coap_session_t *c_session,
1584 const uint8_t *data,
1585 size_t data_len)
1586 {
1587 int ret;
1588 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1589
1590 assert(m_env != NULL);
1591
1592 if (!m_env) {
1593 return -1;
1594 }
1595 c_session->dtls_event = -1;
1596 if (m_env->established) {
1597 ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char*) data, data_len);
1598 if (ret <= 0) {
1599 switch (ret) {
1600 case MBEDTLS_ERR_SSL_WANT_READ:
1601 case MBEDTLS_ERR_SSL_WANT_WRITE:
1602 ret = 0;
1603 break;
1604 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
1605 c_session->dtls_event = COAP_EVENT_DTLS_CLOSED;
1606 ret = -1;
1607 break;
1608 default:
1609 coap_log(LOG_WARNING,
1610 "coap_dtls_send: "
1611 "returned -0x%x: '%s'\n",
1612 -ret, get_error_string(ret));
1613 ret = -1;
1614 break;
1615 }
1616 if (ret == -1) {
1617 coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n");
1618 }
1619 }
1620 } else {
1621 ret = do_mbedtls_handshake(c_session, m_env);
1622 if (ret == 1) {
1623 /* Just connected, so send the data */
1624 return coap_dtls_send(c_session, data, data_len);
1625 }
1626 ret = -1;
1627 }
1628
1629 if (c_session->dtls_event >= 0) {
1630 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
1631 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
1632 coap_handle_event(c_session->context, c_session->dtls_event, c_session);
1633 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1634 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1635 coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED);
1636 ret = -1;
1637 }
1638 }
1639 return ret;
1640 }
1641
coap_dtls_is_context_timeout(void)1642 int coap_dtls_is_context_timeout(void)
1643 {
1644 return 0;
1645 }
1646
coap_dtls_get_context_timeout(void * dtls_context COAP_UNUSED)1647 coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
1648 {
1649 return 0;
1650 }
1651
coap_dtls_get_timeout(coap_session_t * c_session,coap_tick_t now)1652 coap_tick_t coap_dtls_get_timeout(coap_session_t *c_session, coap_tick_t now)
1653 {
1654 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1655 int ret = mbedtls_timing_get_delay(&m_env->timer);
1656 unsigned int scalar = 1 << m_env->retry_scalar;
1657
1658 assert(c_session->state == COAP_SESSION_STATE_HANDSHAKE);
1659 switch (ret) {
1660 case 0:
1661 /* int_ms has not timed out */
1662 if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) {
1663 /* Need to indicate remaining timeout time */
1664 return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
1665 }
1666 m_env->last_timeout = now;
1667 /* This may cause a minor extra delay */
1668 return now + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
1669 case 1:
1670 /* int_ms has timed out, but not fin_ms */
1671 /*
1672 * Need to make sure that we do not do this too frequently
1673 */
1674 if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) {
1675 return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
1676 }
1677
1678 /* Reset for the next time */
1679 m_env->last_timeout = now;
1680 return now;
1681 case 2:
1682 /* fin_ms has timed out - timed out - one final try */
1683 return now;
1684 default:
1685 break;
1686 }
1687
1688 return 0;
1689 }
1690
coap_dtls_handle_timeout(coap_session_t * c_session)1691 void coap_dtls_handle_timeout(coap_session_t *c_session)
1692 {
1693 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1694
1695 assert(m_env != NULL && c_session->state == COAP_SESSION_STATE_HANDSHAKE);
1696 m_env->retry_scalar++;
1697 if ((++c_session->dtls_timeout_count > c_session->max_retransmit) ||
1698 (do_mbedtls_handshake(c_session, m_env) < 0)) {
1699 /* Too many retries */
1700 coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED);
1701 }
1702 return;
1703 }
1704
1705 /*
1706 * return +ve data amount
1707 * 0 no more
1708 * -1 error
1709 */
coap_dtls_receive(coap_session_t * c_session,const uint8_t * data,size_t data_len)1710 int coap_dtls_receive(coap_session_t *c_session,
1711 const uint8_t *data,
1712 size_t data_len)
1713 {
1714 int ret = 1;
1715
1716 c_session->dtls_event = -1;
1717 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1718 coap_ssl_t *ssl_data;
1719
1720 assert(m_env != NULL);
1721
1722 ssl_data = &m_env->coap_ssl_data;
1723 if (ssl_data->pdu_len) {
1724 coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n",
1725 coap_session_str(c_session), ssl_data->pdu_len);
1726 }
1727 ssl_data->pdu = data;
1728 ssl_data->pdu_len = (unsigned)data_len;
1729
1730 if (m_env->established) {
1731 #if COAP_CONSTRAINED_STACK
1732 static coap_mutex_t b_static_mutex = COAP_MUTEX_INITIALIZER;
1733 static uint8_t pdu[COAP_RXBUFFER_SIZE];
1734 #else /* ! COAP_CONSTRAINED_STACK */
1735 uint8_t pdu[COAP_RXBUFFER_SIZE];
1736 #endif /* ! COAP_CONSTRAINED_STACK */
1737
1738 #if COAP_CONSTRAINED_STACK
1739 coap_mutex_lock(&b_static_mutex);
1740 #endif /* COAP_CONSTRAINED_STACK */
1741
1742 if (c_session->state == COAP_SESSION_STATE_HANDSHAKE) {
1743 coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED,
1744 c_session);
1745 coap_session_connected(c_session);
1746 }
1747
1748 ret = mbedtls_ssl_read(&m_env->ssl, pdu, sizeof(pdu));
1749 if (ret > 0) {
1750 ret = coap_handle_dgram(c_session->context, c_session, pdu, (size_t)ret);
1751 #if COAP_CONSTRAINED_STACK
1752 coap_mutex_unlock(&b_static_mutex);
1753 #endif /* COAP_CONSTRAINED_STACK */
1754 goto finish;
1755 }
1756 switch (ret) {
1757 case 0:
1758 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1759 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
1760 c_session->dtls_event = COAP_EVENT_DTLS_CLOSED;
1761 break;
1762 case MBEDTLS_ERR_SSL_WANT_READ:
1763 break;
1764 default:
1765 coap_log(LOG_WARNING,
1766 "coap_dtls_receive: "
1767 "returned -0x%x: '%s' (length %zd)\n",
1768 -ret, get_error_string(ret), data_len);
1769 break;
1770 }
1771 #if COAP_CONSTRAINED_STACK
1772 coap_mutex_unlock(&b_static_mutex);
1773 #endif /* COAP_CONSTRAINED_STACK */
1774 ret = -1;
1775 }
1776 else {
1777 ret = do_mbedtls_handshake(c_session, m_env);
1778 if (ret == 1) {
1779 /* Just connected, so send the data */
1780 coap_session_connected(c_session);
1781 } else {
1782 if (ssl_data->pdu_len) {
1783 /* Do the handshake again incase of internal timeout */
1784 ret = do_mbedtls_handshake(c_session, m_env);
1785 if (ret == 1) {
1786 /* Just connected, so send the data */
1787 coap_session_connected(c_session);
1788 } else {
1789 ret = -1;
1790 }
1791 }
1792 ret = -1;
1793 }
1794 }
1795 if (c_session->dtls_event >= 0) {
1796 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
1797 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
1798 coap_handle_event(c_session->context, c_session->dtls_event, c_session);
1799 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1800 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1801 coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED);
1802 ssl_data = NULL;
1803 ret = -1;
1804 }
1805 }
1806 finish:
1807 if (ssl_data && ssl_data->pdu_len) {
1808 /* pdu data is held on stack which will not stay there */
1809 coap_log(LOG_DEBUG, "coap_dtls_receive: ret %d: remaining data %u\n", ret, ssl_data->pdu_len);
1810 ssl_data->pdu_len = 0;
1811 ssl_data->pdu = NULL;
1812 }
1813 return ret;
1814 }
1815
1816 /*
1817 * return -1 failure
1818 * 0 not completed
1819 * 1 client hello seen
1820 */
coap_dtls_hello(coap_session_t * c_session,const uint8_t * data,size_t data_len)1821 int coap_dtls_hello(coap_session_t *c_session,
1822 const uint8_t *data,
1823 size_t data_len)
1824 {
1825 #if !defined(MBEDTLS_SSL_PROTO_DTLS) || !defined(MBEDTLS_SSL_SRV_C)
1826 (void)c_session;
1827 (void)data;
1828 (void)data_len;
1829 coap_log(LOG_EMERG, "coap_dtls_hello:"
1830 " libcoap not compiled for DTLS or Server Mode for Mbed TLS"
1831 " - update Mbed TLS to include DTLS and Server Mode\n");
1832 return -1;
1833 #else /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */
1834 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1835 coap_ssl_t *ssl_data;
1836 int ret;
1837
1838 if (!m_env) {
1839 m_env = coap_dtls_new_mbedtls_env(c_session, COAP_DTLS_ROLE_SERVER);
1840 if (m_env) {
1841 c_session->tls = m_env;
1842 }
1843 else {
1844 /* error should have already been reported */
1845 return -1;
1846 }
1847 }
1848
1849 if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl,
1850 (unsigned char *)&c_session->addr_info.remote,
1851 sizeof(c_session->addr_info.remote))) != 0) {
1852 coap_log(LOG_ERR,
1853 "mbedtls_ssl_set_client_transport_id() returned -0x%x: '%s'\n",
1854 -ret, get_error_string(ret));
1855 return -1;
1856 }
1857
1858 ssl_data = &m_env->coap_ssl_data;
1859 if (ssl_data->pdu_len) {
1860 coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n",
1861 coap_session_str(c_session), ssl_data->pdu_len);
1862 }
1863 ssl_data->pdu = data;
1864 ssl_data->pdu_len = (unsigned)data_len;
1865
1866 ret = do_mbedtls_handshake(c_session, m_env);
1867 if (ret == 0 || m_env->seen_client_hello) {
1868 /* The test for seen_client_hello gives the ability to setup a new
1869 c_session to continue the do_mbedtls_handshake past the client hello
1870 and safely allow updating of the m_env and separately
1871 letting a new session cleanly start up.
1872 */
1873 m_env->seen_client_hello = 0;
1874 ret = 1;
1875 }
1876 else {
1877 ret = 0;
1878 }
1879
1880 if (ssl_data->pdu_len) {
1881 /* pdu data is held on stack which will not stay there */
1882 coap_log(LOG_DEBUG, "coap_dtls_hello: ret %d: remaining data %u\n", ret, ssl_data->pdu_len);
1883 ssl_data->pdu_len = 0;
1884 ssl_data->pdu = NULL;
1885 }
1886 return ret;
1887 #endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */
1888 }
1889
coap_dtls_get_overhead(coap_session_t * c_session)1890 unsigned int coap_dtls_get_overhead(coap_session_t *c_session)
1891 {
1892 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1893 int expansion = mbedtls_ssl_get_record_expansion(&m_env->ssl);
1894
1895 if (expansion == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) {
1896 return 13 + 8 + 8;
1897 }
1898 return expansion;
1899 }
1900
1901 #if !COAP_DISABLE_TCP
coap_tls_new_client_session(coap_session_t * c_session COAP_UNUSED,int * connected COAP_UNUSED)1902 void *coap_tls_new_client_session(coap_session_t *c_session COAP_UNUSED,
1903 int *connected COAP_UNUSED)
1904 {
1905 return NULL;
1906 }
1907
coap_tls_new_server_session(coap_session_t * c_session COAP_UNUSED,int * connected COAP_UNUSED)1908 void *coap_tls_new_server_session(coap_session_t *c_session COAP_UNUSED,
1909 int *connected COAP_UNUSED)
1910 {
1911 return NULL;
1912 }
1913
coap_tls_free_session(coap_session_t * c_session COAP_UNUSED)1914 void coap_tls_free_session( coap_session_t *c_session COAP_UNUSED)
1915 {
1916 }
1917
coap_tls_write(coap_session_t * c_session COAP_UNUSED,const uint8_t * data COAP_UNUSED,size_t data_len COAP_UNUSED)1918 ssize_t coap_tls_write(coap_session_t *c_session COAP_UNUSED,
1919 const uint8_t *data COAP_UNUSED,
1920 size_t data_len COAP_UNUSED
1921 )
1922 {
1923 return 0;
1924 }
1925
coap_tls_read(coap_session_t * c_session COAP_UNUSED,uint8_t * data COAP_UNUSED,size_t data_len COAP_UNUSED)1926 ssize_t coap_tls_read(coap_session_t *c_session COAP_UNUSED,
1927 uint8_t *data COAP_UNUSED,
1928 size_t data_len COAP_UNUSED
1929 )
1930 {
1931 return 0;
1932 }
1933 #endif /* !COAP_DISABLE_TCP */
1934
coap_dtls_startup(void)1935 void coap_dtls_startup(void)
1936 {
1937 }
1938
coap_dtls_shutdown(void)1939 void coap_dtls_shutdown(void) {
1940 }
1941
1942 void *
coap_dtls_get_tls(const coap_session_t * c_session,coap_tls_library_t * tls_lib)1943 coap_dtls_get_tls(const coap_session_t *c_session,
1944 coap_tls_library_t *tls_lib) {
1945 if (tls_lib)
1946 *tls_lib = COAP_TLS_LIBRARY_MBEDTLS;
1947 if (c_session && c_session->tls) {
1948 coap_mbedtls_env_t *m_env;
1949
1950 /* To get around const issue */
1951 memcpy(&m_env, &c_session->tls, sizeof(m_env));
1952
1953 return (void *)&m_env->ssl;
1954 }
1955 return NULL;
1956 }
1957
1958 static int keep_log_level = 0;
1959
coap_dtls_set_log_level(int level)1960 void coap_dtls_set_log_level(int level)
1961 {
1962 #if !defined(ESPIDF_VERSION)
1963 int use_level;
1964 /*
1965 * Mbed TLS debug levels filter
1966 * 0 No debug
1967 * 1 Error
1968 * 2 State change
1969 * 3 Informational
1970 * 4 Verbose
1971 */
1972
1973 if (level <= LOG_ERR) {
1974 use_level = 1;
1975 }
1976 else {
1977 use_level = (level >= LOG_DEBUG) ? level - LOG_DEBUG + 2 : 0;
1978 }
1979 mbedtls_debug_set_threshold(use_level);
1980 #endif /* !ESPIDF_VERSION) */
1981 keep_log_level = level;
1982 }
1983
coap_dtls_get_log_level(void)1984 int coap_dtls_get_log_level(void)
1985 {
1986 return keep_log_level;
1987 }
1988
coap_get_tls_library_version(void)1989 coap_tls_version_t * coap_get_tls_library_version(void)
1990 {
1991 static coap_tls_version_t version;
1992 version.version = mbedtls_version_get_number();
1993 version.built_version = MBEDTLS_VERSION_NUMBER;
1994 version.type = COAP_TLS_LIBRARY_MBEDTLS;
1995 return &version;
1996 }
1997
1998 coap_digest_ctx_t *
coap_digest_setup(void)1999 coap_digest_setup(void) {
2000 mbedtls_sha256_context *digest_ctx = mbedtls_malloc(sizeof(mbedtls_sha256_context));
2001
2002 if (digest_ctx) {
2003 mbedtls_sha256_init(digest_ctx);
2004 mbedtls_sha256_starts_ret(digest_ctx, 0);
2005 }
2006 return digest_ctx;
2007 }
2008
2009 void
coap_digest_free(coap_digest_ctx_t * digest_ctx)2010 coap_digest_free(coap_digest_ctx_t *digest_ctx) {
2011 mbedtls_sha256_free(digest_ctx);
2012 mbedtls_free(digest_ctx);
2013 }
2014
2015 int
coap_digest_update(coap_digest_ctx_t * digest_ctx,const uint8_t * data,size_t data_len)2016 coap_digest_update(coap_digest_ctx_t *digest_ctx,
2017 const uint8_t *data,
2018 size_t data_len) {
2019 int ret = mbedtls_sha256_update_ret(digest_ctx, data, data_len);
2020
2021 return ret == 0;
2022 }
2023
2024 int
coap_digest_final(coap_digest_ctx_t * digest_ctx,coap_digest_t * digest_buffer)2025 coap_digest_final(coap_digest_ctx_t *digest_ctx,
2026 coap_digest_t *digest_buffer) {
2027 int ret = mbedtls_sha256_finish_ret(digest_ctx, (uint8_t*)digest_buffer);
2028
2029 coap_digest_free(digest_ctx);
2030 return ret == 0;
2031 }
2032
2033 #else /* !HAVE_MBEDTLS */
2034
2035 #ifdef __clang__
2036 /* Make compilers happy that do not like empty modules. As this function is
2037 * never used, we ignore -Wunused-function at the end of compiling this file
2038 */
2039 #pragma GCC diagnostic ignored "-Wunused-function"
2040 #endif
dummy(void)2041 static inline void dummy(void) {
2042 }
2043
2044 #endif /* HAVE_MBEDTLS */
2045