libcoap  4.2.0
coap_openssl.c
Go to the documentation of this file.
1 /*
2 * coap_openssl.c -- Datagram Transport Layer Support for libcoap with openssl
3 *
4 * Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
5 * Copyright (C) 2018 Jon Shallow <supjps-libcoap@jpshallow.com>
6 *
7 * This file is part of the CoAP library libcoap. Please see README for terms
8 * of use.
9 */
10 
11 #include "coap_config.h"
12 
13 #ifdef HAVE_OPENSSL
14 
15 /*
16  * OpenSSL 1.1.0 has support for making decisions during receipt of
17  * the Client Hello - the call back function is set up using
18  * SSL_CTX_set_tlsext_servername_callback() which is called later in the
19  * Client Hello processing - but called every Client Hello.
20  * Certificates and Preshared Keys have to be set up in the SSL CTX before
21  * SSL_Accept() is called, making the code messy to decide whether this is a
22  * PKI or PSK incoming request to handle things accordingly if both are
23  * defined. SNI has to create a new SSL CTX to handle different server names
24  * with different crtificates.
25  *
26  * OpenSSL 1.1.1 introduces a new function SSL_CTX_set_client_hello_cb().
27  * The call back is invoked early on in the Client Hello processing giving
28  * the ability to easily use different Preshared Keys, Certificates etc.
29  * Certificates do not have to be set up in the SSL CTX before SSL_Accept is
30  * called.
31  * Later in the Client Hello code, the callback for
32  * SSL_CTX_set_tlsext_servername_callback() is still called, but only if SNI
33  * is being used by the client, so cannot be used for doing things the
34  * OpenSSL 1.1.0 way.
35  *
36  * OpenSSL 1.1.1 supports TLS1.3.
37  *
38  * Consequently, this code has to have compile time options to include /
39  * exclude code based on whether compiled against 1.1.0 or 1.1.1, as well as
40  * have additional run time checks.
41  *
42  */
43 #include "net.h"
44 #include "mem.h"
45 #include "coap_debug.h"
46 #include "prng.h"
47 #include <openssl/ssl.h>
48 #include <openssl/err.h>
49 #include <openssl/rand.h>
50 #include <openssl/hmac.h>
51 #include <openssl/x509v3.h>
52 
53 #if OPENSSL_VERSION_NUMBER < 0x10100000L
54 #error Must be compiled against OpenSSL 1.1.0 or later
55 #endif
56 
57 #ifdef __GNUC__
58 #define UNUSED __attribute__((unused))
59 #else
60 #define UNUSED
61 #endif /* __GNUC__ */
62 
63 /* RFC6091/RFC7250 */
64 #ifndef TLSEXT_TYPE_client_certificate_type
65 #define TLSEXT_TYPE_client_certificate_type 19
66 #endif
67 #ifndef TLSEXT_TYPE_server_certificate_type
68 #define TLSEXT_TYPE_server_certificate_type 20
69 #endif
70 
71 /* This structure encapsulates the OpenSSL context object. */
72 typedef struct coap_dtls_context_t {
73  SSL_CTX *ctx;
74  SSL *ssl; /* OpenSSL object for listening to connection requests */
75  HMAC_CTX *cookie_hmac;
76  BIO_METHOD *meth;
77  BIO_ADDR *bio_addr;
78 } coap_dtls_context_t;
79 
80 typedef struct coap_tls_context_t {
81  SSL_CTX *ctx;
82  BIO_METHOD *meth;
83 } coap_tls_context_t;
84 
85 #define IS_PSK 0x1
86 #define IS_PKI 0x2
87 
88 typedef struct sni_entry {
89  char *sni;
90 #if OPENSSL_VERSION_NUMBER < 0x10101000L
91  SSL_CTX *ctx;
92 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
93  coap_dtls_key_t pki_key;
94 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
95 } sni_entry;
96 
97 typedef struct coap_openssl_context_t {
98  coap_dtls_context_t dtls;
99  coap_tls_context_t tls;
100  coap_dtls_pki_t setup_data;
101  int psk_pki_enabled;
102  size_t sni_count;
103  sni_entry *sni_entry_list;
104 } coap_openssl_context_t;
105 
106 int coap_dtls_is_supported(void) {
107  if (SSLeay() < 0x10100000L) {
108  coap_log(LOG_WARNING, "OpenSSL version 1.1.0 or later is required\n");
109  return 0;
110  }
111 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
112  /*
113  * For 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
114  * which is not in 1.1.0 instead of SSL_CTX_set_tlsext_servername_callback()
115  *
116  * However, there could be a runtime undefined external reference error
117  * as SSL_CTX_set_client_hello_cb() is not there in 1.1.0.
118  */
119  if (SSLeay() < 0x10101000L) {
120  coap_log(LOG_WARNING, "OpenSSL version 1.1.1 or later is required\n");
121  return 0;
122  }
123 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
124  return 1;
125 }
126 
127 int coap_tls_is_supported(void) {
128  if (SSLeay() < 0x10100000L) {
129  coap_log(LOG_WARNING, "OpenSSL version 1.1.0 or later is required\n");
130  return 0;
131  }
132 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
133  if (SSLeay() < 0x10101000L) {
134  coap_log(LOG_WARNING, "OpenSSL version 1.1.1 or later is required\n");
135  return 0;
136  }
137 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
138  return 1;
139 }
140 
143  static coap_tls_version_t version;
144  version.version = SSLeay();
145  version.built_version = OPENSSL_VERSION_NUMBER;
146  version.type = COAP_TLS_LIBRARY_OPENSSL;
147  return &version;
148 }
149 
150 void coap_dtls_startup(void) {
151  SSL_load_error_strings();
152  SSL_library_init();
153 }
154 
155 static int dtls_log_level = 0;
156 
157 void coap_dtls_set_log_level(int level) {
158  dtls_log_level = level;
159 }
160 
161 int coap_dtls_get_log_level(void) {
162  return dtls_log_level;
163 }
164 
165 typedef struct coap_ssl_st {
166  coap_session_t *session;
167  const void *pdu;
168  unsigned pdu_len;
169  unsigned peekmode;
170  coap_tick_t timeout;
171 } coap_ssl_data;
172 
173 static int coap_dgram_create(BIO *a) {
174  coap_ssl_data *data = NULL;
175  data = malloc(sizeof(coap_ssl_data));
176  if (data == NULL)
177  return 0;
178  BIO_set_init(a, 1);
179  BIO_set_data(a, data);
180  memset(data, 0x00, sizeof(coap_ssl_data));
181  return 1;
182 }
183 
184 static int coap_dgram_destroy(BIO *a) {
185  coap_ssl_data *data;
186  if (a == NULL)
187  return 0;
188  data = (coap_ssl_data *)BIO_get_data(a);
189  if (data != NULL)
190  free(data);
191  return 1;
192 }
193 
194 static int coap_dgram_read(BIO *a, char *out, int outl) {
195  int ret = 0;
196  coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
197 
198  if (out != NULL) {
199  if (data != NULL && data->pdu_len > 0) {
200  if (outl < (int)data->pdu_len) {
201  memcpy(out, data->pdu, outl);
202  ret = outl;
203  } else {
204  memcpy(out, data->pdu, data->pdu_len);
205  ret = (int)data->pdu_len;
206  }
207  if (!data->peekmode) {
208  data->pdu_len = 0;
209  data->pdu = NULL;
210  }
211  } else {
212  ret = -1;
213  }
214  BIO_clear_retry_flags(a);
215  if (ret < 0)
216  BIO_set_retry_read(a);
217  }
218  return ret;
219 }
220 
221 static int coap_dgram_write(BIO *a, const char *in, int inl) {
222  int ret = 0;
223  coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
224 
225  if (data->session) {
226  if (data->session->sock.flags == COAP_SOCKET_EMPTY && data->session->endpoint == NULL) {
227  /* socket was closed on client due to error */
228  BIO_clear_retry_flags(a);
229  return -1;
230  }
231  ret = (int)coap_session_send(data->session, (const uint8_t *)in, (size_t)inl);
232  BIO_clear_retry_flags(a);
233  if (ret <= 0)
234  BIO_set_retry_write(a);
235  } else {
236  BIO_clear_retry_flags(a);
237  ret = -1;
238  }
239  return ret;
240 }
241 
242 static int coap_dgram_puts(BIO *a, const char *pstr) {
243  return coap_dgram_write(a, pstr, (int)strlen(pstr));
244 }
245 
246 static long coap_dgram_ctrl(BIO *a, int cmd, long num, void *ptr) {
247  long ret = 1;
248  coap_ssl_data *data = BIO_get_data(a);
249 
250  (void)ptr;
251 
252  switch (cmd) {
253  case BIO_CTRL_GET_CLOSE:
254  ret = BIO_get_shutdown(a);
255  break;
256  case BIO_CTRL_SET_CLOSE:
257  BIO_set_shutdown(a, (int)num);
258  ret = 1;
259  break;
260  case BIO_CTRL_DGRAM_SET_PEEK_MODE:
261  data->peekmode = (unsigned)num;
262  break;
263  case BIO_CTRL_DGRAM_CONNECT:
264  case BIO_C_SET_FD:
265  case BIO_C_GET_FD:
266  case BIO_CTRL_DGRAM_SET_DONT_FRAG:
267  case BIO_CTRL_DGRAM_GET_MTU:
268  case BIO_CTRL_DGRAM_SET_MTU:
269  case BIO_CTRL_DGRAM_QUERY_MTU:
270  case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
271  ret = -1;
272  break;
273  case BIO_CTRL_DUP:
274  case BIO_CTRL_FLUSH:
275  case BIO_CTRL_DGRAM_MTU_DISCOVER:
276  case BIO_CTRL_DGRAM_SET_CONNECTED:
277  ret = 1;
278  break;
279  case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
280  data->timeout = coap_ticks_from_rt_us((uint64_t)((struct timeval*)ptr)->tv_sec * 1000000 + ((struct timeval*)ptr)->tv_usec);
281  ret = 1;
282  break;
283  case BIO_CTRL_RESET:
284  case BIO_C_FILE_SEEK:
285  case BIO_C_FILE_TELL:
286  case BIO_CTRL_INFO:
287  case BIO_CTRL_PENDING:
288  case BIO_CTRL_WPENDING:
289  case BIO_CTRL_DGRAM_GET_PEER:
290  case BIO_CTRL_DGRAM_SET_PEER:
291  case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
292  case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
293  case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
294  case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
295  case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
296  case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
297  case BIO_CTRL_DGRAM_MTU_EXCEEDED:
298  case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
299  default:
300  ret = 0;
301  break;
302  }
303  return ret;
304 }
305 
306 static int coap_dtls_generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) {
307  coap_dtls_context_t *dtls = (coap_dtls_context_t *)SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl));
308  coap_ssl_data *data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
309  int r = HMAC_Init_ex(dtls->cookie_hmac, NULL, 0, NULL, NULL);
310  r &= HMAC_Update(dtls->cookie_hmac, (const uint8_t*)&data->session->local_addr.addr, (size_t)data->session->local_addr.size);
311  r &= HMAC_Update(dtls->cookie_hmac, (const uint8_t*)&data->session->remote_addr.addr, (size_t)data->session->remote_addr.size);
312  r &= HMAC_Final(dtls->cookie_hmac, cookie, cookie_len);
313  return r;
314 }
315 
316 static int coap_dtls_verify_cookie(SSL *ssl, const uint8_t *cookie, unsigned int cookie_len) {
317  uint8_t hmac[32];
318  unsigned len = 32;
319  if (coap_dtls_generate_cookie(ssl, hmac, &len) && cookie_len == len && memcmp(cookie, hmac, len) == 0)
320  return 1;
321  else
322  return 0;
323 }
324 
325 static unsigned coap_dtls_psk_client_callback(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *buf, unsigned max_len) {
326  size_t hint_len = 0, identity_len = 0, psk_len;
327  coap_session_t *session = (coap_session_t*)SSL_get_app_data(ssl);
328 
329  if (hint)
330  hint_len = strlen(hint);
331  else
332  hint = "";
333 
334  coap_log(LOG_DEBUG, "got psk_identity_hint: '%.*s'\n", (int)hint_len, hint);
335 
336  if (session == NULL || session->context == NULL || session->context->get_client_psk == NULL)
337  return 0;
338 
339  psk_len = session->context->get_client_psk(session, (const uint8_t*)hint, hint_len, (uint8_t*)identity, &identity_len, max_identity_len - 1, (uint8_t*)buf, max_len);
340  if (identity_len < max_identity_len)
341  identity[identity_len] = 0;
342  return (unsigned)psk_len;
343 }
344 
345 static unsigned coap_dtls_psk_server_callback(SSL *ssl, const char *identity, unsigned char *buf, unsigned max_len) {
346  size_t identity_len = 0;
347  coap_session_t *session = (coap_session_t*)SSL_get_app_data(ssl);
348 
349  if (identity)
350  identity_len = strlen(identity);
351  else
352  identity = "";
353 
354  coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n",
355  (int)identity_len, identity);
356 
357  if (session == NULL || session->context == NULL || session->context->get_server_psk == NULL)
358  return 0;
359 
360  return (unsigned)session->context->get_server_psk(session, (const uint8_t*)identity, identity_len, (uint8_t*)buf, max_len);
361 }
362 
363 static void coap_dtls_info_callback(const SSL *ssl, int where, int ret) {
364  coap_session_t *session = (coap_session_t*)SSL_get_app_data(ssl);
365  const char *pstr;
366  int w = where &~SSL_ST_MASK;
367 
368  if (w & SSL_ST_CONNECT)
369  pstr = "SSL_connect";
370  else if (w & SSL_ST_ACCEPT)
371  pstr = "SSL_accept";
372  else
373  pstr = "undefined";
374 
375  if (where & SSL_CB_LOOP) {
376  if (dtls_log_level >= LOG_DEBUG)
377  coap_log(LOG_DEBUG, "* %s: %s:%s\n",
378  coap_session_str(session), pstr, SSL_state_string_long(ssl));
379  } else if (where & SSL_CB_ALERT) {
380  pstr = (where & SSL_CB_READ) ? "read" : "write";
381  if (dtls_log_level >= LOG_INFO)
382  coap_log(LOG_INFO, "* %s: SSL3 alert %s:%s:%s\n",
383  coap_session_str(session),
384  pstr,
385  SSL_alert_type_string_long(ret),
386  SSL_alert_desc_string_long(ret));
387  if ((where & (SSL_CB_WRITE|SSL_CB_READ)) && (ret >> 8) == SSL3_AL_FATAL)
389  } else if (where & SSL_CB_EXIT) {
390  if (ret == 0) {
391  if (dtls_log_level >= LOG_WARNING) {
392  unsigned long e;
393  coap_log(LOG_WARNING, "* %s: %s:failed in %s\n",
394  coap_session_str(session), pstr, SSL_state_string_long(ssl));
395  while ((e = ERR_get_error()))
396  coap_log(LOG_WARNING, "* %s: %s at %s:%s\n",
397  coap_session_str(session), ERR_reason_error_string(e),
398  ERR_lib_error_string(e), ERR_func_error_string(e));
399  }
400  } else if (ret < 0) {
401  if (dtls_log_level >= LOG_WARNING) {
402  int err = SSL_get_error(ssl, ret);
403  if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE && err != SSL_ERROR_WANT_CONNECT && err != SSL_ERROR_WANT_ACCEPT && err != SSL_ERROR_WANT_X509_LOOKUP) {
404  long e;
405  coap_log(LOG_WARNING, "* %s: %s:error in %s\n",
406  coap_session_str(session), pstr, SSL_state_string_long(ssl));
407  while ((e = ERR_get_error()))
408  coap_log(LOG_WARNING, "* %s: %s at %s:%s\n",
409  coap_session_str(session), ERR_reason_error_string(e),
410  ERR_lib_error_string(e), ERR_func_error_string(e));
411  }
412  }
413  }
414  }
415 
416  if (where == SSL_CB_HANDSHAKE_START && SSL_get_state(ssl) == TLS_ST_OK)
418 }
419 
420 static int coap_sock_create(BIO *a) {
421  BIO_set_init(a, 1);
422  return 1;
423 }
424 
425 static int coap_sock_destroy(BIO *a) {
426  (void)a;
427  return 1;
428 }
429 
430 static int coap_sock_read(BIO *a, char *out, int outl) {
431  int ret = 0;
432  coap_session_t *session = (coap_session_t *)BIO_get_data(a);
433 
434  if (out != NULL) {
435  ret = (int)coap_socket_read(&session->sock, (uint8_t*)out, (size_t)outl);
436  if (ret == 0) {
437  BIO_set_retry_read(a);
438  ret = -1;
439  } else {
440  BIO_clear_retry_flags(a);
441  }
442  }
443  return ret;
444 }
445 
446 static int coap_sock_write(BIO *a, const char *in, int inl) {
447  int ret = 0;
448  coap_session_t *session = (coap_session_t *)BIO_get_data(a);
449 
450  ret = (int)coap_socket_write(&session->sock, (const uint8_t*)in, (size_t)inl);
451  BIO_clear_retry_flags(a);
452  if (ret == 0) {
453  BIO_set_retry_read(a);
454  ret = -1;
455  } else {
456  BIO_clear_retry_flags(a);
457  }
458  return ret;
459 }
460 
461 static int coap_sock_puts(BIO *a, const char *pstr) {
462  return coap_sock_write(a, pstr, (int)strlen(pstr));
463 }
464 
465 static long coap_sock_ctrl(BIO *a, int cmd, long num, void *ptr) {
466  int r = 1;
467  (void)a;
468  (void)ptr;
469  (void)num;
470 
471  switch (cmd) {
472  case BIO_C_SET_FD:
473  case BIO_C_GET_FD:
474  r = -1;
475  break;
476  case BIO_CTRL_SET_CLOSE:
477  case BIO_CTRL_DUP:
478  case BIO_CTRL_FLUSH:
479  r = 1;
480  break;
481  default:
482  case BIO_CTRL_GET_CLOSE:
483  r = 0;
484  break;
485  }
486  return r;
487 }
488 
489 void *coap_dtls_new_context(struct coap_context_t *coap_context) {
490  coap_openssl_context_t *context;
491  (void)coap_context;
492 
493  context = (coap_openssl_context_t *)coap_malloc(sizeof(coap_openssl_context_t));
494  if (context) {
495  uint8_t cookie_secret[32];
496 
497  memset(context, 0, sizeof(coap_openssl_context_t));
498 
499  /* Set up DTLS context */
500  context->dtls.ctx = SSL_CTX_new(DTLS_method());
501  if (!context->dtls.ctx)
502  goto error;
503  SSL_CTX_set_min_proto_version(context->dtls.ctx, DTLS1_2_VERSION);
504  SSL_CTX_set_app_data(context->dtls.ctx, &context->dtls);
505  SSL_CTX_set_read_ahead(context->dtls.ctx, 1);
506  SSL_CTX_set_cipher_list(context->dtls.ctx, "TLSv1.2:TLSv1.0");
507  if (!RAND_bytes(cookie_secret, (int)sizeof(cookie_secret))) {
510  "Insufficient entropy for random cookie generation");
511  prng(cookie_secret, sizeof(cookie_secret));
512  }
513  context->dtls.cookie_hmac = HMAC_CTX_new();
514  if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret), EVP_sha256(), NULL))
515  goto error;
516  SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie);
517  SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie);
518  SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback);
519  SSL_CTX_set_options(context->dtls.ctx, SSL_OP_NO_QUERY_MTU);
520  context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM, "coapdgram");
521  if (!context->dtls.meth)
522  goto error;
523  context->dtls.bio_addr = BIO_ADDR_new();
524  if (!context->dtls.bio_addr)
525  goto error;
526  BIO_meth_set_write(context->dtls.meth, coap_dgram_write);
527  BIO_meth_set_read(context->dtls.meth, coap_dgram_read);
528  BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts);
529  BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl);
530  BIO_meth_set_create(context->dtls.meth, coap_dgram_create);
531  BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy);
532 
533  /* Set up TLS context */
534  context->tls.ctx = SSL_CTX_new(TLS_method());
535  if (!context->tls.ctx)
536  goto error;
537  SSL_CTX_set_app_data(context->tls.ctx, &context->tls);
538  SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION);
539  SSL_CTX_set_cipher_list(context->tls.ctx, "TLSv1.2:TLSv1.0");
540  SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback);
541  context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET, "coapsock");
542  if (!context->tls.meth)
543  goto error;
544  BIO_meth_set_write(context->tls.meth, coap_sock_write);
545  BIO_meth_set_read(context->tls.meth, coap_sock_read);
546  BIO_meth_set_puts(context->tls.meth, coap_sock_puts);
547  BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl);
548  BIO_meth_set_create(context->tls.meth, coap_sock_create);
549  BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy);
550  }
551 
552  return context;
553 
554 error:
555  coap_dtls_free_context(context);
556  return NULL;
557 }
558 
559 int
561  const char *identity_hint,
562  coap_dtls_role_t role
563 ) {
564  coap_openssl_context_t *context = ((coap_openssl_context_t *)ctx->dtls_context);
565  BIO *bio;
566 
567  if (role == COAP_DTLS_ROLE_SERVER) {
568  SSL_CTX_set_psk_server_callback(context->dtls.ctx, coap_dtls_psk_server_callback);
569  SSL_CTX_set_psk_server_callback(context->tls.ctx, coap_dtls_psk_server_callback);
570  SSL_CTX_use_psk_identity_hint(context->dtls.ctx, identity_hint ? identity_hint : "");
571  SSL_CTX_use_psk_identity_hint(context->tls.ctx, identity_hint ? identity_hint : "");
572  }
573  if (!context->dtls.ssl) {
574  /* This is set up to handle new incoming sessions to a server */
575  context->dtls.ssl = SSL_new(context->dtls.ctx);
576  if (!context->dtls.ssl)
577  return 0;
578  bio = BIO_new(context->dtls.meth);
579  if (!bio) {
580  SSL_free (context->dtls.ssl);
581  context->dtls.ssl = NULL;
582  return 0;
583  }
584  SSL_set_bio(context->dtls.ssl, bio, bio);
585  SSL_set_app_data(context->dtls.ssl, NULL);
586  SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
587  SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
588  }
589  context->psk_pki_enabled |= IS_PSK;
590  return 1;
591 }
592 
593 static int
594 map_key_type(int asn1_private_key_type
595 ) {
596  switch (asn1_private_key_type) {
597  case COAP_ASN1_PKEY_NONE: return EVP_PKEY_NONE;
598  case COAP_ASN1_PKEY_RSA: return EVP_PKEY_RSA;
599  case COAP_ASN1_PKEY_RSA2: return EVP_PKEY_RSA2;
600  case COAP_ASN1_PKEY_DSA: return EVP_PKEY_DSA;
601  case COAP_ASN1_PKEY_DSA1: return EVP_PKEY_DSA1;
602  case COAP_ASN1_PKEY_DSA2: return EVP_PKEY_DSA2;
603  case COAP_ASN1_PKEY_DSA3: return EVP_PKEY_DSA3;
604  case COAP_ASN1_PKEY_DSA4: return EVP_PKEY_DSA4;
605  case COAP_ASN1_PKEY_DH: return EVP_PKEY_DH;
606  case COAP_ASN1_PKEY_DHX: return EVP_PKEY_DHX;
607  case COAP_ASN1_PKEY_EC: return EVP_PKEY_EC;
608  case COAP_ASN1_PKEY_HMAC: return EVP_PKEY_HMAC;
609  case COAP_ASN1_PKEY_CMAC: return EVP_PKEY_CMAC;
610  case COAP_ASN1_PKEY_TLS1_PRF: return EVP_PKEY_TLS1_PRF;
611  case COAP_ASN1_PKEY_HKDF: return EVP_PKEY_HKDF;
612  default:
614  "*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
615  asn1_private_key_type);
616  break;
617  }
618  return 0;
619 }
620 static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
621 
622 static int
623 server_alpn_callback (SSL *ssl UNUSED,
624  const unsigned char **out,
625  unsigned char *outlen,
626  const unsigned char *in,
627  unsigned int inlen,
628  void *arg UNUSED
629 ) {
630  unsigned char *tout = NULL;
631  int ret;
632  if (inlen == 0)
633  return SSL_TLSEXT_ERR_NOACK;
634  ret = SSL_select_next_proto(&tout,
635  outlen,
636  coap_alpn,
637  sizeof(coap_alpn),
638  in,
639  inlen);
640  *out = tout;
641  return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
642 }
643 
644 static void
645 add_ca_to_cert_store(X509_STORE *st, X509 *x509)
646 {
647  long e;
648 
649  /* Flush out existing errors */
650  while ((e = ERR_get_error()) != 0) {
651  }
652 
653  if (!X509_STORE_add_cert(st, x509)) {
654  while ((e = ERR_get_error()) != 0) {
655  int r = ERR_GET_REASON(e);
656  if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
657  /* Not already added */
658  coap_log(LOG_WARNING, "***setup_pki: (D)TLS: %s at %s:%s\n",
659  ERR_reason_error_string(e),
660  ERR_lib_error_string(e),
661  ERR_func_error_string(e));
662  }
663  }
664  }
665 }
666 
667 #if OPENSSL_VERSION_NUMBER < 0x10101000L
668 static int
669 setup_pki_server(SSL_CTX *ctx,
670  coap_dtls_pki_t* setup_data
671 ) {
672  switch (setup_data->pki_key.key_type) {
673  case COAP_PKI_KEY_PEM:
674  if (setup_data->pki_key.key.pem.public_cert &&
675  setup_data->pki_key.key.pem.public_cert[0]) {
676  if (!(SSL_CTX_use_certificate_file(ctx,
677  setup_data->pki_key.key.pem.public_cert,
678  SSL_FILETYPE_PEM))) {
680  "*** setup_pki: (D)TLS: %s: Unable to configure "
681  "Server Certificate\n",
682  setup_data->pki_key.key.pem.public_cert);
683  return 0;
684  }
685  }
686  else {
688  "*** setup_pki: (D)TLS: No Server Certificate defined\n");
689  return 0;
690  }
691 
692  if (setup_data->pki_key.key.pem.private_key &&
693  setup_data->pki_key.key.pem.private_key[0]) {
694  if (!(SSL_CTX_use_PrivateKey_file(ctx,
695  setup_data->pki_key.key.pem.private_key,
696  SSL_FILETYPE_PEM))) {
698  "*** setup_pki: (D)TLS: %s: Unable to configure "
699  "Server Private Key\n",
700  setup_data->pki_key.key.pem.private_key);
701  return 0;
702  }
703  }
704  else {
706  "*** setup_pki: (D)TLS: No Server Private Key defined\n");
707  return 0;
708  }
709 
710  if (setup_data->pki_key.key.pem.ca_file &&
711  setup_data->pki_key.key.pem.ca_file[0]) {
712  STACK_OF(X509_NAME) *cert_names;
713  X509_STORE *st;
714  BIO *in;
715  X509 *x = NULL;
716  char *rw_var = NULL;
717  cert_names = SSL_load_client_CA_file(setup_data->pki_key.key.pem.ca_file);
718  if (cert_names != NULL)
719  SSL_CTX_set_client_CA_list(ctx, cert_names);
720  else {
722  "*** setup_pki: (D)TLS: %s: Unable to configure "
723  "client CA File\n",
724  setup_data->pki_key.key.pem.ca_file);
725  return 0;
726  }
727  st = SSL_CTX_get_cert_store(ctx);
728  in = BIO_new(BIO_s_file());
729  /* Need to do this to not get a compiler warning about const parameters */
730  memcpy(&rw_var, &setup_data->pki_key.key.pem.ca_file, sizeof (rw_var));
731  if (!BIO_read_filename(in, rw_var)) {
732  BIO_free(in);
733  X509_free(x);
734  break;
735  }
736 
737  for (;;) {
738  if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
739  break;
740  add_ca_to_cert_store(st, x);
741  }
742  BIO_free(in);
743  X509_free(x);
744  }
745  break;
746 
747  case COAP_PKI_KEY_ASN1:
748  if (setup_data->pki_key.key.asn1.public_cert &&
749  setup_data->pki_key.key.asn1.public_cert_len > 0) {
750  if (!(SSL_CTX_use_certificate_ASN1(ctx,
751  setup_data->pki_key.key.asn1.public_cert_len,
752  setup_data->pki_key.key.asn1.public_cert))) {
754  "*** setup_pki: (D)TLS: %s: Unable to configure "
755  "Server Certificate\n",
756  "ASN1");
757  return 0;
758  }
759  }
760  else {
762  "*** setup_pki: (D)TLS: No Server Certificate defined\n");
763  return 0;
764  }
765 
766  if (setup_data->pki_key.key.asn1.private_key &&
767  setup_data->pki_key.key.asn1.private_key_len > 0) {
768  int pkey_type = map_key_type(setup_data->pki_key.key.asn1.private_key_type);
769  if (!(SSL_CTX_use_PrivateKey_ASN1(pkey_type, ctx,
770  setup_data->pki_key.key.asn1.private_key,
771  setup_data->pki_key.key.asn1.private_key_len))) {
773  "*** setup_pki: (D)TLS: %s: Unable to configure "
774  "Server Private Key\n",
775  "ASN1");
776  return 0;
777  }
778  }
779  else {
781  "*** setup_pki: (D)TLS: No Server Private Key defined\n");
782  return 0;
783  }
784 
785  if (setup_data->pki_key.key.asn1.ca_cert &&
786  setup_data->pki_key.key.asn1.ca_cert_len > 0) {
787  /* Need to use a temp variable as it gets incremented*/
788  const uint8_t *p = setup_data->pki_key.key.asn1.ca_cert;
789  X509* x509 = d2i_X509(NULL, &p, setup_data->pki_key.key.asn1.ca_cert_len);
790  X509_STORE *st;
791  if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
793  "*** setup_pki: (D)TLS: %s: Unable to configure "
794  "client CA File\n",
795  "ASN1");
796  X509_free(x509);
797  return 0;
798  }
799  st = SSL_CTX_get_cert_store(ctx);
800  add_ca_to_cert_store(st, x509);
801  X509_free(x509);
802  }
803  break;
804  default:
806  "*** setup_pki: (D)TLS: Unknown key type %d\n",
807  setup_data->pki_key.key_type);
808  return 0;
809  }
810 
811  return 1;
812 }
813 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
814 
815 static int
816 setup_pki_ssl(SSL *ssl,
817  coap_dtls_pki_t* setup_data, coap_dtls_role_t role
818 ) {
819  switch (setup_data->pki_key.key_type) {
820  case COAP_PKI_KEY_PEM:
821  if (setup_data->pki_key.key.pem.public_cert &&
822  setup_data->pki_key.key.pem.public_cert[0]) {
823  if (!(SSL_use_certificate_file(ssl,
824  setup_data->pki_key.key.pem.public_cert,
825  SSL_FILETYPE_PEM))) {
827  "*** setup_pki: (D)TLS: %s: Unable to configure "
828  "%s Certificate\n",
829  setup_data->pki_key.key.pem.public_cert,
830  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
831  return 0;
832  }
833  }
834  else if (role == COAP_DTLS_ROLE_SERVER ||
835  (setup_data->pki_key.key.pem.private_key &&
836  setup_data->pki_key.key.pem.private_key[0])) {
838  "*** setup_pki: (D)TLS: No %s Certificate defined\n",
839  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
840  return 0;
841  }
842  if (setup_data->pki_key.key.pem.private_key &&
843  setup_data->pki_key.key.pem.private_key[0]) {
844  if (!(SSL_use_PrivateKey_file(ssl,
845  setup_data->pki_key.key.pem.private_key,
846  SSL_FILETYPE_PEM))) {
848  "*** setup_pki: (D)TLS: %s: Unable to configure "
849  "Client Private Key\n",
850  setup_data->pki_key.key.pem.private_key);
851  return 0;
852  }
853  }
854  else if (role == COAP_DTLS_ROLE_SERVER ||
855  (setup_data->pki_key.key.pem.public_cert &&
856  setup_data->pki_key.key.pem.public_cert[0])) {
858  "*** setup_pki: (D)TLS: No %s Private Key defined\n",
859  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
860  return 0;
861  }
862  if (setup_data->pki_key.key.pem.ca_file &&
863  setup_data->pki_key.key.pem.ca_file[0]) {
864  X509_STORE *st;
865  BIO *in;
866  X509 *x = NULL;
867  char *rw_var = NULL;
868  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
869 
870  if (role == COAP_DTLS_ROLE_SERVER) {
871  STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(setup_data->pki_key.key.pem.ca_file);
872 
873  if (cert_names != NULL)
874  SSL_set_client_CA_list(ssl, cert_names);
875  else {
877  "*** setup_pki: (D)TLS: %s: Unable to configure "
878  "%s CA File\n",
879  setup_data->pki_key.key.pem.ca_file,
880  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
881  return 0;
882  }
883  }
884 
885  /* Add CA to the trusted root CA store */
886  in = BIO_new(BIO_s_file());
887  /* Need to do this to not get a compiler warning about const parameters */
888  memcpy(&rw_var, &setup_data->pki_key.key.pem.ca_file, sizeof (rw_var));
889  if (!BIO_read_filename(in, rw_var)) {
890  BIO_free(in);
891  X509_free(x);
892  break;
893  }
894  st = SSL_CTX_get_cert_store(ctx);
895  for (;;) {
896  if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
897  break;
898  add_ca_to_cert_store(st, x);
899  }
900  BIO_free(in);
901  X509_free(x);
902  }
903  break;
904 
905  case COAP_PKI_KEY_ASN1:
906  if (setup_data->pki_key.key.asn1.public_cert &&
907  setup_data->pki_key.key.asn1.public_cert_len > 0) {
908  if (!(SSL_use_certificate_ASN1(ssl,
909  setup_data->pki_key.key.asn1.public_cert,
910  setup_data->pki_key.key.asn1.public_cert_len))) {
912  "*** setup_pki: (D)TLS: %s: Unable to configure "
913  "%s Certificate\n",
914  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client",
915  "ASN1");
916  return 0;
917  }
918  }
919  else if (role == COAP_DTLS_ROLE_SERVER ||
920  (setup_data->pki_key.key.asn1.private_key &&
921  setup_data->pki_key.key.asn1.private_key[0])) {
923  "*** setup_pki: (D)TLS: No %s Certificate defined\n",
924  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
925  return 0;
926  }
927  if (setup_data->pki_key.key.asn1.private_key &&
928  setup_data->pki_key.key.asn1.private_key_len > 0) {
929  int pkey_type = map_key_type(setup_data->pki_key.key.asn1.private_key_type);
930  if (!(SSL_use_PrivateKey_ASN1(pkey_type, ssl,
931  setup_data->pki_key.key.asn1.private_key,
932  setup_data->pki_key.key.asn1.private_key_len))) {
934  "*** setup_pki: (D)TLS: %s: Unable to configure "
935  "%s Private Key\n",
936  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client",
937  "ASN1");
938  return 0;
939  }
940  }
941  else if (role == COAP_DTLS_ROLE_SERVER ||
942  (setup_data->pki_key.key.asn1.public_cert &&
943  setup_data->pki_key.key.asn1.public_cert_len > 0)) {
945  "*** setup_pki: (D)TLS: No %s Private Key defined",
946  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
947  return 0;
948  }
949  if (setup_data->pki_key.key.asn1.ca_cert &&
950  setup_data->pki_key.key.asn1.ca_cert_len > 0) {
951  /* Need to use a temp variable as it gets incremented*/
952  const uint8_t *p = setup_data->pki_key.key.asn1.ca_cert;
953  X509* x509 = d2i_X509(NULL, &p, setup_data->pki_key.key.asn1.ca_cert_len);
954  X509_STORE *st;
955  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
956 
957  if (role == COAP_DTLS_ROLE_SERVER) {
958  if (!x509 || !SSL_add_client_CA(ssl, x509)) {
960  "*** setup_pki: (D)TLS: %s: Unable to configure "
961  "client CA File\n",
962  "ASN1");
963  X509_free(x509);
964  return 0;
965  }
966  }
967 
968  /* Add CA to the trusted root CA store */
969  st = SSL_CTX_get_cert_store(ctx);
970  add_ca_to_cert_store(st, x509);
971  X509_free(x509);
972  }
973  break;
974  default:
976  "*** setup_pki: (D)TLS: Unknown key type %d\n",
977  setup_data->pki_key.key_type);
978  return 0;
979  }
980  return 1;
981 }
982 
983 static char*
984 get_common_name_from_cert(X509* x509) {
985  if (x509) {
986  char *cn;
987  int n;
988  STACK_OF(GENERAL_NAME) *san_list;
989  char buffer[256];
990 
991  san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
992  if (san_list) {
993  int san_count = sk_GENERAL_NAME_num(san_list);
994 
995  for (n = 0; n < san_count; n++) {
996  const GENERAL_NAME * name = sk_GENERAL_NAME_value (san_list, n);
997 
998  if (name->type == GEN_DNS) {
999  const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
1000 
1001  /* Make sure that there is not an embedded NUL in the dns_name */
1002  if (ASN1_STRING_length(name->d.dNSName) != (int)strlen (dns_name))
1003  continue;
1004  cn = OPENSSL_strdup(dns_name);
1005  sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
1006  return cn;
1007  }
1008  }
1009  sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
1010  }
1011  /* Otherwise look for the CN= field */
1012  X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
1013 
1014  /* Need to emulate strcasestr() here. Looking for CN= */
1015  n = strlen(buffer) - 3;
1016  cn = buffer;
1017  while (n > 0) {
1018  if (((cn[0] == 'C') || (cn[0] == 'c')) &&
1019  ((cn[1] == 'N') || (cn[1] == 'n')) &&
1020  (cn[2] == '=')) {
1021  cn += 3;
1022  break;
1023  }
1024  cn++;
1025  n--;
1026  }
1027  if (n > 0) {
1028  char * ecn = strchr(cn, '/');
1029  if (ecn) {
1030  return OPENSSL_strndup(cn, ecn-cn);
1031  }
1032  else {
1033  return OPENSSL_strdup(cn);
1034  }
1035  }
1036  }
1037  return NULL;
1038 }
1039 
1040 static int
1041 tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
1042  SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
1043  SSL_get_ex_data_X509_STORE_CTX_idx());
1044  coap_session_t *session = SSL_get_app_data(ssl);
1045  coap_openssl_context_t *context =
1046  ((coap_openssl_context_t *)session->context->dtls_context);
1047  coap_dtls_pki_t *setup_data = &context->setup_data;
1048  int depth = X509_STORE_CTX_get_error_depth(ctx);
1049  int err = X509_STORE_CTX_get_error(ctx);
1050  X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
1051  char *cn = get_common_name_from_cert(x509);
1052  int keep_preverify_ok = preverify_ok;
1053 
1054  if (!preverify_ok) {
1055  switch (err) {
1056  case X509_V_ERR_CERT_NOT_YET_VALID:
1057  case X509_V_ERR_CERT_HAS_EXPIRED:
1058  if (setup_data->allow_expired_certs)
1059  preverify_ok = 1;
1060  break;
1061  case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
1062  if (setup_data->allow_self_signed)
1063  preverify_ok = 1;
1064  break;
1065  case X509_V_ERR_UNABLE_TO_GET_CRL:
1066  if (setup_data->allow_no_crl)
1067  preverify_ok = 1;
1068  break;
1069  case X509_V_ERR_CRL_NOT_YET_VALID:
1070  case X509_V_ERR_CRL_HAS_EXPIRED:
1071  if (setup_data->allow_expired_crl)
1072  preverify_ok = 1;
1073  break;
1074  default:
1075  break;
1076  }
1077  if (!preverify_ok) {
1079  " %s: %s: '%s' depth=%d\n",
1080  coap_session_str(session),
1081  X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1082  /* Invoke the CN callback function for this failure */
1083  keep_preverify_ok = 1;
1084  }
1085  else {
1087  " %s: %s: overridden: '%s' depth=%d\n",
1088  coap_session_str(session),
1089  X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1090  }
1091  }
1092  /* Certificate - depth == 0 is the Client Cert */
1093  if (setup_data->validate_cn_call_back && keep_preverify_ok) {
1094  int length = i2d_X509(x509, NULL);
1095  uint8_t *base_buf;
1096  uint8_t *base_buf2 = base_buf = OPENSSL_malloc(length);
1097 
1098  /* base_buf2 gets moved to the end */
1099  i2d_X509(x509, &base_buf2);
1100  if (!setup_data->validate_cn_call_back(cn, base_buf, length, session,
1101  depth, preverify_ok,
1102  setup_data->cn_call_back_arg)) {
1103  if (depth == 0) {
1104  X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
1105  }
1106  else {
1107  X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
1108  }
1109  preverify_ok = 0;
1110  }
1111  OPENSSL_free(base_buf);
1112  }
1113  OPENSSL_free(cn);
1114  return preverify_ok;
1115 }
1116 
1117 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1118 /*
1119  * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
1120  * it is possible to determine whether this is a PKI or PSK incoming
1121  * request and adjust the Ciphers if necessary
1122  *
1123  * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
1124  */
1125 static int
1126 tls_secret_call_back(SSL *ssl,
1127  void *secret UNUSED,
1128  int *secretlen UNUSED,
1129  STACK_OF(SSL_CIPHER) *peer_ciphers,
1130  const SSL_CIPHER **cipher UNUSED,
1131  void *arg
1132 ) {
1133  int ii;
1134  int psk_requested = 0;
1135  coap_session_t *session = SSL_get_app_data(ssl);
1136  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t*)arg;
1137 
1138  if (session && session->context->psk_key && session->context->psk_key_len) {
1139  /* Is PSK being requested - if so, we need to change algorithms */
1140  for (ii = 0; ii < sk_SSL_CIPHER_num (peer_ciphers); ii++) {
1141  const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
1142 
1143  if (strstr (SSL_CIPHER_get_name (peer_cipher), "PSK")) {
1144  psk_requested = 1;
1145  break;
1146  }
1147  }
1148  }
1149  if (!psk_requested) {
1150  if (session) {
1151  coap_log(LOG_DEBUG, " %s: Using PKI ciphers\n",
1152  coap_session_str(session));
1153  }
1154  else {
1155  coap_log(LOG_DEBUG, "Using PKI ciphers\n");
1156  }
1157  if (setup_data->verify_peer_cert) {
1158  if (setup_data->require_peer_cert) {
1159  SSL_set_verify(ssl,
1160  SSL_VERIFY_PEER |
1161  SSL_VERIFY_CLIENT_ONCE |
1162  SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1163  tls_verify_call_back);
1164  }
1165  else {
1166  SSL_set_verify(ssl,
1167  SSL_VERIFY_PEER |
1168  SSL_VERIFY_CLIENT_ONCE,
1169  tls_verify_call_back);
1170  }
1171  }
1172  else {
1173  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1174  }
1175 
1176  /* Check CA Chain */
1177  if (setup_data->cert_chain_validation)
1178  SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth);
1179 
1180  /* Certificate Revocation */
1181  if (setup_data->check_cert_revocation) {
1182  X509_VERIFY_PARAM *param;
1183 
1184  param = X509_VERIFY_PARAM_new();
1185  X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
1186  SSL_set1_param(ssl, param);
1187  X509_VERIFY_PARAM_free(param);
1188  }
1189  }
1190  else {
1191  if (session) {
1192  if (session->context->psk_key && session->context->psk_key_len) {
1193  memcpy(secret, session->context->psk_key, session->context->psk_key_len);
1194  *secretlen = session->context->psk_key_len;
1195  }
1196  coap_log(LOG_DEBUG, " %s: Setting PSK ciphers\n",
1197  coap_session_str(session));
1198  }
1199  else {
1200  coap_log(LOG_DEBUG, "Setting PSK ciphers\n");
1201  }
1202  /*
1203  * Force a PSK algorithm to be used, so we do PSK
1204  */
1205  SSL_set_cipher_list (ssl, "PSK:!NULL");
1206  SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1207  }
1208  if (setup_data->additional_tls_setup_call_back) {
1209  /* Additional application setup wanted */
1210  if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
1211  return 0;
1212  }
1213  return 0;
1214 }
1215 
1216 /*
1217  * During the SSL/TLS initial negotiations, tls_server_name_call_back() is called
1218  * so it is possible to set up an extra callback to determine whether this is
1219  * a PKI or PSK incoming request and adjust the Ciphers if necessary
1220  *
1221  * Set up by SSL_CTX_set_tlsext_servername_callback() in coap_dtls_context_set_pki()
1222  */
1223 static int
1224 tls_server_name_call_back(SSL *ssl,
1225  int *sd UNUSED,
1226  void *arg
1227 ) {
1228  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t*)arg;
1229 
1230  if (!ssl) {
1231  return SSL_TLSEXT_ERR_NOACK;
1232  }
1233 
1234  if (setup_data->validate_sni_call_back) {
1235  /* SNI checking requested */
1236  coap_session_t *session = (coap_session_t*)SSL_get_app_data(ssl);
1237  coap_openssl_context_t *context =
1238  ((coap_openssl_context_t *)session->context->dtls_context);
1239  const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
1240  size_t i;
1241 
1242  if (!sni || !sni[0]) {
1243  sni = "";
1244  }
1245  for (i = 0; i < context->sni_count; i++) {
1246  if (!strcmp(sni, context->sni_entry_list[i].sni)) {
1247  break;
1248  }
1249  }
1250  if (i == context->sni_count) {
1251  SSL_CTX *ctx;
1252  coap_dtls_pki_t sni_setup_data;
1253  coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni,
1254  setup_data->sni_call_back_arg);
1255  if (!new_entry) {
1256  return SSL_TLSEXT_ERR_ALERT_FATAL;
1257  }
1258  /* Need to set up a new SSL_CTX to switch to */
1259  if (session->proto == COAP_PROTO_DTLS) {
1260  /* Set up DTLS context */
1261  ctx = SSL_CTX_new(DTLS_method());
1262  if (!ctx)
1263  goto error;
1264  SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
1265  SSL_CTX_set_app_data(ctx, &context->dtls);
1266  SSL_CTX_set_read_ahead(ctx, 1);
1267  SSL_CTX_set_cipher_list(ctx, "TLSv1.2:TLSv1.0");
1268  SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
1269  SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
1270  SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
1271  SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
1272  }
1273  else {
1274  /* Set up TLS context */
1275  ctx = SSL_CTX_new(TLS_method());
1276  if (!ctx)
1277  goto error;
1278  SSL_CTX_set_app_data(ctx, &context->tls);
1279  SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1280  SSL_CTX_set_cipher_list(ctx, "TLSv1.2:TLSv1.0");
1281  SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
1282  SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
1283  }
1284  memset(&sni_setup_data, 0, sizeof(sni_setup_data));
1285  sni_setup_data.pki_key.key_type = new_entry->key_type;
1286  sni_setup_data.pki_key.key.pem = new_entry->key.pem;
1287  sni_setup_data.pki_key.key.asn1 = new_entry->key.asn1;
1288  setup_pki_server(ctx, &sni_setup_data);
1289 
1290  context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
1291  (context->sni_count+1)*sizeof(sni_entry));
1292  context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
1293  context->sni_entry_list[context->sni_count].ctx = ctx;
1294  context->sni_count++;
1295  }
1296  SSL_set_SSL_CTX (ssl, context->sni_entry_list[i].ctx);
1297  SSL_clear_options (ssl, 0xFFFFFFFFL);
1298  SSL_set_options (ssl, SSL_CTX_get_options (context->sni_entry_list[i].ctx));
1299  }
1300 
1301  /*
1302  * Have to do extra call back next to get client algorithms
1303  * SSL_get_client_ciphers() does not work this early on
1304  */
1305  SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
1306  return SSL_TLSEXT_ERR_OK;
1307 
1308 error:
1309  return SSL_TLSEXT_ERR_ALERT_WARNING;
1310 }
1311 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1312 /*
1313  * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
1314  * called early in the Client Hello processing so it is possible to determine
1315  * whether this is a PKI or PSK incoming request and adjust the Ciphers if
1316  * necessary.
1317  *
1318  * Set up by SSL_CTX_set_client_hello_cb().
1319  */
1320 static int
1321 tls_client_hello_call_back(SSL *ssl,
1322  int *al,
1323  void *arg UNUSED
1324 ) {
1325  coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
1326  coap_openssl_context_t *dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
1327  coap_dtls_pki_t *setup_data = &dtls_context->setup_data;
1328  int psk_requested = 0;
1329  const unsigned char *out;
1330  size_t outlen;
1331 
1332  if (!ssl) {
1333  *al = SSL_AD_INTERNAL_ERROR;
1334  return SSL_CLIENT_HELLO_ERROR;
1335  }
1336 
1337  /*
1338  * See if PSK being requested
1339  */
1340  if (session && session->context->psk_key && session->context->psk_key_len) {
1341  int len = SSL_client_hello_get0_ciphers(ssl, &out);
1342  STACK_OF(SSL_CIPHER) *peer_ciphers = NULL;
1343  STACK_OF(SSL_CIPHER) *scsvc = NULL;
1344 
1345  if (len && SSL_bytes_to_cipher_list(ssl, out, len,
1346  SSL_client_hello_isv2(ssl),
1347  &peer_ciphers, &scsvc)) {
1348  int ii;
1349  for (ii = 0; ii < sk_SSL_CIPHER_num (peer_ciphers); ii++) {
1350  const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
1351 
1352  if (strstr (SSL_CIPHER_get_name (peer_cipher), "PSK")) {
1353  psk_requested = 1;
1354  break;
1355  }
1356  }
1357  }
1358  sk_SSL_CIPHER_free(peer_ciphers);
1359  sk_SSL_CIPHER_free(scsvc);
1360  }
1361 
1362  if (psk_requested) {
1363  /*
1364  * Client has requested PSK and it is supported
1365  */
1366  if (session) {
1367  coap_log(LOG_DEBUG, " %s: PSK request\n",
1368  coap_session_str(session));
1369  }
1370  else {
1371  coap_log(LOG_DEBUG, "PSK request\n");
1372  }
1373  SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1374  if (setup_data->additional_tls_setup_call_back) {
1375  /* Additional application setup wanted */
1376  if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
1377  return 0;
1378  }
1379  return SSL_CLIENT_HELLO_SUCCESS;
1380  }
1381 
1382  /*
1383  * Handle Certificate requests
1384  */
1385 
1386  /*
1387  * Determine what type of certificate is being requested
1388  */
1389  if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
1390  &out, &outlen)) {
1391  size_t ii;
1392  for (ii = 0; ii < outlen; ii++) {
1393  switch (out[ii]) {
1394  case 0:
1395  /* RFC6091 X.509 */
1396  if (outlen >= 2) {
1397  /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
1398  goto is_x509;
1399  }
1400  break;
1401  case 2:
1402  /* RFC7250 RPK - not yet supported */
1403  break;
1404  default:
1405  break;
1406  }
1407  }
1408  *al = SSL_AD_UNSUPPORTED_EXTENSION;
1409  return SSL_CLIENT_HELLO_ERROR;
1410  }
1411 
1412 is_x509:
1413  if (setup_data->validate_sni_call_back) {
1414  /*
1415  * SNI checking requested
1416  */
1417  coap_dtls_pki_t sni_setup_data;
1418  coap_openssl_context_t *context =
1419  ((coap_openssl_context_t *)session->context->dtls_context);
1420  const char *sni = "";
1421  char *sni_tmp = NULL;
1422  size_t i;
1423 
1424  if (SSL_client_hello_get0_ext (ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
1425  outlen > 5 &&
1426  (((out[0]<<8) + out[1] +2) == (int)outlen) &&
1427  out[2] == TLSEXT_NAMETYPE_host_name &&
1428  (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
1429  /* Skip over length, type and length */
1430  out += 5;
1431  outlen -= 5;
1432  sni_tmp = OPENSSL_malloc(outlen+1);
1433  sni_tmp[outlen] = '\000';
1434  memcpy(sni_tmp, out, outlen);
1435  sni = sni_tmp;
1436  }
1437  /* Is this a cached entry? */
1438  for (i = 0; i < context->sni_count; i++) {
1439  if (!strcmp(sni, context->sni_entry_list[i].sni)) {
1440  break;
1441  }
1442  }
1443  if (i == context->sni_count) {
1444  /*
1445  * New SNI request
1446  */
1447  coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni,
1448  setup_data->sni_call_back_arg);
1449  if (!new_entry) {
1450  *al = SSL_AD_UNRECOGNIZED_NAME;
1451  return SSL_CLIENT_HELLO_ERROR;
1452  }
1453 
1454 
1455  context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
1456  (context->sni_count+1)*sizeof(sni_entry));
1457  context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
1458  context->sni_entry_list[context->sni_count].pki_key = *new_entry;
1459  context->sni_count++;
1460  }
1461  if (sni_tmp) {
1462  OPENSSL_free(sni_tmp);
1463  }
1464  memset(&sni_setup_data, 0, sizeof(sni_setup_data));
1465  sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
1466  setup_pki_ssl(ssl, &sni_setup_data, 1);
1467  }
1468  else {
1469  setup_pki_ssl(ssl, setup_data, 1);
1470  }
1471 
1472  if (session) {
1473  coap_log(LOG_DEBUG, " %s: Using PKI ciphers\n",
1474  coap_session_str(session));
1475  }
1476  else {
1477  coap_log(LOG_DEBUG, "Using PKI ciphers\n");
1478  }
1479  if (setup_data->verify_peer_cert) {
1480  if (setup_data->require_peer_cert) {
1481  SSL_set_verify(ssl,
1482  SSL_VERIFY_PEER |
1483  SSL_VERIFY_CLIENT_ONCE |
1484  SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1485  tls_verify_call_back);
1486  }
1487  else {
1488  SSL_set_verify(ssl,
1489  SSL_VERIFY_PEER |
1490  SSL_VERIFY_CLIENT_ONCE,
1491  tls_verify_call_back);
1492  }
1493  }
1494  else {
1495  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1496  }
1497 
1498  /* Check CA Chain */
1499  if (setup_data->cert_chain_validation)
1500  SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth);
1501 
1502  /* Certificate Revocation */
1503  if (setup_data->check_cert_revocation) {
1504  X509_VERIFY_PARAM *param;
1505 
1506  param = X509_VERIFY_PARAM_new();
1507  X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
1508  SSL_set1_param(ssl, param);
1509  X509_VERIFY_PARAM_free(param);
1510  }
1511  if (setup_data->additional_tls_setup_call_back) {
1512  /* Additional application setup wanted */
1513  if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
1514  return 0;
1515  }
1516  return SSL_CLIENT_HELLO_SUCCESS;
1517 }
1518 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1519 
1520 int
1522  coap_dtls_pki_t *setup_data,
1523  coap_dtls_role_t role
1524 ) {
1525  coap_openssl_context_t *context =
1526  ((coap_openssl_context_t *)ctx->dtls_context);
1527  BIO *bio;
1528  if (!setup_data)
1529  return 0;
1530  context->setup_data = *setup_data;
1531  if (role == COAP_DTLS_ROLE_SERVER) {
1532  if (context->dtls.ctx) {
1533  /* SERVER DTLS */
1534 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1535  if (!setup_pki_server(context->dtls.ctx, setup_data))
1536  return 0;
1537 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1538  /* libcoap is managing TLS connection based on setup_data options */
1539  /* Need to set up logic to differentiate between a PSK or PKI session */
1540  /*
1541  * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
1542  * which is not in 1.1.0
1543  */
1544 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1545  if (SSLeay() >= 0x10101000L) {
1547  "OpenSSL compiled with %lux, linked with %lux, so "
1548  "no certificate checking\n",
1549  OPENSSL_VERSION_NUMBER, SSLeay());
1550  }
1551  SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
1552  SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
1553  tls_server_name_call_back);
1554 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1555  SSL_CTX_set_client_hello_cb(context->dtls.ctx,
1556  tls_client_hello_call_back,
1557  NULL);
1558 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1559  }
1560  if (context->tls.ctx) {
1561  /* SERVER TLS */
1562 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1563  if (!setup_pki_server(context->tls.ctx, setup_data))
1564  return 0;
1565 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1566  /* libcoap is managing TLS connection based on setup_data options */
1567  /* Need to set up logic to differentiate between a PSK or PKI session */
1568  /*
1569  * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
1570  * which is not in 1.1.0
1571  */
1572 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1573  if (SSLeay() >= 0x10101000L) {
1575  "OpenSSL compiled with %lux, linked with %lux, so "
1576  "no certificate checking\n",
1577  OPENSSL_VERSION_NUMBER, SSLeay());
1578  }
1579  SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
1580  SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
1581  tls_server_name_call_back);
1582 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1583  SSL_CTX_set_client_hello_cb(context->tls.ctx,
1584  tls_client_hello_call_back,
1585  NULL);
1586 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1587  /* TLS Only */
1588  SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
1589  }
1590  }
1591 
1592  if (!context->dtls.ssl) {
1593  /* This is set up to handle new incoming sessions to a server */
1594  context->dtls.ssl = SSL_new(context->dtls.ctx);
1595  if (!context->dtls.ssl)
1596  return 0;
1597  bio = BIO_new(context->dtls.meth);
1598  if (!bio) {
1599  SSL_free (context->dtls.ssl);
1600  context->dtls.ssl = NULL;
1601  return 0;
1602  }
1603  SSL_set_bio(context->dtls.ssl, bio, bio);
1604  SSL_set_app_data(context->dtls.ssl, NULL);
1605  SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1606  SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
1607  }
1608  context->psk_pki_enabled |= IS_PKI;
1609  return 1;
1610 }
1611 
1612 int
1614  const char *ca_file,
1615  const char *ca_dir
1616 ) {
1617  coap_openssl_context_t *context =
1618  ((coap_openssl_context_t *)ctx->dtls_context);
1619  if (context->dtls.ctx) {
1620  if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
1621  coap_log(LOG_WARNING, "Unable to install root CAs (%s/%s)\n",
1622  ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
1623  return 0;
1624  }
1625  }
1626  if (context->tls.ctx) {
1627  if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
1628  coap_log(LOG_WARNING, "Unable to install root CAs (%s/%s)\n",
1629  ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
1630  return 0;
1631  }
1632  }
1633  return 1;
1634 }
1635 
1636 int
1638 {
1639  coap_openssl_context_t *context =
1640  ((coap_openssl_context_t *)ctx->dtls_context);
1641  return context->psk_pki_enabled ? 1 : 0;
1642 }
1643 
1644 
1645 void coap_dtls_free_context(void *handle) {
1646  size_t i;
1647  coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
1648 
1649  if (context->dtls.ssl)
1650  SSL_free(context->dtls.ssl);
1651  if (context->dtls.ctx)
1652  SSL_CTX_free(context->dtls.ctx);
1653  if (context->dtls.cookie_hmac)
1654  HMAC_CTX_free(context->dtls.cookie_hmac);
1655  if (context->dtls.meth)
1656  BIO_meth_free(context->dtls.meth);
1657  if (context->dtls.bio_addr)
1658  BIO_ADDR_free(context->dtls.bio_addr);
1659  if ( context->tls.ctx )
1660  SSL_CTX_free( context->tls.ctx );
1661  if ( context->tls.meth )
1662  BIO_meth_free( context->tls.meth );
1663  for (i = 0; i < context->sni_count; i++) {
1664  OPENSSL_free(context->sni_entry_list[i].sni);
1665 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1666  SSL_CTX_free(context->sni_entry_list[i].ctx);
1667 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1668  }
1669  if (context->sni_count)
1670  OPENSSL_free(context->sni_entry_list);
1671  coap_free(context);
1672 }
1673 
1675  BIO *nbio = NULL;
1676  SSL *nssl = NULL, *ssl = NULL;
1677  coap_ssl_data *data;
1678  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
1679  int r;
1680 
1681  nssl = SSL_new(dtls->ctx);
1682  if (!nssl)
1683  goto error;
1684  nbio = BIO_new(dtls->meth);
1685  if (!nbio)
1686  goto error;
1687  SSL_set_bio(nssl, nbio, nbio);
1688  SSL_set_app_data(nssl, NULL);
1689  SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
1690  SSL_set_mtu(nssl, session->mtu);
1691  ssl = dtls->ssl;
1692  dtls->ssl = nssl;
1693  nssl = NULL;
1694  SSL_set_app_data(ssl, session);
1695 
1696  data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
1697  data->session = session;
1698 
1699  if (session->context->get_server_hint) {
1700  char hint[128] = "";
1701  size_t hint_len = session->context->get_server_hint(session, (uint8_t*)hint, sizeof(hint) - 1);
1702  if (hint_len > 0 && hint_len < sizeof(hint)) {
1703  hint[hint_len] = 0;
1704  SSL_use_psk_identity_hint(ssl, hint);
1705  }
1706  }
1707 
1708  r = SSL_accept(ssl);
1709  if (r == -1) {
1710  int err = SSL_get_error(ssl, r);
1711  if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
1712  r = 0;
1713  }
1714 
1715  if (r == 0) {
1716  SSL_free(ssl);
1717  return NULL;
1718  }
1719 
1720  return ssl;
1721 
1722 error:
1723  if (nssl)
1724  SSL_free(nssl);
1725  return NULL;
1726 }
1727 
1728 static int
1729 setup_client_ssl_session(coap_session_t *session, SSL *ssl
1730 ) {
1731  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
1732 
1733  if (context->psk_pki_enabled & IS_PSK) {
1734  SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
1735  SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1736  SSL_set_cipher_list(ssl, "PSK:!NULL");
1737  }
1738  if (context->psk_pki_enabled & IS_PKI) {
1739  coap_dtls_pki_t *setup_data = &context->setup_data;
1740  if (!setup_pki_ssl(ssl, setup_data, 0))
1741  return 0;
1742  /* libcoap is managing (D)TLS connection based on setup_data options */
1743  if (session->proto == COAP_PROTO_TLS)
1744  SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
1745 
1746  /* Issue SNI if requested */
1747  if (setup_data->client_sni &&
1748  SSL_set_tlsext_host_name (ssl, setup_data->client_sni) != 1) {
1749  coap_log(LOG_WARNING, "SSL_set_tlsext_host_name: set '%s' failed",
1750  setup_data->client_sni);
1751  }
1752  /* Certificate Revocation */
1753  if (setup_data->check_cert_revocation) {
1754  X509_VERIFY_PARAM *param;
1755 
1756  param = X509_VERIFY_PARAM_new();
1757  X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
1758  SSL_set1_param(ssl, param);
1759  X509_VERIFY_PARAM_free(param);
1760  }
1761 
1762  /* Verify Peer */
1763  if (setup_data->verify_peer_cert)
1764  SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_call_back);
1765  else
1766  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1767 
1768  /* Check CA Chain */
1769  if (setup_data->cert_chain_validation)
1770  SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth);
1771 
1772  }
1773  return 1;
1774 }
1775 
1777  BIO *bio = NULL;
1778  SSL *ssl = NULL;
1779  coap_ssl_data *data;
1780  int r;
1781  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
1782  coap_dtls_context_t *dtls = &context->dtls;
1783 
1784  ssl = SSL_new(dtls->ctx);
1785  if (!ssl)
1786  goto error;
1787  bio = BIO_new(dtls->meth);
1788  if (!bio)
1789  goto error;
1790  data = (coap_ssl_data *)BIO_get_data(bio);
1791  data->session = session;
1792  SSL_set_bio(ssl, bio, bio);
1793  SSL_set_app_data(ssl, session);
1794  SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
1795  SSL_set_mtu(ssl, session->mtu);
1796 
1797  if (!setup_client_ssl_session(session, ssl))
1798  goto error;
1799 
1800  session->dtls_timeout_count = 0;
1801 
1802  r = SSL_connect(ssl);
1803  if (r == -1) {
1804  int ret = SSL_get_error(ssl, r);
1805  if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
1806  r = 0;
1807  }
1808 
1809  if (r == 0)
1810  goto error;
1811 
1812  return ssl;
1813 
1814 error:
1815  if (ssl)
1816  SSL_free(ssl);
1817  return NULL;
1818 }
1819 
1821  SSL *ssl = (SSL *)session->tls;
1822  if (ssl)
1823  SSL_set_mtu(ssl, session->mtu);
1824 }
1825 
1826 void coap_dtls_free_session(coap_session_t *session) {
1827  SSL *ssl = (SSL *)session->tls;
1828  if (ssl) {
1829  if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
1830  int r = SSL_shutdown(ssl);
1831  if (r == 0) r = SSL_shutdown(ssl);
1832  }
1833  SSL_free(ssl);
1834  session->tls = NULL;
1835  }
1836 }
1837 
1838 int coap_dtls_send(coap_session_t *session,
1839  const uint8_t *data, size_t data_len) {
1840  int r;
1841  SSL *ssl = (SSL *)session->tls;
1842 
1843  assert(ssl != NULL);
1844 
1845  session->dtls_event = -1;
1846  r = SSL_write(ssl, data, (int)data_len);
1847 
1848  if (r <= 0) {
1849  int err = SSL_get_error(ssl, r);
1850  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1851  r = 0;
1852  } else {
1853  coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n");
1854  if (err == SSL_ERROR_ZERO_RETURN)
1856  else if (err == SSL_ERROR_SSL)
1857  session->dtls_event = COAP_EVENT_DTLS_ERROR;
1858  r = -1;
1859  }
1860  }
1861 
1862  if (session->dtls_event >= 0) {
1863  coap_handle_event(session->context, session->dtls_event, session);
1864  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1865  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1867  r = -1;
1868  }
1869  }
1870 
1871  return r;
1872 }
1873 
1874 int coap_dtls_is_context_timeout(void) {
1875  return 0;
1876 }
1877 
1878 coap_tick_t coap_dtls_get_context_timeout(void *dtls_context) {
1879  (void)dtls_context;
1880  return 0;
1881 }
1882 
1884  SSL *ssl = (SSL *)session->tls;
1885  coap_ssl_data *ssl_data;
1886 
1887  assert(ssl != NULL);
1888  ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
1889  return ssl_data->timeout;
1890 }
1891 
1893  SSL *ssl = (SSL *)session->tls;
1894 
1895  assert(ssl != NULL);
1896  if (((session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1897  (++session->dtls_timeout_count > session->max_retransmit)) ||
1898  (DTLSv1_handle_timeout(ssl) < 0)) {
1899  /* Too many retries */
1901  }
1902 }
1903 
1904 int coap_dtls_hello(coap_session_t *session,
1905  const uint8_t *data, size_t data_len) {
1906  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
1907  coap_ssl_data *ssl_data;
1908  int r;
1909 
1910  SSL_set_mtu(dtls->ssl, session->mtu);
1911  ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(dtls->ssl));
1912  ssl_data->session = session;
1913  ssl_data->pdu = data;
1914  ssl_data->pdu_len = (unsigned)data_len;
1915  r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
1916  if (r <= 0) {
1917  int err = SSL_get_error(dtls->ssl, r);
1918  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1919  /* Got a ClientHello, sent-out a VerifyRequest */
1920  r = 0;
1921  }
1922  } else {
1923  /* Got a valid answer to a VerifyRequest */
1924  r = 1;
1925  }
1926 
1927  return r;
1928 }
1929 
1930 int coap_dtls_receive(coap_session_t *session,
1931  const uint8_t *data, size_t data_len) {
1932  coap_ssl_data *ssl_data;
1933  SSL *ssl = (SSL *)session->tls;
1934  int r;
1935 
1936  assert(ssl != NULL);
1937 
1938  int in_init = SSL_in_init(ssl);
1940  ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
1941  ssl_data->pdu = data;
1942  ssl_data->pdu_len = (unsigned)data_len;
1943 
1944  session->dtls_event = -1;
1945  r = SSL_read(ssl, pdu, (int)sizeof(pdu));
1946  if (r > 0) {
1947  return coap_handle_dgram(session->context, session, pdu, (size_t)r);
1948  } else {
1949  int err = SSL_get_error(ssl, r);
1950  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1951  if (in_init && SSL_is_init_finished(ssl)) {
1953  coap_session_connected(session);
1954  }
1955  r = 0;
1956  } else {
1957  if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
1959  else if (err == SSL_ERROR_SSL)
1960  session->dtls_event = COAP_EVENT_DTLS_ERROR;
1961  r = -1;
1962  }
1963  if (session->dtls_event >= 0) {
1964  coap_handle_event(session->context, session->dtls_event, session);
1965  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1966  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1968  r = -1;
1969  }
1970  }
1971  }
1972 
1973  return r;
1974 }
1975 
1976 unsigned int coap_dtls_get_overhead(coap_session_t *session) {
1977  unsigned int overhead = 37;
1978  const SSL_CIPHER *s_ciph = NULL;
1979  if (session->tls != NULL)
1980  s_ciph = SSL_get_current_cipher(session->tls);
1981  if ( s_ciph ) {
1982  unsigned int ivlen, maclen, blocksize = 1, pad = 0;
1983 
1984  const EVP_CIPHER *e_ciph;
1985  const EVP_MD *e_md;
1986  char cipher[128];
1987 
1988  e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
1989 
1990  switch (EVP_CIPHER_mode(e_ciph)) {
1991  case EVP_CIPH_GCM_MODE:
1992  ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
1993  maclen = EVP_GCM_TLS_TAG_LEN;
1994  break;
1995 
1996  case EVP_CIPH_CCM_MODE:
1997  ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
1998  SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
1999  if (strstr(cipher, "CCM8"))
2000  maclen = 8;
2001  else
2002  maclen = 16;
2003  break;
2004 
2005  case EVP_CIPH_CBC_MODE:
2006  e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
2007  blocksize = EVP_CIPHER_block_size(e_ciph);
2008  ivlen = EVP_CIPHER_iv_length(e_ciph);
2009  pad = 1;
2010  maclen = EVP_MD_size(e_md);
2011  break;
2012 
2013  case EVP_CIPH_STREAM_CIPHER:
2014  /* Seen with PSK-CHACHA20-POLY1305 */
2015  ivlen = 8;
2016  maclen = 8;
2017  break;
2018 
2019  default:
2020  SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
2021  coap_log(LOG_WARNING, "Unknown overhead for DTLS with cipher %s\n",
2022  cipher);
2023  ivlen = 8;
2024  maclen = 16;
2025  break;
2026  }
2027  overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
2028  }
2029  return overhead;
2030 }
2031 
2032 void *coap_tls_new_client_session(coap_session_t *session, int *connected) {
2033  BIO *bio = NULL;
2034  SSL *ssl = NULL;
2035  int r;
2036  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
2037  coap_tls_context_t *tls = &context->tls;
2038 
2039  *connected = 0;
2040  ssl = SSL_new(tls->ctx);
2041  if (!ssl)
2042  goto error;
2043  bio = BIO_new(tls->meth);
2044  if (!bio)
2045  goto error;
2046  BIO_set_data(bio, session);
2047  SSL_set_bio(ssl, bio, bio);
2048  SSL_set_app_data(ssl, session);
2049 
2050  if (!setup_client_ssl_session(session, ssl))
2051  return 0;
2052 
2053  r = SSL_connect(ssl);
2054  if (r == -1) {
2055  int ret = SSL_get_error(ssl, r);
2056  if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
2057  r = 0;
2058  if (ret == SSL_ERROR_WANT_READ)
2059  session->sock.flags |= COAP_SOCKET_WANT_READ;
2060  if (ret == SSL_ERROR_WANT_WRITE)
2061  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2062  }
2063 
2064  if (r == 0)
2065  goto error;
2066 
2067  *connected = SSL_is_init_finished(ssl);
2068 
2069  return ssl;
2070 
2071 error:
2072  if (ssl)
2073  SSL_free(ssl);
2074  return NULL;
2075 }
2076 
2077 void *coap_tls_new_server_session(coap_session_t *session, int *connected) {
2078  BIO *bio = NULL;
2079  SSL *ssl = NULL;
2080  coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
2081  int r;
2082 
2083  *connected = 0;
2084  ssl = SSL_new(tls->ctx);
2085  if (!ssl)
2086  goto error;
2087  bio = BIO_new(tls->meth);
2088  if (!bio)
2089  goto error;
2090  BIO_set_data(bio, session);
2091  SSL_set_bio(ssl, bio, bio);
2092  SSL_set_app_data(ssl, session);
2093 
2094  if (session->context->get_server_hint) {
2095  char hint[128] = "";
2096  size_t hint_len = session->context->get_server_hint(session, (uint8_t*)hint, sizeof(hint) - 1);
2097  if (hint_len > 0 && hint_len < sizeof(hint)) {
2098  hint[hint_len] = 0;
2099  SSL_use_psk_identity_hint(ssl, hint);
2100  }
2101  }
2102 
2103  r = SSL_accept(ssl);
2104  if (r == -1) {
2105  int err = SSL_get_error(ssl, r);
2106  if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
2107  r = 0;
2108  if (err == SSL_ERROR_WANT_READ)
2109  session->sock.flags |= COAP_SOCKET_WANT_READ;
2110  if (err == SSL_ERROR_WANT_WRITE)
2111  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2112  }
2113 
2114  if (r == 0)
2115  goto error;
2116 
2117  *connected = SSL_is_init_finished(ssl);
2118 
2119  return ssl;
2120 
2121 error:
2122  if (ssl)
2123  SSL_free(ssl);
2124  return NULL;
2125 }
2126 
2127 void coap_tls_free_session(coap_session_t *session) {
2128  SSL *ssl = (SSL *)session->tls;
2129  if (ssl) {
2130  if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
2131  int r = SSL_shutdown(ssl);
2132  if (r == 0) r = SSL_shutdown(ssl);
2133  }
2134  SSL_free(ssl);
2135  session->tls = NULL;
2136  }
2137 }
2138 
2139 ssize_t coap_tls_write(coap_session_t *session,
2140  const uint8_t *data,
2141  size_t data_len
2142 ) {
2143  SSL *ssl = (SSL *)session->tls;
2144  int r, in_init;
2145 
2146  if (ssl == NULL)
2147  return -1;
2148 
2149  in_init = !SSL_is_init_finished(ssl);
2150  session->dtls_event = -1;
2151  r = SSL_write(ssl, data, (int)data_len);
2152 
2153  if (r <= 0) {
2154  int err = SSL_get_error(ssl, r);
2155  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2156  if (in_init && SSL_is_init_finished(ssl)) {
2158  coap_session_send_csm(session);
2159  }
2160  if (err == SSL_ERROR_WANT_READ)
2161  session->sock.flags |= COAP_SOCKET_WANT_READ;
2162  if (err == SSL_ERROR_WANT_WRITE)
2163  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2164  r = 0;
2165  } else {
2166  coap_log(LOG_WARNING, "***%s: coap_tls_write: cannot send PDU\n",
2167  coap_session_str(session));
2168  if (err == SSL_ERROR_ZERO_RETURN)
2170  else if (err == SSL_ERROR_SSL)
2171  session->dtls_event = COAP_EVENT_DTLS_ERROR;
2172  r = -1;
2173  }
2174  } else if (in_init && SSL_is_init_finished(ssl)) {
2176  coap_session_send_csm(session);
2177  }
2178 
2179  if (session->dtls_event >= 0) {
2180  coap_handle_event(session->context, session->dtls_event, session);
2181  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2182  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2184  r = -1;
2185  }
2186  }
2187 
2188  return r;
2189 }
2190 
2191 ssize_t coap_tls_read(coap_session_t *session,
2192  uint8_t *data,
2193  size_t data_len
2194 ) {
2195  SSL *ssl = (SSL *)session->tls;
2196  int r, in_init;
2197 
2198  if (ssl == NULL)
2199  return -1;
2200 
2201  in_init = !SSL_is_init_finished(ssl);
2202  session->dtls_event = -1;
2203  r = SSL_read(ssl, data, (int)data_len);
2204  if (r <= 0) {
2205  int err = SSL_get_error(ssl, r);
2206  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2207  if (in_init && SSL_is_init_finished(ssl)) {
2209  coap_session_send_csm(session);
2210  }
2211  if (err == SSL_ERROR_WANT_READ)
2212  session->sock.flags |= COAP_SOCKET_WANT_READ;
2213  if (err == SSL_ERROR_WANT_WRITE)
2214  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2215  r = 0;
2216  } else {
2217  if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
2219  else if (err == SSL_ERROR_SSL)
2220  session->dtls_event = COAP_EVENT_DTLS_ERROR;
2221  r = -1;
2222  }
2223  } else if (in_init && SSL_is_init_finished(ssl)) {
2225  coap_session_send_csm(session);
2226  }
2227 
2228  if (session->dtls_event >= 0) {
2229  coap_handle_event(session->context, session->dtls_event, session);
2230  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2231  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2233  r = -1;
2234  }
2235  }
2236 
2237  return r;
2238 }
2239 
2240 #else /* !HAVE_OPENSSL */
2241 
2242 #ifdef __clang__
2243 /* Make compilers happy that do not like empty modules. As this function is
2244  * never used, we ignore -Wunused-function at the end of compiling this file
2245  */
2246 #pragma GCC diagnostic ignored "-Wunused-function"
2247 #endif
2248 static inline void dummy(void) {
2249 }
2250 
2251 #endif /* HAVE_OPENSSL */
unsigned mtu
path or CSM mtu
Definition: coap_session.h:63
void coap_dtls_set_log_level(int level)
Sets the (D)TLS logging level to the specified level.
Definition: coap_notls.c:76
void coap_session_send_csm(coap_session_t *session)
Notify session transport has just connected and CSM exchange can now start.
Definition: coap_session.c:290
#define COAP_SOCKET_EMPTY
coap_socket_flags_t values
Definition: coap_io.h:54
int coap_dtls_hello(coap_session_t *session UNUSED, const uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:140
#define COAP_RXBUFFER_SIZE
Definition: coap_io.h:19
#define COAP_DEFAULT_MTU
Definition: pdu.h:32
uint8_t allow_self_signed
1 if self signed certs are allowed
Definition: coap_dtls.h:197
static void dummy(void)
void coap_tls_free_session(coap_session_t *coap_session UNUSED)
Definition: coap_notls.c:159
struct coap_context_t * context
session's context
Definition: coap_session.h:70
The PKI key type is ASN.1 (DER)
Definition: coap_dtls.h:133
void * tls
security parameters
Definition: coap_session.h:71
coap_pki_key_t key_type
key format type
Definition: coap_dtls.h:162
#define COAP_SESSION_STATE_HANDSHAKE
Definition: coap_session.h:52
int coap_dtls_receive(coap_session_t *session UNUSED, const uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:132
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx UNUSED)
Definition: coap_notls.c:65
#define COAP_EVENT_DTLS_RENEGOTIATE
Definition: coap_event.h:35
size_t psk_key_len
Definition: net.h:211
ssize_t coap_tls_read(coap_session_t *session UNUSED, uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:169
int coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition: coap_notls.c:81
#define COAP_TLS_LIBRARY_OPENSSL
Using OpenSSL library.
Definition: coap_dtls.h:40
#define COAP_PROTO_DTLS
Definition: pdu.h:345
void * coap_dtls_new_client_session(coap_session_t *session UNUSED)
Definition: coap_notls.c:98
Internal function invoked for server.
Definition: coap_dtls.h:266
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_notls.c:23
void coap_dtls_free_context(void *handle UNUSED)
Definition: coap_notls.c:91
int coap_dtls_context_set_pki(coap_context_t *ctx UNUSED, coap_dtls_pki_t *setup_data UNUSED, coap_dtls_role_t role UNUSED)
Definition: coap_notls.c:41
void * coap_tls_new_server_session(coap_session_t *session UNUSED, int *connected UNUSED)
Definition: coap_notls.c:155
ssize_t coap_tls_write(coap_session_t *session UNUSED, const uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:162
void * sni_call_back_arg
Passed in to the sni call-back function.
Definition: coap_dtls.h:227
ssize_t coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len)
Definition: coap_io.c:665
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:218
int dtls_event
Tracking any (D)TLS events on this sesison.
Definition: coap_session.h:93
uint8_t verify_peer_cert
Set to 1 to support this version of the struct.
Definition: coap_dtls.h:195
Debug.
Definition: coap_debug.h:49
uint8_t allow_no_crl
1 ignore if CRL not there
Definition: coap_dtls.h:202
uint64_t version
(D)TLS runtime Library Version
Definition: coap_dtls.h:48
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)
Definition: net.h:203
coap_dtls_sni_callback_t validate_sni_call_back
SNI check call-back function.
Definition: coap_dtls.h:226
void * coap_tls_new_client_session(coap_session_t *session UNUSED, int *connected UNUSED)
Definition: coap_notls.c:151
const char * coap_session_str(const coap_session_t *session)
Get session description.
Definition: coap_session.c:943
unsigned int max_retransmit
maximum re-transmit count (default 4)
Definition: coap_session.h:89
COAP_STATIC_INLINE void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
Definition: mem.h:75
coap_dtls_security_setup_t additional_tls_setup_call_back
Additional Security call-back handler that is invoked when libcoap has done the standerd,...
Definition: coap_dtls.h:234
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition: coap_notls.c:28
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:33
const char * private_key
File location of Private Key in PEM format.
Definition: coap_dtls.h:142
int type
Library type.
Definition: coap_dtls.h:49
uint8_t require_peer_cert
1 if peer cert is required
Definition: coap_dtls.h:196
coap_proto_t proto
protocol used
Definition: coap_session.h:58
coap_dtls_key_t pki_key
PKI key definition.
Definition: coap_dtls.h:240
coap_pki_key_pem_t pem
for PEM keys
Definition: coap_dtls.h:164
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition: coap_dtls.h:236
Warning.
Definition: coap_debug.h:46
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:85
#define assert(...)
Definition: mem.c:18
The structure that holds the PKI key information.
Definition: coap_dtls.h:161
unsigned int coap_dtls_get_overhead(coap_session_t *session UNUSED)
Definition: coap_notls.c:147
const uint8_t * public_cert
ASN1 (DER) Public Cert.
Definition: coap_dtls.h:150
const char * ca_file
File location of Common CA in PEM format.
Definition: coap_dtls.h:140
size_t ca_cert_len
ASN1 CA Cert length.
Definition: coap_dtls.h:152
The PKI key type is PEM.
Definition: coap_dtls.h:132
coap_socket_t sock
socket object for the session, if any
Definition: coap_session.h:68
ssize_t coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len)
Definition: coap_io.c:635
static int dtls_log_level
Definition: coap_notls.c:70
The structure used for returning the underlying (D)TLS library information.
Definition: coap_dtls.h:47
#define COAP_EVENT_DTLS_CLOSED
(D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
Definition: coap_event.h:33
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:1369
int coap_dtls_context_set_psk(coap_context_t *ctx UNUSED, const char *hint UNUSED, coap_dtls_role_t role UNUSED)
Definition: coap_notls.c:57
#define COAP_PROTO_TLS
Definition: pdu.h:347
uint8_t cert_chain_validation
1 if to check cert_chain_verify_depth
Definition: coap_dtls.h:199
COAP_STATIC_INLINE void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:82
Error.
Definition: coap_debug.h:45
void * dtls_context
Definition: net.h:207
union coap_dtls_key_t::@1 key
coap_session_state_t state
current state of relationaship with peer
Definition: coap_session.h:60
const uint8_t * private_key
ASN1 (DER) Private Key.
Definition: coap_dtls.h:151
coap_dtls_cn_callback_t validate_cn_call_back
CN check call-back function.
Definition: coap_dtls.h:218
uint8_t allow_expired_certs
1 if expired certs are allowed
Definition: coap_dtls.h:198
uint8_t check_cert_revocation
1 if revocation checks wanted
Definition: coap_dtls.h:201
coap_dtls_role_t
Definition: coap_dtls.h:264
size_t(* get_server_hint)(const coap_session_t *session, uint8_t *hint, size_t max_hint_len)
Definition: net.h:205
void coap_dtls_free_session(coap_session_t *coap_session UNUSED)
Definition: coap_notls.c:102
#define COAP_EVENT_DTLS_ERROR
Definition: coap_event.h:36
#define COAP_EVENT_DTLS_CONNECTED
Definition: coap_event.h:34
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:2310
void * cn_call_back_arg
Passed in to the CN call-back function.
Definition: coap_dtls.h:219
void * coap_dtls_new_server_session(coap_session_t *session UNUSED)
Definition: coap_notls.c:94
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
Definition: coap_session.c:326
uint8_t allow_expired_crl
1 if expired crl is allowed
Definition: coap_dtls.h:203
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
Definition: coap_io.h:58
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:191
int coap_dtls_context_set_pki_root_cas(struct coap_context_t *ctx UNUSED, const char *ca_file UNUSED, const char *ca_path UNUSED)
Definition: coap_notls.c:49
coap_asn1_privatekey_type_t private_key_type
Private Key Type.
Definition: coap_dtls.h:155
int coap_dtls_send(coap_session_t *session UNUSED, const uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:109
uint8_t cert_chain_verify_depth
recommended depth is 3
Definition: coap_dtls.h:200
coap_tick_t coap_dtls_get_timeout(coap_session_t *session UNUSED)
Definition: coap_notls.c:124
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)
Definition: net.h:204
coap_tick_t coap_ticks_from_rt_us(uint64_t t)
Helper function that converts POSIX wallclock time in us to coap ticks.
void coap_dtls_handle_timeout(coap_session_t *session UNUSED)
Definition: coap_notls.c:128
const char * public_cert
File location of Public Cert in PEM format.
Definition: coap_dtls.h:141
uint8_t * psk_key
Definition: net.h:210
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition: coap_notls.c:72
coap_socket_flags_t flags
Definition: coap_io.h:48
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:383
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:122
const uint8_t * ca_cert
ASN1 (DER) Common CA Cert.
Definition: coap_dtls.h:149
unsigned char uint8_t
Definition: uthash.h:79
Pseudo Random Numbers.
TLS1_PRF type.
Definition: coap_dtls.h:124
size_t public_cert_len
ASN1 Public Cert length.
Definition: coap_dtls.h:153
#define UNUSED
Definition: coap_notls.c:19
#define prng(Buf, Length)
Fills Buf with Length bytes of random data.
Definition: prng.h:112
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context UNUSED)
Definition: coap_notls.c:120
uint64_t built_version
(D)TLS Built against Library Version
Definition: coap_dtls.h:50
void coap_dtls_session_update_mtu(coap_session_t *session UNUSED)
Definition: coap_notls.c:105
Information.
Definition: coap_debug.h:48
void * coap_dtls_new_context(struct coap_context_t *coap_context UNUSED)
Definition: coap_notls.c:86
unsigned int dtls_timeout_count
dtls setup retry counter
Definition: coap_session.h:92
The CoAP stack's global state is stored in a coap_context_t object.
Definition: net.h:148
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition: coap_notls.c:116
size_t private_key_len
ASN1 Private Key length.
Definition: coap_dtls.h:154
coap_pki_key_asn1_t asn1
for ASN.1 (DER) keys
Definition: coap_dtls.h:165
#define COAP_SOCKET_WANT_WRITE
non blocking socket is waiting for writing
Definition: coap_io.h:59