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