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