libcoap  4.2.0rc4
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  int 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, int isserver
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  "Client Certificate\n",
829  setup_data->pki_key.key.pem.public_cert);
830  return 0;
831  }
832  }
833  else {
835  "*** setup_pki: (D)TLS: No Client Certificate defined\n");
836  return 0;
837  }
838  if (setup_data->pki_key.key.pem.private_key &&
839  setup_data->pki_key.key.pem.private_key[0]) {
840  if (!(SSL_use_PrivateKey_file(ssl,
841  setup_data->pki_key.key.pem.private_key,
842  SSL_FILETYPE_PEM))) {
844  "*** setup_pki: (D)TLS: %s: Unable to configure "
845  "Client Private Key\n",
846  setup_data->pki_key.key.pem.private_key);
847  return 0;
848  }
849  }
850  else {
852  "*** setup_pki: (D)TLS: No Client Private Key defined\n");
853  return 0;
854  }
855  if (setup_data->pki_key.key.pem.ca_file &&
856  setup_data->pki_key.key.pem.ca_file[0]) {
857  X509_STORE *st;
858  BIO *in;
859  X509 *x = NULL;
860  char *rw_var = NULL;
861  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
862 
863  if (isserver) {
864  STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(setup_data->pki_key.key.pem.ca_file);
865 
866  if (cert_names != NULL)
867  SSL_set_client_CA_list(ssl, cert_names);
868  else {
870  "*** setup_pki: (D)TLS: %s: Unable to configure "
871  "client CA File\n",
872  setup_data->pki_key.key.pem.ca_file);
873  return 0;
874  }
875  }
876 
877  /* Add CA to the trusted root CA store */
878  in = BIO_new(BIO_s_file());
879  /* Need to do this to not get a compiler warning about const parameters */
880  memcpy(&rw_var, &setup_data->pki_key.key.pem.ca_file, sizeof (rw_var));
881  if (!BIO_read_filename(in, rw_var)) {
882  BIO_free(in);
883  X509_free(x);
884  break;
885  }
886  st = SSL_CTX_get_cert_store(ctx);
887  for (;;) {
888  if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
889  break;
890  add_ca_to_cert_store(st, x);
891  }
892  BIO_free(in);
893  X509_free(x);
894  }
895  break;
896 
897  case COAP_PKI_KEY_ASN1:
898  if (setup_data->pki_key.key.asn1.public_cert &&
899  setup_data->pki_key.key.asn1.public_cert_len > 0) {
900  if (!(SSL_use_certificate_ASN1(ssl,
901  setup_data->pki_key.key.asn1.public_cert,
902  setup_data->pki_key.key.asn1.public_cert_len))) {
904  "*** setup_pki: (D)TLS: %s: Unable to configure "
905  "Client Certificate\n",
906  "ASN1");
907  return 0;
908  }
909  }
910  else {
912  "*** setup_pki: (D)TLS: No Client Certificate defined\n");
913  return 0;
914  }
915  if (setup_data->pki_key.key.asn1.private_key &&
916  setup_data->pki_key.key.asn1.private_key_len > 0) {
917  int pkey_type = map_key_type(setup_data->pki_key.key.asn1.private_key_type);
918  if (!(SSL_use_PrivateKey_ASN1(pkey_type, ssl,
919  setup_data->pki_key.key.asn1.private_key,
920  setup_data->pki_key.key.asn1.private_key_len))) {
922  "*** setup_pki: (D)TLS: %s: Unable to configure "
923  "Client Private Key\n",
924  "ASN1");
925  return 0;
926  }
927  }
928  else {
930  "*** setup_pki: (D)TLS: No Client Private Key defined\n");
931  return 0;
932  }
933  if (setup_data->pki_key.key.asn1.ca_cert &&
934  setup_data->pki_key.key.asn1.ca_cert_len > 0) {
935  /* Need to use a temp variable as it gets incremented*/
936  const uint8_t *p = setup_data->pki_key.key.asn1.ca_cert;
937  X509* x509 = d2i_X509(NULL, &p, setup_data->pki_key.key.asn1.ca_cert_len);
938  X509_STORE *st;
939  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
940 
941  if (isserver) {
942  if (!x509 || !SSL_add_client_CA(ssl, x509)) {
944  "*** setup_pki: (D)TLS: %s: Unable to configure "
945  "client CA File\n",
946  "ASN1");
947  X509_free(x509);
948  return 0;
949  }
950  }
951 
952  /* Add CA to the trusted root CA store */
953  st = SSL_CTX_get_cert_store(ctx);
954  add_ca_to_cert_store(st, x509);
955  X509_free(x509);
956  }
957  break;
958  default:
960  "*** setup_pki: (D)TLS: Unknown key type %d\n",
961  setup_data->pki_key.key_type);
962  return 0;
963  }
964  return 1;
965 }
966 
967 static char*
968 get_common_name_from_cert(X509* x509) {
969  if (x509) {
970  char *cn;
971  int n;
972  STACK_OF(GENERAL_NAME) *san_list;
973  char buffer[256];
974 
975  san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
976  if (san_list) {
977  int san_count = sk_GENERAL_NAME_num(san_list);
978 
979  for (n = 0; n < san_count; n++) {
980  const GENERAL_NAME * name = sk_GENERAL_NAME_value (san_list, n);
981 
982  if (name->type == GEN_DNS) {
983  const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
984 
985  /* Make sure that there is not an embedded NUL in the dns_name */
986  if (ASN1_STRING_length(name->d.dNSName) != (int)strlen (dns_name))
987  continue;
988  cn = OPENSSL_strdup(dns_name);
989  sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
990  return cn;
991  }
992  }
993  sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
994  }
995  /* Otherwise look for the CN= field */
996  X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
997 
998  /* Need to emulate strcasestr() here. Looking for CN= */
999  n = strlen(buffer) - 3;
1000  cn = buffer;
1001  while (n > 0) {
1002  if (((cn[0] == 'C') || (cn[0] == 'c')) &&
1003  ((cn[1] == 'N') || (cn[1] == 'n')) &&
1004  (cn[2] == '=')) {
1005  cn += 3;
1006  break;
1007  }
1008  cn++;
1009  n--;
1010  }
1011  if (n > 0) {
1012  char * ecn = strchr(cn, '/');
1013  if (ecn) {
1014  return OPENSSL_strndup(cn, ecn-cn);
1015  }
1016  else {
1017  return OPENSSL_strdup(cn);
1018  }
1019  }
1020  }
1021  return NULL;
1022 }
1023 
1024 static int
1025 tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
1026  SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
1027  SSL_get_ex_data_X509_STORE_CTX_idx());
1028  coap_session_t *session = SSL_get_app_data(ssl);
1029  coap_openssl_context_t *context =
1030  ((coap_openssl_context_t *)session->context->dtls_context);
1031  coap_dtls_pki_t *setup_data = &context->setup_data;
1032  int depth = X509_STORE_CTX_get_error_depth(ctx);
1033  int err = X509_STORE_CTX_get_error(ctx);
1034  X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
1035  char *cn = get_common_name_from_cert(x509);
1036  int keep_preverify_ok = preverify_ok;
1037 
1038  if (!preverify_ok) {
1039  switch (err) {
1040  case X509_V_ERR_CERT_NOT_YET_VALID:
1041  case X509_V_ERR_CERT_HAS_EXPIRED:
1042  if (setup_data->allow_expired_certs)
1043  preverify_ok = 1;
1044  break;
1045  case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
1046  if (setup_data->allow_self_signed)
1047  preverify_ok = 1;
1048  break;
1049  case X509_V_ERR_UNABLE_TO_GET_CRL:
1050  if (setup_data->allow_no_crl)
1051  preverify_ok = 1;
1052  break;
1053  case X509_V_ERR_CRL_NOT_YET_VALID:
1054  case X509_V_ERR_CRL_HAS_EXPIRED:
1055  if (setup_data->allow_expired_crl)
1056  preverify_ok = 1;
1057  break;
1058  default:
1059  break;
1060  }
1061  if (!preverify_ok) {
1063  " %s: %s: '%s' depth=%d\n",
1064  coap_session_str(session),
1065  X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1066  /* Invoke the CN callback function for this failure */
1067  keep_preverify_ok = 1;
1068  }
1069  else {
1071  " %s: %s: overridden: '%s' depth=%d\n",
1072  coap_session_str(session),
1073  X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1074  }
1075  }
1076  /* Certificate - depth == 0 is the Client Cert */
1077  if (setup_data->validate_cn_call_back && keep_preverify_ok) {
1078  int length = i2d_X509(x509, NULL);
1079  uint8_t *base_buf;
1080  uint8_t *base_buf2 = base_buf = OPENSSL_malloc(length);
1081 
1082  /* base_buf2 gets moved to the end */
1083  i2d_X509(x509, &base_buf2);
1084  if (!setup_data->validate_cn_call_back(cn, base_buf, length, session,
1085  depth, preverify_ok,
1086  setup_data->cn_call_back_arg)) {
1087  if (depth == 0) {
1088  X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
1089  }
1090  else {
1091  X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
1092  }
1093  preverify_ok = 0;
1094  }
1095  OPENSSL_free(base_buf);
1096  }
1097  OPENSSL_free(cn);
1098  return preverify_ok;
1099 }
1100 
1101 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1102 /*
1103  * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
1104  * it is possible to determine whether this is a PKI or PSK incoming
1105  * request and adjust the Ciphers if necessary
1106  *
1107  * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
1108  */
1109 static int
1110 tls_secret_call_back(SSL *ssl,
1111  void *secret UNUSED,
1112  int *secretlen UNUSED,
1113  STACK_OF(SSL_CIPHER) *peer_ciphers,
1114  const SSL_CIPHER **cipher UNUSED,
1115  void *arg
1116 ) {
1117  int ii;
1118  int psk_requested = 0;
1119  coap_session_t *session = SSL_get_app_data(ssl);
1120  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t*)arg;
1121 
1122  if (session && session->context->psk_key && session->context->psk_key_len) {
1123  /* Is PSK being requested - if so, we need to change algorithms */
1124  for (ii = 0; ii < sk_SSL_CIPHER_num (peer_ciphers); ii++) {
1125  const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
1126 
1127  if (strstr (SSL_CIPHER_get_name (peer_cipher), "PSK")) {
1128  psk_requested = 1;
1129  break;
1130  }
1131  }
1132  }
1133  if (!psk_requested) {
1134  if (session) {
1135  coap_log(LOG_DEBUG, " %s: Using PKI ciphers\n",
1136  coap_session_str(session));
1137  }
1138  else {
1139  coap_log(LOG_DEBUG, "Using PKI ciphers\n");
1140  }
1141  if (setup_data->verify_peer_cert) {
1142  if (setup_data->require_peer_cert) {
1143  SSL_set_verify(ssl,
1144  SSL_VERIFY_PEER |
1145  SSL_VERIFY_CLIENT_ONCE |
1146  SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1147  tls_verify_call_back);
1148  }
1149  else {
1150  SSL_set_verify(ssl,
1151  SSL_VERIFY_PEER |
1152  SSL_VERIFY_CLIENT_ONCE,
1153  tls_verify_call_back);
1154  }
1155  }
1156  else {
1157  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1158  }
1159 
1160  /* Check CA Chain */
1161  if (setup_data->cert_chain_validation)
1162  SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth);
1163 
1164  /* Certificate Revocation */
1165  if (setup_data->check_cert_revocation) {
1166  X509_VERIFY_PARAM *param;
1167 
1168  param = X509_VERIFY_PARAM_new();
1169  X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
1170  SSL_set1_param(ssl, param);
1171  X509_VERIFY_PARAM_free(param);
1172  }
1173  }
1174  else {
1175  if (session) {
1176  if (session->context->psk_key && session->context->psk_key_len) {
1177  memcpy(secret, session->context->psk_key, session->context->psk_key_len);
1178  *secretlen = session->context->psk_key_len;
1179  }
1180  coap_log(LOG_DEBUG, " %s: Setting PSK ciphers\n",
1181  coap_session_str(session));
1182  }
1183  else {
1184  coap_log(LOG_DEBUG, "Setting PSK ciphers\n");
1185  }
1186  /*
1187  * Force a PSK algorithm to be used, so we do PSK
1188  */
1189  SSL_set_cipher_list (ssl, "PSK:!NULL");
1190  SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1191  }
1192  if (setup_data->additional_tls_setup_call_back) {
1193  /* Additional application setup wanted */
1194  if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
1195  return 0;
1196  }
1197  return 0;
1198 }
1199 
1200 /*
1201  * During the SSL/TLS initial negotiations, tls_server_name_call_back() is called
1202  * so it is possible to set up an extra callback to determine whether this is
1203  * a PKI or PSK incoming request and adjust the Ciphers if necessary
1204  *
1205  * Set up by SSL_CTX_set_tlsext_servername_callback() in coap_dtls_context_set_pki()
1206  */
1207 static int
1208 tls_server_name_call_back(SSL *ssl,
1209  int *sd UNUSED,
1210  void *arg
1211 ) {
1212  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t*)arg;
1213 
1214  if (!ssl) {
1215  return SSL_TLSEXT_ERR_NOACK;
1216  }
1217 
1218  if (setup_data->validate_sni_call_back) {
1219  /* SNI checking requested */
1220  coap_session_t *session = (coap_session_t*)SSL_get_app_data(ssl);
1221  coap_openssl_context_t *context =
1222  ((coap_openssl_context_t *)session->context->dtls_context);
1223  const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
1224  size_t i;
1225 
1226  if (!sni || !sni[0]) {
1227  sni = "";
1228  }
1229  for (i = 0; i < context->sni_count; i++) {
1230  if (!strcmp(sni, context->sni_entry_list[i].sni)) {
1231  break;
1232  }
1233  }
1234  if (i == context->sni_count) {
1235  SSL_CTX *ctx;
1236  coap_dtls_pki_t sni_setup_data;
1237  coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni,
1238  setup_data->sni_call_back_arg);
1239  if (!new_entry) {
1240  return SSL_TLSEXT_ERR_ALERT_FATAL;
1241  }
1242  /* Need to set up a new SSL_CTX to switch to */
1243  if (session->proto == COAP_PROTO_DTLS) {
1244  /* Set up DTLS context */
1245  ctx = SSL_CTX_new(DTLS_method());
1246  if (!ctx)
1247  goto error;
1248  SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
1249  SSL_CTX_set_app_data(ctx, &context->dtls);
1250  SSL_CTX_set_read_ahead(ctx, 1);
1251  SSL_CTX_set_cipher_list(ctx, "TLSv1.2:TLSv1.0");
1252  SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
1253  SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
1254  SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
1255  SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
1256  }
1257  else {
1258  /* Set up TLS context */
1259  ctx = SSL_CTX_new(TLS_method());
1260  if (!ctx)
1261  goto error;
1262  SSL_CTX_set_app_data(ctx, &context->tls);
1263  SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1264  SSL_CTX_set_cipher_list(ctx, "TLSv1.2:TLSv1.0");
1265  SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
1266  SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
1267  }
1268  memset(&sni_setup_data, 0, sizeof(sni_setup_data));
1269  sni_setup_data.pki_key.key_type = new_entry->key_type;
1270  sni_setup_data.pki_key.key.pem = new_entry->key.pem;
1271  sni_setup_data.pki_key.key.asn1 = new_entry->key.asn1;
1272  setup_pki_server(ctx, &sni_setup_data);
1273 
1274  context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
1275  (context->sni_count+1)*sizeof(sni_entry));
1276  context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
1277  context->sni_entry_list[context->sni_count].ctx = ctx;
1278  context->sni_count++;
1279  }
1280  SSL_set_SSL_CTX (ssl, context->sni_entry_list[i].ctx);
1281  SSL_clear_options (ssl, 0xFFFFFFFFL);
1282  SSL_set_options (ssl, SSL_CTX_get_options (context->sni_entry_list[i].ctx));
1283  }
1284 
1285  /*
1286  * Have to do extra call back next to get client algorithms
1287  * SSL_get_client_ciphers() does not work this early on
1288  */
1289  SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
1290  return SSL_TLSEXT_ERR_OK;
1291 
1292 error:
1293  return SSL_TLSEXT_ERR_ALERT_WARNING;
1294 }
1295 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1296 /*
1297  * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
1298  * called early in the Client Hello processing so it is possible to determine
1299  * whether this is a PKI or PSK incoming request and adjust the Ciphers if
1300  * necessary.
1301  *
1302  * Set up by SSL_CTX_set_client_hello_cb().
1303  */
1304 static int
1305 tls_client_hello_call_back(SSL *ssl,
1306  int *al,
1307  void *arg UNUSED
1308 ) {
1309  coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
1310  coap_openssl_context_t *dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
1311  coap_dtls_pki_t *setup_data = &dtls_context->setup_data;
1312  int psk_requested = 0;
1313  const unsigned char *out;
1314  size_t outlen;
1315 
1316  if (!ssl) {
1317  *al = SSL_AD_INTERNAL_ERROR;
1318  return SSL_CLIENT_HELLO_ERROR;
1319  }
1320 
1321  /*
1322  * See if PSK being requested
1323  */
1324  if (session && session->context->psk_key && session->context->psk_key_len) {
1325  int len = SSL_client_hello_get0_ciphers(ssl, &out);
1326  STACK_OF(SSL_CIPHER) *peer_ciphers;
1327  STACK_OF(SSL_CIPHER) *scsvc;
1328  int ii;
1329 
1330  len = SSL_bytes_to_cipher_list(ssl, out, len,
1331  SSL_client_hello_isv2(ssl),
1332  &peer_ciphers, &scsvc);
1333  for (ii = 0; ii < sk_SSL_CIPHER_num (peer_ciphers); ii++) {
1334  const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
1335 
1336  if (strstr (SSL_CIPHER_get_name (peer_cipher), "PSK")) {
1337  psk_requested = 1;
1338  break;
1339  }
1340  }
1341  sk_SSL_CIPHER_free(peer_ciphers);
1342  sk_SSL_CIPHER_free(scsvc);
1343  }
1344 
1345  if (psk_requested) {
1346  /*
1347  * Client has requested PSK and it is supported
1348  */
1349  if (session) {
1350  coap_log(LOG_DEBUG, " %s: PSK request\n",
1351  coap_session_str(session));
1352  }
1353  else {
1354  coap_log(LOG_DEBUG, "PSK request\n");
1355  }
1356  SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1357  if (setup_data->additional_tls_setup_call_back) {
1358  /* Additional application setup wanted */
1359  if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
1360  return 0;
1361  }
1362  return SSL_CLIENT_HELLO_SUCCESS;
1363  }
1364 
1365  /*
1366  * Handle Certificate requests
1367  */
1368 
1369  /*
1370  * Determine what type of certificate is being requested
1371  */
1372  if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
1373  &out, &outlen)) {
1374  size_t ii;
1375  for (ii = 0; ii < outlen; ii++) {
1376  switch (out[ii]) {
1377  case 0:
1378  /* RFC6091 X.509 */
1379  if (outlen >= 2) {
1380  /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
1381  goto is_x509;
1382  }
1383  break;
1384  case 2:
1385  /* RFC7250 RPK - not yet supported */
1386  break;
1387  default:
1388  break;
1389  }
1390  }
1391  *al = SSL_AD_UNSUPPORTED_EXTENSION;
1392  return SSL_CLIENT_HELLO_ERROR;
1393  }
1394 
1395 is_x509:
1396  if (setup_data->validate_sni_call_back) {
1397  /*
1398  * SNI checking requested
1399  */
1400  coap_dtls_pki_t sni_setup_data;
1401  coap_openssl_context_t *context =
1402  ((coap_openssl_context_t *)session->context->dtls_context);
1403  const char *sni = "";
1404  char *sni_tmp = NULL;
1405  size_t i;
1406 
1407  if (SSL_client_hello_get0_ext (ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
1408  outlen > 5 &&
1409  (((out[0]<<8) + out[1] +2) == (int)outlen) &&
1410  out[2] == TLSEXT_NAMETYPE_host_name &&
1411  (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
1412  /* Skip over length, type and length */
1413  out += 5;
1414  outlen -= 5;
1415  sni_tmp = OPENSSL_malloc(outlen+1);
1416  sni_tmp[outlen] = '\000';
1417  memcpy(sni_tmp, out, outlen);
1418  sni = sni_tmp;
1419  }
1420  /* Is this a cached entry? */
1421  for (i = 0; i < context->sni_count; i++) {
1422  if (!strcmp(sni, context->sni_entry_list[i].sni)) {
1423  break;
1424  }
1425  }
1426  if (i == context->sni_count) {
1427  /*
1428  * New SNI request
1429  */
1430  coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni,
1431  setup_data->sni_call_back_arg);
1432  if (!new_entry) {
1433  *al = SSL_AD_UNRECOGNIZED_NAME;
1434  return SSL_CLIENT_HELLO_ERROR;
1435  }
1436 
1437 
1438  context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
1439  (context->sni_count+1)*sizeof(sni_entry));
1440  context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
1441  context->sni_entry_list[context->sni_count].pki_key = *new_entry;
1442  context->sni_count++;
1443  }
1444  if (sni_tmp) {
1445  OPENSSL_free(sni_tmp);
1446  }
1447  memset(&sni_setup_data, 0, sizeof(sni_setup_data));
1448  sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
1449  setup_pki_ssl(ssl, &sni_setup_data, 1);
1450  }
1451  else {
1452  setup_pki_ssl(ssl, setup_data, 1);
1453  }
1454 
1455  if (session) {
1456  coap_log(LOG_DEBUG, " %s: Using PKI ciphers\n",
1457  coap_session_str(session));
1458  }
1459  else {
1460  coap_log(LOG_DEBUG, "Using PKI ciphers\n");
1461  }
1462  if (setup_data->verify_peer_cert) {
1463  if (setup_data->require_peer_cert) {
1464  SSL_set_verify(ssl,
1465  SSL_VERIFY_PEER |
1466  SSL_VERIFY_CLIENT_ONCE |
1467  SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1468  tls_verify_call_back);
1469  }
1470  else {
1471  SSL_set_verify(ssl,
1472  SSL_VERIFY_PEER |
1473  SSL_VERIFY_CLIENT_ONCE,
1474  tls_verify_call_back);
1475  }
1476  }
1477  else {
1478  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1479  }
1480 
1481  /* Check CA Chain */
1482  if (setup_data->cert_chain_validation)
1483  SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth);
1484 
1485  /* Certificate Revocation */
1486  if (setup_data->check_cert_revocation) {
1487  X509_VERIFY_PARAM *param;
1488 
1489  param = X509_VERIFY_PARAM_new();
1490  X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
1491  SSL_set1_param(ssl, param);
1492  X509_VERIFY_PARAM_free(param);
1493  }
1494  if (setup_data->additional_tls_setup_call_back) {
1495  /* Additional application setup wanted */
1496  if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
1497  return 0;
1498  }
1499  return SSL_CLIENT_HELLO_SUCCESS;
1500 }
1501 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1502 
1503 int
1505  coap_dtls_pki_t *setup_data,
1506  int role
1507 ) {
1508  coap_openssl_context_t *context =
1509  ((coap_openssl_context_t *)ctx->dtls_context);
1510  BIO *bio;
1511  if (!setup_data)
1512  return 0;
1513  context->setup_data = *setup_data;
1514  if (role == COAP_DTLS_ROLE_SERVER) {
1515  if (context->dtls.ctx) {
1516  /* SERVER DTLS */
1517 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1518  if (!setup_pki_server(context->dtls.ctx, setup_data))
1519  return 0;
1520 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1521  /* libcoap is managing TLS connection based on setup_data options */
1522  /* Need to set up logic to differentiate between a PSK or PKI session */
1523  /*
1524  * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
1525  * which is not in 1.1.0
1526  */
1527 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1528  if (SSLeay() >= 0x10101000L) {
1530  "OpenSSL compiled with %lux, linked with %lux, so "
1531  "no certificate checking\n",
1532  OPENSSL_VERSION_NUMBER, SSLeay());
1533  }
1534  SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
1535  SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
1536  tls_server_name_call_back);
1537 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1538  SSL_CTX_set_client_hello_cb(context->dtls.ctx,
1539  tls_client_hello_call_back,
1540  NULL);
1541 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1542  }
1543  if (context->tls.ctx) {
1544  /* SERVER TLS */
1545 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1546  if (!setup_pki_server(context->tls.ctx, setup_data))
1547  return 0;
1548 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1549  /* libcoap is managing TLS connection based on setup_data options */
1550  /* Need to set up logic to differentiate between a PSK or PKI session */
1551  /*
1552  * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
1553  * which is not in 1.1.0
1554  */
1555 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1556  if (SSLeay() >= 0x10101000L) {
1558  "OpenSSL compiled with %lux, linked with %lux, so "
1559  "no certificate checking\n",
1560  OPENSSL_VERSION_NUMBER, SSLeay());
1561  }
1562  SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
1563  SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
1564  tls_server_name_call_back);
1565 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1566  SSL_CTX_set_client_hello_cb(context->tls.ctx,
1567  tls_client_hello_call_back,
1568  NULL);
1569 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1570  /* TLS Only */
1571  SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
1572  }
1573  }
1574 
1575  if (!context->dtls.ssl) {
1576  /* This is set up to handle new incoming sessions to a server */
1577  context->dtls.ssl = SSL_new(context->dtls.ctx);
1578  if (!context->dtls.ssl)
1579  return 0;
1580  bio = BIO_new(context->dtls.meth);
1581  if (!bio) {
1582  SSL_free (context->dtls.ssl);
1583  context->dtls.ssl = NULL;
1584  return 0;
1585  }
1586  SSL_set_bio(context->dtls.ssl, bio, bio);
1587  SSL_set_app_data(context->dtls.ssl, NULL);
1588  SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1589  SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
1590  }
1591  context->psk_pki_enabled |= IS_PKI;
1592  return 1;
1593 }
1594 
1595 int
1597  const char *ca_file,
1598  const char *ca_dir
1599 ) {
1600  coap_openssl_context_t *context =
1601  ((coap_openssl_context_t *)ctx->dtls_context);
1602  if (context->dtls.ctx) {
1603  if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
1604  coap_log(LOG_WARNING, "Unable to install root CAs (%s/%s)\n",
1605  ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
1606  return 0;
1607  }
1608  }
1609  if (context->tls.ctx) {
1610  if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
1611  coap_log(LOG_WARNING, "Unable to install root CAs (%s/%s)\n",
1612  ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
1613  return 0;
1614  }
1615  }
1616  return 1;
1617 }
1618 
1619 int
1621 {
1622  coap_openssl_context_t *context =
1623  ((coap_openssl_context_t *)ctx->dtls_context);
1624  return context->psk_pki_enabled ? 1 : 0;
1625 }
1626 
1627 
1628 void coap_dtls_free_context(void *handle) {
1629  size_t i;
1630  coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
1631 
1632  if (context->dtls.ssl)
1633  SSL_free(context->dtls.ssl);
1634  if (context->dtls.ctx)
1635  SSL_CTX_free(context->dtls.ctx);
1636  if (context->dtls.cookie_hmac)
1637  HMAC_CTX_free(context->dtls.cookie_hmac);
1638  if (context->dtls.meth)
1639  BIO_meth_free(context->dtls.meth);
1640  if (context->dtls.bio_addr)
1641  BIO_ADDR_free(context->dtls.bio_addr);
1642  if ( context->tls.ctx )
1643  SSL_CTX_free( context->tls.ctx );
1644  if ( context->tls.meth )
1645  BIO_meth_free( context->tls.meth );
1646  for (i = 0; i < context->sni_count; i++) {
1647  OPENSSL_free(context->sni_entry_list[i].sni);
1648 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1649  SSL_CTX_free(context->sni_entry_list[i].ctx);
1650 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1651  }
1652  if (context->sni_count)
1653  OPENSSL_free(context->sni_entry_list);
1654  coap_free(context);
1655 }
1656 
1658  BIO *nbio = NULL;
1659  SSL *nssl = NULL, *ssl = NULL;
1660  coap_ssl_data *data;
1661  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
1662  int r;
1663 
1664  nssl = SSL_new(dtls->ctx);
1665  if (!nssl)
1666  goto error;
1667  nbio = BIO_new(dtls->meth);
1668  if (!nbio)
1669  goto error;
1670  SSL_set_bio(nssl, nbio, nbio);
1671  SSL_set_app_data(nssl, NULL);
1672  SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
1673  SSL_set_mtu(nssl, session->mtu);
1674  ssl = dtls->ssl;
1675  dtls->ssl = nssl;
1676  nssl = NULL;
1677  SSL_set_app_data(ssl, session);
1678 
1679  data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
1680  data->session = session;
1681 
1682  if (session->context->get_server_hint) {
1683  char hint[128] = "";
1684  size_t hint_len = session->context->get_server_hint(session, (uint8_t*)hint, sizeof(hint) - 1);
1685  if (hint_len > 0 && hint_len < sizeof(hint)) {
1686  hint[hint_len] = 0;
1687  SSL_use_psk_identity_hint(ssl, hint);
1688  }
1689  }
1690 
1691  r = SSL_accept(ssl);
1692  if (r == -1) {
1693  int err = SSL_get_error(ssl, r);
1694  if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
1695  r = 0;
1696  }
1697 
1698  if (r == 0) {
1699  SSL_free(ssl);
1700  return NULL;
1701  }
1702 
1703  return ssl;
1704 
1705 error:
1706  if (nssl)
1707  SSL_free(nssl);
1708  return NULL;
1709 }
1710 
1711 static int
1712 setup_client_ssl_session(coap_session_t *session, SSL *ssl
1713 ) {
1714  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
1715 
1716  if (context->psk_pki_enabled & IS_PSK) {
1717  SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
1718  SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1719  SSL_set_cipher_list(ssl, "PSK:!NULL");
1720  }
1721  if (context->psk_pki_enabled & IS_PKI) {
1722  coap_dtls_pki_t *setup_data = &context->setup_data;
1723  if (!setup_pki_ssl(ssl, setup_data, 0))
1724  return 0;
1725  /* libcoap is managing (D)TLS connection based on setup_data options */
1726  if (session->proto == COAP_PROTO_TLS)
1727  SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
1728 
1729  /* Issue SNI if requested */
1730  if (setup_data->client_sni &&
1731  SSL_set_tlsext_host_name (ssl, setup_data->client_sni) != 1) {
1732  coap_log(LOG_WARNING, "SSL_set_tlsext_host_name: set '%s' failed",
1733  setup_data->client_sni);
1734  }
1735  /* Certificate Revocation */
1736  if (setup_data->check_cert_revocation) {
1737  X509_VERIFY_PARAM *param;
1738 
1739  param = X509_VERIFY_PARAM_new();
1740  X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
1741  SSL_set1_param(ssl, param);
1742  X509_VERIFY_PARAM_free(param);
1743  }
1744 
1745  /* Verify Peer */
1746  if (setup_data->verify_peer_cert)
1747  SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_call_back);
1748  else
1749  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1750 
1751  /* Check CA Chain */
1752  if (setup_data->cert_chain_validation)
1753  SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth);
1754 
1755  }
1756  return 1;
1757 }
1758 
1760  BIO *bio = NULL;
1761  SSL *ssl = NULL;
1762  coap_ssl_data *data;
1763  int r;
1764  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
1765  coap_dtls_context_t *dtls = &context->dtls;
1766 
1767  ssl = SSL_new(dtls->ctx);
1768  if (!ssl)
1769  goto error;
1770  bio = BIO_new(dtls->meth);
1771  if (!bio)
1772  goto error;
1773  data = (coap_ssl_data *)BIO_get_data(bio);
1774  data->session = session;
1775  SSL_set_bio(ssl, bio, bio);
1776  SSL_set_app_data(ssl, session);
1777  SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
1778  SSL_set_mtu(ssl, session->mtu);
1779 
1780  if (!setup_client_ssl_session(session, ssl))
1781  goto error;
1782 
1783  session->dtls_timeout_count = 0;
1784 
1785  r = SSL_connect(ssl);
1786  if (r == -1) {
1787  int ret = SSL_get_error(ssl, r);
1788  if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
1789  r = 0;
1790  }
1791 
1792  if (r == 0)
1793  goto error;
1794 
1795  return ssl;
1796 
1797 error:
1798  if (ssl)
1799  SSL_free(ssl);
1800  return NULL;
1801 }
1802 
1804  SSL *ssl = (SSL *)session->tls;
1805  if (ssl)
1806  SSL_set_mtu(ssl, session->mtu);
1807 }
1808 
1809 void coap_dtls_free_session(coap_session_t *session) {
1810  SSL *ssl = (SSL *)session->tls;
1811  if (ssl) {
1812  if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
1813  int r = SSL_shutdown(ssl);
1814  if (r == 0) r = SSL_shutdown(ssl);
1815  }
1816  SSL_free(ssl);
1817  session->tls = NULL;
1818  }
1819 }
1820 
1821 int coap_dtls_send(coap_session_t *session,
1822  const uint8_t *data, size_t data_len) {
1823  int r;
1824  SSL *ssl = (SSL *)session->tls;
1825 
1826  assert(ssl != NULL);
1827 
1828  session->dtls_event = -1;
1829  r = SSL_write(ssl, data, (int)data_len);
1830 
1831  if (r <= 0) {
1832  int err = SSL_get_error(ssl, r);
1833  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1834  r = 0;
1835  } else {
1836  coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n");
1837  if (err == SSL_ERROR_ZERO_RETURN)
1839  else if (err == SSL_ERROR_SSL)
1840  session->dtls_event = COAP_EVENT_DTLS_ERROR;
1841  r = -1;
1842  }
1843  }
1844 
1845  if (session->dtls_event >= 0) {
1846  coap_handle_event(session->context, session->dtls_event, session);
1847  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1848  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1850  r = -1;
1851  }
1852  }
1853 
1854  return r;
1855 }
1856 
1857 int coap_dtls_is_context_timeout(void) {
1858  return 0;
1859 }
1860 
1861 coap_tick_t coap_dtls_get_context_timeout(void *dtls_context) {
1862  (void)dtls_context;
1863  return 0;
1864 }
1865 
1867  SSL *ssl = (SSL *)session->tls;
1868  coap_ssl_data *ssl_data;
1869 
1870  assert(ssl != NULL);
1871  ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
1872  return ssl_data->timeout;
1873 }
1874 
1876  SSL *ssl = (SSL *)session->tls;
1877 
1878  assert(ssl != NULL);
1879  if (((session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1880  (++session->dtls_timeout_count > session->max_retransmit)) ||
1881  (DTLSv1_handle_timeout(ssl) < 0)) {
1882  /* Too many retries */
1884  }
1885 }
1886 
1887 int coap_dtls_hello(coap_session_t *session,
1888  const uint8_t *data, size_t data_len) {
1889  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
1890  coap_ssl_data *ssl_data;
1891  int r;
1892 
1893  SSL_set_mtu(dtls->ssl, session->mtu);
1894  ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(dtls->ssl));
1895  ssl_data->session = session;
1896  ssl_data->pdu = data;
1897  ssl_data->pdu_len = (unsigned)data_len;
1898  r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
1899  if (r <= 0) {
1900  int err = SSL_get_error(dtls->ssl, r);
1901  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1902  /* Got a ClientHello, sent-out a VerifyRequest */
1903  r = 0;
1904  }
1905  } else {
1906  /* Got a valid answer to a VerifyRequest */
1907  r = 1;
1908  }
1909 
1910  return r;
1911 }
1912 
1913 int coap_dtls_receive(coap_session_t *session,
1914  const uint8_t *data, size_t data_len) {
1915  coap_ssl_data *ssl_data;
1916  SSL *ssl = (SSL *)session->tls;
1917  int r;
1918 
1919  assert(ssl != NULL);
1920 
1921  int in_init = SSL_in_init(ssl);
1923  ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
1924  ssl_data->pdu = data;
1925  ssl_data->pdu_len = (unsigned)data_len;
1926 
1927  session->dtls_event = -1;
1928  r = SSL_read(ssl, pdu, (int)sizeof(pdu));
1929  if (r > 0) {
1930  return coap_handle_dgram(session->context, session, pdu, (size_t)r);
1931  } else {
1932  int err = SSL_get_error(ssl, r);
1933  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1934  if (in_init && SSL_is_init_finished(ssl)) {
1936  coap_session_connected(session);
1937  }
1938  r = 0;
1939  } else {
1940  if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
1942  else if (err == SSL_ERROR_SSL)
1943  session->dtls_event = COAP_EVENT_DTLS_ERROR;
1944  r = -1;
1945  }
1946  if (session->dtls_event >= 0) {
1947  coap_handle_event(session->context, session->dtls_event, session);
1948  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1949  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1951  r = -1;
1952  }
1953  }
1954  }
1955 
1956  return r;
1957 }
1958 
1959 unsigned int coap_dtls_get_overhead(coap_session_t *session) {
1960  unsigned int overhead = 37;
1961  const SSL_CIPHER *s_ciph = NULL;
1962  if (session->tls != NULL)
1963  s_ciph = SSL_get_current_cipher(session->tls);
1964  if ( s_ciph ) {
1965  unsigned int ivlen, maclen, blocksize = 1, pad = 0;
1966 
1967  const EVP_CIPHER *e_ciph;
1968  const EVP_MD *e_md;
1969  char cipher[128];
1970 
1971  e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
1972 
1973  switch (EVP_CIPHER_mode(e_ciph)) {
1974  case EVP_CIPH_GCM_MODE:
1975  ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
1976  maclen = EVP_GCM_TLS_TAG_LEN;
1977  break;
1978 
1979  case EVP_CIPH_CCM_MODE:
1980  ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
1981  SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
1982  if (strstr(cipher, "CCM8"))
1983  maclen = 8;
1984  else
1985  maclen = 16;
1986  break;
1987 
1988  case EVP_CIPH_CBC_MODE:
1989  e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
1990  blocksize = EVP_CIPHER_block_size(e_ciph);
1991  ivlen = EVP_CIPHER_iv_length(e_ciph);
1992  pad = 1;
1993  maclen = EVP_MD_size(e_md);
1994  break;
1995 
1996  case EVP_CIPH_STREAM_CIPHER:
1997  /* Seen with PSK-CHACHA20-POLY1305 */
1998  ivlen = 8;
1999  maclen = 8;
2000  break;
2001 
2002  default:
2003  SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
2004  coap_log(LOG_WARNING, "Unknown overhead for DTLS with cipher %s\n",
2005  cipher);
2006  ivlen = 8;
2007  maclen = 16;
2008  break;
2009  }
2010  overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
2011  }
2012  return overhead;
2013 }
2014 
2015 void *coap_tls_new_client_session(coap_session_t *session, int *connected) {
2016  BIO *bio = NULL;
2017  SSL *ssl = NULL;
2018  int r;
2019  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
2020  coap_tls_context_t *tls = &context->tls;
2021 
2022  *connected = 0;
2023  ssl = SSL_new(tls->ctx);
2024  if (!ssl)
2025  goto error;
2026  bio = BIO_new(tls->meth);
2027  if (!bio)
2028  goto error;
2029  BIO_set_data(bio, session);
2030  SSL_set_bio(ssl, bio, bio);
2031  SSL_set_app_data(ssl, session);
2032 
2033  if (!setup_client_ssl_session(session, ssl))
2034  return 0;
2035 
2036  r = SSL_connect(ssl);
2037  if (r == -1) {
2038  int ret = SSL_get_error(ssl, r);
2039  if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
2040  r = 0;
2041  if (ret == SSL_ERROR_WANT_READ)
2042  session->sock.flags |= COAP_SOCKET_WANT_READ;
2043  if (ret == SSL_ERROR_WANT_WRITE)
2044  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2045  }
2046 
2047  if (r == 0)
2048  goto error;
2049 
2050  *connected = SSL_is_init_finished(ssl);
2051 
2052  return ssl;
2053 
2054 error:
2055  if (ssl)
2056  SSL_free(ssl);
2057  return NULL;
2058 }
2059 
2060 void *coap_tls_new_server_session(coap_session_t *session, int *connected) {
2061  BIO *bio = NULL;
2062  SSL *ssl = NULL;
2063  coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
2064  int r;
2065 
2066  *connected = 0;
2067  ssl = SSL_new(tls->ctx);
2068  if (!ssl)
2069  goto error;
2070  bio = BIO_new(tls->meth);
2071  if (!bio)
2072  goto error;
2073  BIO_set_data(bio, session);
2074  SSL_set_bio(ssl, bio, bio);
2075  SSL_set_app_data(ssl, session);
2076 
2077  if (session->context->get_server_hint) {
2078  char hint[128] = "";
2079  size_t hint_len = session->context->get_server_hint(session, (uint8_t*)hint, sizeof(hint) - 1);
2080  if (hint_len > 0 && hint_len < sizeof(hint)) {
2081  hint[hint_len] = 0;
2082  SSL_use_psk_identity_hint(ssl, hint);
2083  }
2084  }
2085 
2086  r = SSL_accept(ssl);
2087  if (r == -1) {
2088  int err = SSL_get_error(ssl, r);
2089  if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
2090  r = 0;
2091  if (err == SSL_ERROR_WANT_READ)
2092  session->sock.flags |= COAP_SOCKET_WANT_READ;
2093  if (err == SSL_ERROR_WANT_WRITE)
2094  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2095  }
2096 
2097  if (r == 0)
2098  goto error;
2099 
2100  *connected = SSL_is_init_finished(ssl);
2101 
2102  return ssl;
2103 
2104 error:
2105  if (ssl)
2106  SSL_free(ssl);
2107  return NULL;
2108 }
2109 
2110 void coap_tls_free_session(coap_session_t *session) {
2111  SSL *ssl = (SSL *)session->tls;
2112  if (ssl) {
2113  if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
2114  int r = SSL_shutdown(ssl);
2115  if (r == 0) r = SSL_shutdown(ssl);
2116  }
2117  SSL_free(ssl);
2118  session->tls = NULL;
2119  }
2120 }
2121 
2122 ssize_t coap_tls_write(coap_session_t *session,
2123  const uint8_t *data,
2124  size_t data_len
2125 ) {
2126  SSL *ssl = (SSL *)session->tls;
2127  int r, in_init;
2128 
2129  if (ssl == NULL)
2130  return -1;
2131 
2132  in_init = !SSL_is_init_finished(ssl);
2133  session->dtls_event = -1;
2134  r = SSL_write(ssl, data, (int)data_len);
2135 
2136  if (r <= 0) {
2137  int err = SSL_get_error(ssl, r);
2138  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2139  if (in_init && SSL_is_init_finished(ssl)) {
2141  coap_session_send_csm(session);
2142  }
2143  if (err == SSL_ERROR_WANT_READ)
2144  session->sock.flags |= COAP_SOCKET_WANT_READ;
2145  if (err == SSL_ERROR_WANT_WRITE)
2146  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2147  r = 0;
2148  } else {
2149  coap_log(LOG_WARNING, "***%s: coap_tls_write: cannot send PDU\n",
2150  coap_session_str(session));
2151  if (err == SSL_ERROR_ZERO_RETURN)
2153  else if (err == SSL_ERROR_SSL)
2154  session->dtls_event = COAP_EVENT_DTLS_ERROR;
2155  r = -1;
2156  }
2157  } else if (in_init && SSL_is_init_finished(ssl)) {
2159  coap_session_send_csm(session);
2160  }
2161 
2162  if (session->dtls_event >= 0) {
2163  coap_handle_event(session->context, session->dtls_event, session);
2164  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2165  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2167  r = -1;
2168  }
2169  }
2170 
2171  return r;
2172 }
2173 
2174 ssize_t coap_tls_read(coap_session_t *session,
2175  uint8_t *data,
2176  size_t data_len
2177 ) {
2178  SSL *ssl = (SSL *)session->tls;
2179  int r, in_init;
2180 
2181  if (ssl == NULL)
2182  return -1;
2183 
2184  in_init = !SSL_is_init_finished(ssl);
2185  session->dtls_event = -1;
2186  r = SSL_read(ssl, data, (int)data_len);
2187  if (r <= 0) {
2188  int err = SSL_get_error(ssl, r);
2189  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2190  if (in_init && SSL_is_init_finished(ssl)) {
2192  coap_session_send_csm(session);
2193  }
2194  if (err == SSL_ERROR_WANT_READ)
2195  session->sock.flags |= COAP_SOCKET_WANT_READ;
2196  if (err == SSL_ERROR_WANT_WRITE)
2197  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2198  r = 0;
2199  } else {
2200  if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
2202  else if (err == SSL_ERROR_SSL)
2203  session->dtls_event = COAP_EVENT_DTLS_ERROR;
2204  r = -1;
2205  }
2206  } else if (in_init && SSL_is_init_finished(ssl)) {
2208  coap_session_send_csm(session);
2209  }
2210 
2211  if (session->dtls_event >= 0) {
2212  coap_handle_event(session->context, session->dtls_event, session);
2213  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2214  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2216  r = -1;
2217  }
2218  }
2219 
2220  return r;
2221 }
2222 
2223 #else /* !HAVE_OPENSSL */
2224 
2225 #ifdef __clang__
2226 /* Make compilers happy that do not like empty modules. As this function is
2227  * never used, we ignore -Wunused-function at the end of compiling this file
2228  */
2229 #pragma GCC diagnostic ignored "-Wunused-function"
2230 #endif
2231 static inline void dummy(void) {
2232 }
2233 
2234 #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
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
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
Addtional 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
int coap_dtls_context_set_pki(coap_context_t *ctx UNUSED, coap_dtls_pki_t *setup_data UNUSED, int server UNUSED)
Definition: coap_notls.c:41
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
#define COAP_DTLS_ROLE_SERVER
Internal function invoked for server.
Definition: coap_dtls.h:265
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
int coap_dtls_context_set_psk(coap_context_t *ctx UNUSED, const char *hint UNUSED, int server UNUSED)
Definition: coap_notls.c:57
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
#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
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