• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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