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