libcoap  4.3.0
coap_mbedtls.c
Go to the documentation of this file.
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 
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
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  */
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*
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 *
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
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;
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;
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;
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;
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;
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;
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;
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;
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;
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';
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
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) {
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) {
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;
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) {
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) {
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:
684  "***setup_pki: (D)TLS: PKCS11 not currently supported\n");
685  return -1;
686 
687  default:
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
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
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 =
849  c_session,
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 
874  &m_context->psk_sni_entry_list[i].psk_info.hint);
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 
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,
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);
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,
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
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 
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,
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,
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 
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
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 *
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  */
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:
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;
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
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 
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 
1335 int coap_dtls_is_supported(void) {
1336 #if defined(MBEDTLS_SSL_PROTO_DTLS)
1337  return 1;
1338 #else /* !MBEDTLS_SSL_PROTO_DTLS */
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 
1346 int coap_tls_is_supported(void)
1347 {
1348  return 0;
1349 }
1350 
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
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
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) {
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 
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 
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) {
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) {
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 
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 
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 
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,
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 
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 
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 
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 
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:
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) {
1636  ret = -1;
1637  }
1638  }
1639  return ret;
1640 }
1641 
1643 {
1644  return 0;
1645 }
1646 
1648 {
1649  return 0;
1650 }
1651 
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 
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 */
1701  }
1702  return;
1703 }
1704 
1705 /*
1706  * return +ve data amount
1707  * 0 no more
1708  * -1 error
1709  */
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) {
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:
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) {
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  */
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 
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
1903  int *connected COAP_UNUSED)
1904 {
1905  return NULL;
1906 }
1907 
1909  int *connected COAP_UNUSED)
1910 {
1911  return NULL;
1912 }
1913 
1915 {
1916 }
1917 
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 
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 
1935 void coap_dtls_startup(void)
1936 {
1937 }
1938 
1939 void coap_dtls_shutdown(void) {
1940 }
1941 
1942 void *
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 
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 
1984 int coap_dtls_get_log_level(void)
1985 {
1986  return keep_log_level;
1987 }
1988 
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 
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
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
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
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
2041 static inline void dummy(void) {
2042 }
2043 
2044 #endif /* HAVE_MBEDTLS */
Pulls together all the internal only header files.
#define COAP_RXBUFFER_SIZE
Definition: coap_io.h:24
@ COAP_NACK_TLS_FAILED
Definition: coap_io.h:68
static void dummy(void)
void * coap_dtls_new_server_session(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:105
int coap_dtls_context_set_spsk(coap_context_t *ctx COAP_UNUSED, coap_dtls_spsk_t *setup_data COAP_UNUSED)
Definition: coap_notls.c:58
void coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:140
int coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, const coap_dtls_pki_t *setup_data COAP_UNUSED, const coap_dtls_role_t role COAP_UNUSED)
Definition: coap_notls.c:35
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition: coap_notls.c:136
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition: coap_notls.c:97
int coap_dtls_send(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:120
void * coap_dtls_new_client_session(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:109
ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED, uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:181
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition: coap_notls.c:131
int coap_dtls_receive(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:144
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:159
void * coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:163
void * coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:167
int coap_dtls_hello(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:152
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition: coap_notls.c:65
int coap_dtls_context_set_cpsk(coap_context_t *ctx COAP_UNUSED, coap_dtls_cpsk_t *setup_data COAP_UNUSED)
Definition: coap_notls.c:51
ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:174
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:116
int coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED, const char *ca_file COAP_UNUSED, const char *ca_path COAP_UNUSED)
Definition: coap_notls.c:43
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition: coap_notls.c:102
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:113
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition: coap_notls.c:76
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:171
void coap_digest_free(coap_digest_ctx_t *digest_ctx)
Free off coap_digest_ctx_t.
Definition: coap_notls.c:205
coap_digest_ctx_t * coap_digest_setup(void)
Initialize a coap_digest.
Definition: coap_notls.c:194
int coap_digest_final(coap_digest_ctx_t *digest_ctx, coap_digest_t *digest_buffer)
Finalize the coap_digest information into the provided digest_buffer.
Definition: coap_notls.c:222
int coap_digest_update(coap_digest_ctx_t *digest_ctx, const uint8_t *data, size_t data_len)
Update the coap_digest information with the next chunk of data.
Definition: coap_notls.c:210
void coap_digest_ctx_t
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:122
int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *msg, size_t msg_len)
Parses and interprets a CoAP datagram with context ctx.
Definition: net.c:1898
int coap_handle_event(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
Definition: net.c:3163
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition: coap_notls.c:72
#define COAP_DTLS_RETRANSMIT_MS
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition: coap_notls.c:127
void coap_dtls_shutdown(void)
Close down the underlying (D)TLS Library layer.
Definition: coap_notls.c:83
#define COAP_DTLS_RETRANSMIT_COAP_TICKS
#define COAP_DTLS_RETRANSMIT_TOTAL_MS
coap_dtls_role_t
Definition: coap_dtls.h:31
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition: coap_notls.c:22
coap_tls_version_t * coap_get_tls_library_version(void)
Determine the type and version of the underlying (D)TLS library.
Definition: coap_notls.c:27
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_notls.c:17
coap_tls_library_t
Definition: coap_dtls.h:52
@ COAP_DTLS_ROLE_SERVER
Internal function invoked for server.
Definition: coap_dtls.h:33
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
Definition: coap_dtls.h:32
@ COAP_PKI_KEY_PKCS11
The PKI key type is PKCS11 (DER)
Definition: coap_dtls.h:152
@ COAP_PKI_KEY_PEM_BUF
The PKI key type is PEM buffer.
Definition: coap_dtls.h:151
@ COAP_PKI_KEY_PEM
The PKI key type is PEM file.
Definition: coap_dtls.h:149
@ COAP_PKI_KEY_ASN1
The PKI key type is ASN.1 (DER) buffer.
Definition: coap_dtls.h:150
@ COAP_TLS_LIBRARY_MBEDTLS
Using Mbed TLS library.
Definition: coap_dtls.h:57
#define COAP_EVENT_DTLS_ERROR
Definition: coap_event.h:35
#define COAP_EVENT_DTLS_CLOSED
(D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
Definition: coap_event.h:32
#define COAP_EVENT_DTLS_CONNECTED
Definition: coap_event.h:33
void coap_dtls_set_log_level(int level)
Sets the (D)TLS logging level to the specified level.
Definition: coap_notls.c:87
const char * coap_session_str(const coap_session_t *session)
Get session description.
int coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition: coap_notls.c:92
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:152
@ LOG_ERR
Error.
Definition: coap_debug.h:55
@ LOG_INFO
Information.
Definition: coap_debug.h:58
@ LOG_WARNING
Warning.
Definition: coap_debug.h:56
@ LOG_DEBUG
Debug.
Definition: coap_debug.h:59
@ COAP_LOG_CIPHERS
CipherInfo.
Definition: coap_debug.h:60
@ LOG_EMERG
Emergency.
Definition: coap_debug.h:52
@ COAP_PROTO_DTLS
Definition: pdu.h:283
@ COAP_PROTO_TLS
Definition: pdu.h:285
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
Definition: coap_session.c:996
ssize_t coap_session_send(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for datagram data transmission.
Definition: coap_session.c:277
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
Definition: coap_session.c:399
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:456
@ COAP_SESSION_STATE_HANDSHAKE
Definition: coap_session.h:55
#define COAP_UNUSED
Definition: libcoap.h:55
coap_address_t remote
remote address and port
Definition: coap_io.h:51
CoAP binary data definition with const data.
Definition: str.h:58
size_t length
length of binary data
Definition: str.h:59
const uint8_t * s
read-only binary data
Definition: str.h:60
The CoAP stack's global state is stored in a coap_context_t object.
size_t(* get_server_psk)(const coap_session_t *session, const uint8_t *identity, size_t identity_len, uint8_t *psk, size_t max_psk_len)
size_t(* get_client_psk)(const coap_session_t *session, const uint8_t *hint, size_t hint_len, uint8_t *identity, size_t *identity_len, size_t max_identity_len, uint8_t *psk, size_t max_psk_len)
coap_dtls_spsk_t spsk_setup_data
Contains the initial PSK server setup data.
The structure used for defining the Client PSK setup data to be used.
Definition: coap_dtls.h:338
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition: coap_dtls.h:362
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition: coap_dtls.h:358
The structure that holds the PKI key information.
Definition: coap_dtls.h:212
coap_pki_key_pem_t pem
for PEM file keys
Definition: coap_dtls.h:215
union coap_dtls_key_t::@2 key
coap_pki_key_pem_buf_t pem_buf
for PEM memory keys
Definition: coap_dtls.h:216
coap_pki_key_t key_type
key format type
Definition: coap_dtls.h:213
coap_pki_key_asn1_t asn1
for ASN.1 (DER) memory keys
Definition: coap_dtls.h:217
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:244
uint8_t verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
Definition: coap_dtls.h:249
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition: coap_dtls.h:262
uint8_t check_common_ca
1 if peer cert is to be signed by the same CA as the local cert
Definition: coap_dtls.h:250
coap_dtls_key_t pki_key
PKI key definition.
Definition: coap_dtls.h:301
The structure that holds the Server Pre-Shared Key and Identity Hint information.
Definition: coap_dtls.h:374
The structure used for defining the Server PSK setup data to be used.
Definition: coap_dtls.h:425
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition: coap_dtls.h:452
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition: coap_dtls.h:444
void * id_call_back_arg
Passed in to the Identity callback function.
Definition: coap_dtls.h:445
void * sni_call_back_arg
Passed in to the SNI callback function.
Definition: coap_dtls.h:453
const uint8_t * private_key
ASN1 (DER) Private Key.
Definition: coap_dtls.h:190
size_t public_cert_len
ASN1 Public Cert length.
Definition: coap_dtls.h:192
size_t private_key_len
ASN1 Private Key length.
Definition: coap_dtls.h:193
const uint8_t * ca_cert
ASN1 (DER) Common CA Cert.
Definition: coap_dtls.h:188
size_t ca_cert_len
ASN1 CA Cert length.
Definition: coap_dtls.h:191
const uint8_t * public_cert
ASN1 (DER) Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:189
size_t ca_cert_len
PEM buffer CA Cert length.
Definition: coap_dtls.h:179
const uint8_t * ca_cert
PEM buffer Common CA Cert.
Definition: coap_dtls.h:174
size_t private_key_len
PEM buffer Private Key length.
Definition: coap_dtls.h:181
const uint8_t * private_key
PEM buffer Private Key If RPK and 'EC PRIVATE KEY' this can be used for both the public_cert and priv...
Definition: coap_dtls.h:176
size_t public_cert_len
PEM buffer Public Cert length.
Definition: coap_dtls.h:180
const uint8_t * public_cert
PEM buffer Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:175
const char * ca_file
File location of Common CA in PEM format.
Definition: coap_dtls.h:159
const char * public_cert
File location of Public Cert.
Definition: coap_dtls.h:160
const char * private_key
File location of Private Key in PEM format.
Definition: coap_dtls.h:161
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
unsigned int dtls_timeout_count
dtls setup retry counter
unsigned int max_retransmit
maximum re-transmit count (default 4)
coap_session_state_t state
current state of relationaship with peer
coap_addr_tuple_t addr_info
key: remote/local address info
coap_proto_t proto
protocol used
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
size_t mtu
path or CSM mtu
int dtls_event
Tracking any (D)TLS events on this sesison.
void * tls
security parameters
coap_context_t * context
session's context
The structure used for returning the underlying (D)TLS library information.
Definition: coap_dtls.h:64
uint64_t built_version
(D)TLS Built against Library Version
Definition: coap_dtls.h:67
coap_tls_library_t type
Library type.
Definition: coap_dtls.h:66
uint64_t version
(D)TLS runtime Library Version
Definition: coap_dtls.h:65