libcoap  4.2.0
coap_openssl.c
Go to the documentation of this file.
1 /*
2 * coap_openssl.c -- Datagram Transport Layer Support for libcoap with openssl
3 *
4 * Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
5 * Copyright (C) 2018 Jon Shallow <supjps-libcoap@jpshallow.com>
6 *
7 * This file is part of the CoAP library libcoap. Please see README for terms
8 * of use.
9 */
10 
11 #include "coap_config.h"
12 
13 #ifdef HAVE_OPENSSL
14 
15 /*
16  * OpenSSL 1.1.0 has support for making decisions during receipt of
17  * the Client Hello - the call back function is set up using
18  * SSL_CTX_set_tlsext_servername_callback() which is called later in the
19  * Client Hello processing - but called every Client Hello.
20  * Certificates and Preshared Keys have to be set up in the SSL CTX before
21  * SSL_Accept() is called, making the code messy to decide whether this is a
22  * PKI or PSK incoming request to handle things accordingly if both are
23  * defined. SNI has to create a new SSL CTX to handle different server names
24  * with different crtificates.
25  *
26  * OpenSSL 1.1.1 introduces a new function SSL_CTX_set_client_hello_cb().
27  * The call back is invoked early on in the Client Hello processing giving
28  * the ability to easily use different Preshared Keys, Certificates etc.
29  * Certificates do not have to be set up in the SSL CTX before SSL_Accept is
30  * called.
31  * Later in the Client Hello code, the callback for
32  * SSL_CTX_set_tlsext_servername_callback() is still called, but only if SNI
33  * is being used by the client, so cannot be used for doing things the
34  * OpenSSL 1.1.0 way.
35  *
36  * OpenSSL 1.1.1 supports TLS1.3.
37  *
38  * Consequently, this code has to have compile time options to include /
39  * exclude code based on whether compiled against 1.1.0 or 1.1.1, as well as
40  * have additional run time checks.
41  *
42  */
43 #include "net.h"
44 #include "mem.h"
45 #include "coap_debug.h"
46 #include "prng.h"
47 #include <openssl/ssl.h>
48 #include <openssl/err.h>
49 #include <openssl/rand.h>
50 #include <openssl/hmac.h>
51 #include <openssl/x509v3.h>
52 
53 #if OPENSSL_VERSION_NUMBER < 0x10100000L
54 #error Must be compiled against OpenSSL 1.1.0 or later
55 #endif
56 
57 #ifdef __GNUC__
58 #define UNUSED __attribute__((unused))
59 #else
60 #define UNUSED
61 #endif /* __GNUC__ */
62 
63 /* RFC6091/RFC7250 */
64 #ifndef TLSEXT_TYPE_client_certificate_type
65 #define TLSEXT_TYPE_client_certificate_type 19
66 #endif
67 #ifndef TLSEXT_TYPE_server_certificate_type
68 #define TLSEXT_TYPE_server_certificate_type 20
69 #endif
70 
71 /* This structure encapsulates the OpenSSL context object. */
72 typedef struct coap_dtls_context_t {
73  SSL_CTX *ctx;
74  SSL *ssl; /* OpenSSL object for listening to connection requests */
75  HMAC_CTX *cookie_hmac;
76  BIO_METHOD *meth;
77  BIO_ADDR *bio_addr;
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 {
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  coap_dtls_role_t role
563 ) {
564  coap_openssl_context_t *context = ((coap_openssl_context_t *)ctx->dtls_context);
565  BIO *bio;
566 
567  if (role == COAP_DTLS_ROLE_SERVER) {
568  SSL_CTX_set_psk_server_callback(context->dtls.ctx, coap_dtls_psk_server_callback);
569  SSL_CTX_set_psk_server_callback(context->tls.ctx, coap_dtls_psk_server_callback);
570  SSL_CTX_use_psk_identity_hint(context->dtls.ctx, identity_hint ? identity_hint : "");
571  SSL_CTX_use_psk_identity_hint(context->tls.ctx, identity_hint ? identity_hint : "");
572  }
573  if (!context->dtls.ssl) {
574  /* This is set up to handle new incoming sessions to a server */
575  context->dtls.ssl = SSL_new(context->dtls.ctx);
576  if (!context->dtls.ssl)
577  return 0;
578  bio = BIO_new(context->dtls.meth);
579  if (!bio) {
580  SSL_free (context->dtls.ssl);
581  context->dtls.ssl = NULL;
582  return 0;
583  }
584  SSL_set_bio(context->dtls.ssl, bio, bio);
585  SSL_set_app_data(context->dtls.ssl, NULL);
586  SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
587  SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
588  }
589  context->psk_pki_enabled |= IS_PSK;
590  return 1;
591 }
592 
593 static int
594 map_key_type(int asn1_private_key_type
595 ) {
596  switch (asn1_private_key_type) {
597  case COAP_ASN1_PKEY_NONE: return EVP_PKEY_NONE;
598  case COAP_ASN1_PKEY_RSA: return EVP_PKEY_RSA;
599  case COAP_ASN1_PKEY_RSA2: return EVP_PKEY_RSA2;
600  case COAP_ASN1_PKEY_DSA: return EVP_PKEY_DSA;
601  case COAP_ASN1_PKEY_DSA1: return EVP_PKEY_DSA1;
602  case COAP_ASN1_PKEY_DSA2: return EVP_PKEY_DSA2;
603  case COAP_ASN1_PKEY_DSA3: return EVP_PKEY_DSA3;
604  case COAP_ASN1_PKEY_DSA4: return EVP_PKEY_DSA4;
605  case COAP_ASN1_PKEY_DH: return EVP_PKEY_DH;
606  case COAP_ASN1_PKEY_DHX: return EVP_PKEY_DHX;
607  case COAP_ASN1_PKEY_EC: return EVP_PKEY_EC;
608  case COAP_ASN1_PKEY_HMAC: return EVP_PKEY_HMAC;
609  case COAP_ASN1_PKEY_CMAC: return EVP_PKEY_CMAC;
610  case COAP_ASN1_PKEY_TLS1_PRF: return EVP_PKEY_TLS1_PRF;
611  case COAP_ASN1_PKEY_HKDF: return EVP_PKEY_HKDF;
612  default:
614  "*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
615  asn1_private_key_type);
616  break;
617  }
618  return 0;
619 }
620 static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
621 
622 static int
623 server_alpn_callback (SSL *ssl UNUSED,
624  const unsigned char **out,
625  unsigned char *outlen,
626  const unsigned char *in,
627  unsigned int inlen,
628  void *arg UNUSED
629 ) {
630  unsigned char *tout = NULL;
631  int ret;
632  if (inlen == 0)
633  return SSL_TLSEXT_ERR_NOACK;
634  ret = SSL_select_next_proto(&tout,
635  outlen,
636  coap_alpn,
637  sizeof(coap_alpn),
638  in,
639  inlen);
640  *out = tout;
641  return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
642 }
643 
644 static void
645 add_ca_to_cert_store(X509_STORE *st, X509 *x509)
646 {
647  long e;
648 
649  /* Flush out existing errors */
650  while ((e = ERR_get_error()) != 0) {
651  }
652 
653  if (!X509_STORE_add_cert(st, x509)) {
654  while ((e = ERR_get_error()) != 0) {
655  int r = ERR_GET_REASON(e);
656  if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
657  /* Not already added */
658  coap_log(LOG_WARNING, "***setup_pki: (D)TLS: %s at %s:%s\n",
659  ERR_reason_error_string(e),
660  ERR_lib_error_string(e),
661  ERR_func_error_string(e));
662  }
663  }
664  }
665 }
666 
667 #if OPENSSL_VERSION_NUMBER < 0x10101000L
668 static int
669 setup_pki_server(SSL_CTX *ctx,
670  coap_dtls_pki_t* setup_data
671 ) {
672  switch (setup_data->pki_key.key_type) {
673  case COAP_PKI_KEY_PEM:
674  if (setup_data->pki_key.key.pem.public_cert &&
675  setup_data->pki_key.key.pem.public_cert[0]) {
676  if (!(SSL_CTX_use_certificate_file(ctx,
677  setup_data->pki_key.key.pem.public_cert,
678  SSL_FILETYPE_PEM))) {
680  "*** setup_pki: (D)TLS: %s: Unable to configure "
681  "Server Certificate\n",
682  setup_data->pki_key.key.pem.public_cert);
683  return 0;
684  }
685  }
686  else {
688  "*** setup_pki: (D)TLS: No Server Certificate defined\n");
689  return 0;
690  }
691 
692  if (setup_data->pki_key.key.pem.private_key &&
693  setup_data->pki_key.key.pem.private_key[0]) {
694  if (!(SSL_CTX_use_PrivateKey_file(ctx,
695  setup_data->pki_key.key.pem.private_key,
696  SSL_FILETYPE_PEM))) {
698  "*** setup_pki: (D)TLS: %s: Unable to configure "
699  "Server Private Key\n",
700  setup_data->pki_key.key.pem.private_key);
701  return 0;
702  }
703  }
704  else {
706  "*** setup_pki: (D)TLS: No Server Private Key defined\n");
707  return 0;
708  }
709 
710  if (setup_data->pki_key.key.pem.ca_file &&
711  setup_data->pki_key.key.pem.ca_file[0]) {
712  STACK_OF(X509_NAME) *cert_names;
713  X509_STORE *st;
714  BIO *in;
715  X509 *x = NULL;
716  char *rw_var = NULL;
717  cert_names = SSL_load_client_CA_file(setup_data->pki_key.key.pem.ca_file);
718  if (cert_names != NULL)
719  SSL_CTX_set_client_CA_list(ctx, cert_names);
720  else {
722  "*** setup_pki: (D)TLS: %s: Unable to configure "
723  "client CA File\n",
724  setup_data->pki_key.key.pem.ca_file);
725  return 0;
726  }
727  st = SSL_CTX_get_cert_store(ctx);
728  in = BIO_new(BIO_s_file());
729  /* Need to do this to not get a compiler warning about const parameters */
730  memcpy(&rw_var, &setup_data->pki_key.key.pem.ca_file, sizeof (rw_var));
731  if (!BIO_read_filename(in, rw_var)) {
732  BIO_free(in);
733  X509_free(x);
734  break;
735  }
736 
737  for (;;) {
738  if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
739  break;
740  add_ca_to_cert_store(st, x);
741  }
742  BIO_free(in);
743  X509_free(x);
744  }
745  break;
746 
747  case COAP_PKI_KEY_ASN1:
748  if (setup_data->pki_key.key.asn1.public_cert &&
749  setup_data->pki_key.key.asn1.public_cert_len > 0) {
750  if (!(SSL_CTX_use_certificate_ASN1(ctx,
751  setup_data->pki_key.key.asn1.public_cert_len,
752  setup_data->pki_key.key.asn1.public_cert))) {
754  "*** setup_pki: (D)TLS: %s: Unable to configure "
755  "Server Certificate\n",
756  "ASN1");
757  return 0;
758  }
759  }
760  else {
762  "*** setup_pki: (D)TLS: No Server Certificate defined\n");
763  return 0;
764  }
765 
766  if (setup_data->pki_key.key.asn1.private_key &&
767  setup_data->pki_key.key.asn1.private_key_len > 0) {
768  int pkey_type = map_key_type(setup_data->pki_key.key.asn1.private_key_type);
769  if (!(SSL_CTX_use_PrivateKey_ASN1(pkey_type, ctx,
770  setup_data->pki_key.key.asn1.private_key,
771  setup_data->pki_key.key.asn1.private_key_len))) {
773  "*** setup_pki: (D)TLS: %s: Unable to configure "
774  "Server Private Key\n",
775  "ASN1");
776  return 0;
777  }
778  }
779  else {
781  "*** setup_pki: (D)TLS: No Server Private Key defined\n");
782  return 0;
783  }
784 
785  if (setup_data->pki_key.key.asn1.ca_cert &&
786  setup_data->pki_key.key.asn1.ca_cert_len > 0) {
787  /* Need to use a temp variable as it gets incremented*/
788  const uint8_t *p = setup_data->pki_key.key.asn1.ca_cert;
789  X509* x509 = d2i_X509(NULL, &p, setup_data->pki_key.key.asn1.ca_cert_len);
790  X509_STORE *st;
791  if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
793  "*** setup_pki: (D)TLS: %s: Unable to configure "
794  "client CA File\n",
795  "ASN1");
796  X509_free(x509);
797  return 0;
798  }
799  st = SSL_CTX_get_cert_store(ctx);
800  add_ca_to_cert_store(st, x509);
801  X509_free(x509);
802  }
803  break;
804  default:
806  "*** setup_pki: (D)TLS: Unknown key type %d\n",
807  setup_data->pki_key.key_type);
808  return 0;
809  }
810 
811  return 1;
812 }
813 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
814 
815 static int
816 setup_pki_ssl(SSL *ssl,
817  coap_dtls_pki_t* setup_data, coap_dtls_role_t role
818 ) {
819  switch (setup_data->pki_key.key_type) {
820  case COAP_PKI_KEY_PEM:
821  if (setup_data->pki_key.key.pem.public_cert &&
822  setup_data->pki_key.key.pem.public_cert[0]) {
823  if (!(SSL_use_certificate_file(ssl,
824  setup_data->pki_key.key.pem.public_cert,
825  SSL_FILETYPE_PEM))) {
827  "*** setup_pki: (D)TLS: %s: Unable to configure "
828  "%s Certificate\n",
829  setup_data->pki_key.key.pem.public_cert,
830  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
831  return 0;
832  }
833  }
834  else if (role == COAP_DTLS_ROLE_SERVER ||
835  (setup_data->pki_key.key.pem.private_key &&
836  setup_data->pki_key.key.pem.private_key[0])) {
838  "*** setup_pki: (D)TLS: No %s Certificate defined\n",
839  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
840  return 0;
841  }
842  if (setup_data->pki_key.key.pem.private_key &&
843  setup_data->pki_key.key.pem.private_key[0]) {
844  if (!(SSL_use_PrivateKey_file(ssl,
845  setup_data->pki_key.key.pem.private_key,
846  SSL_FILETYPE_PEM))) {
848  "*** setup_pki: (D)TLS: %s: Unable to configure "
849  "Client Private Key\n",
850  setup_data->pki_key.key.pem.private_key);
851  return 0;
852  }
853  }
854  else if (role == COAP_DTLS_ROLE_SERVER ||
855  (setup_data->pki_key.key.pem.public_cert &&
856  setup_data->pki_key.key.pem.public_cert[0])) {
858  "*** setup_pki: (D)TLS: No %s Private Key defined\n",
859  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
860  return 0;
861  }
862  if (setup_data->pki_key.key.pem.ca_file &&
863  setup_data->pki_key.key.pem.ca_file[0]) {
864  X509_STORE *st;
865  BIO *in;
866  X509 *x = NULL;
867  char *rw_var = NULL;
868  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
869 
870  if (role == COAP_DTLS_ROLE_SERVER) {
871  STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(setup_data->pki_key.key.pem.ca_file);
872 
873  if (cert_names != NULL)
874  SSL_set_client_CA_list(ssl, cert_names);
875  else {
877  "*** setup_pki: (D)TLS: %s: Unable to configure "
878  "%s CA File\n",
879  setup_data->pki_key.key.pem.ca_file,
880  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
881  return 0;
882  }
883  }
884 
885  /* Add CA to the trusted root CA store */
886  in = BIO_new(BIO_s_file());
887  /* Need to do this to not get a compiler warning about const parameters */
888  memcpy(&rw_var, &setup_data->pki_key.key.pem.ca_file, sizeof (rw_var));
889  if (!BIO_read_filename(in, rw_var)) {
890  BIO_free(in);
891  X509_free(x);
892  break;
893  }
894  st = SSL_CTX_get_cert_store(ctx);
895  for (;;) {
896  if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
897  break;
898  add_ca_to_cert_store(st, x);
899  }
900  BIO_free(in);
901  X509_free(x);
902  }
903  break;
904 
905  case COAP_PKI_KEY_ASN1:
906  if (setup_data->pki_key.key.asn1.public_cert &&
907  setup_data->pki_key.key.asn1.public_cert_len > 0) {
908  if (!(SSL_use_certificate_ASN1(ssl,
909  setup_data->pki_key.key.asn1.public_cert,
910  setup_data->pki_key.key.asn1.public_cert_len))) {
912  "*** setup_pki: (D)TLS: %s: Unable to configure "
913  "%s Certificate\n",
914  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client",
915  "ASN1");
916  return 0;
917  }
918  }
919  else if (role == COAP_DTLS_ROLE_SERVER ||
920  (setup_data->pki_key.key.asn1.private_key &&
921  setup_data->pki_key.key.asn1.private_key[0])) {
923  "*** setup_pki: (D)TLS: No %s Certificate defined\n",
924  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
925  return 0;
926  }
927  if (setup_data->pki_key.key.asn1.private_key &&
928  setup_data->pki_key.key.asn1.private_key_len > 0) {
929  int pkey_type = map_key_type(setup_data->pki_key.key.asn1.private_key_type);
930  if (!(SSL_use_PrivateKey_ASN1(pkey_type, ssl,
931  setup_data->pki_key.key.asn1.private_key,
932  setup_data->pki_key.key.asn1.private_key_len))) {
934  "*** setup_pki: (D)TLS: %s: Unable to configure "
935  "%s Private Key\n",
936  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client",
937  "ASN1");
938  return 0;
939  }
940  }
941  else if (role == COAP_DTLS_ROLE_SERVER ||
942  (setup_data->pki_key.key.asn1.public_cert &&
943  setup_data->pki_key.key.asn1.public_cert_len > 0)) {
945  "*** setup_pki: (D)TLS: No %s Private Key defined",
946  role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
947  return 0;
948  }
949  if (setup_data->pki_key.key.asn1.ca_cert &&
950  setup_data->pki_key.key.asn1.ca_cert_len > 0) {
951  /* Need to use a temp variable as it gets incremented*/
952  const uint8_t *p = setup_data->pki_key.key.asn1.ca_cert;
953  X509* x509 = d2i_X509(NULL, &p, setup_data->pki_key.key.asn1.ca_cert_len);
954  X509_STORE *st;
955  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
956 
957  if (role == COAP_DTLS_ROLE_SERVER) {
958  if (!x509 || !SSL_add_client_CA(ssl, x509)) {
960  "*** setup_pki: (D)TLS: %s: Unable to configure "
961  "client CA File\n",
962  "ASN1");
963  X509_free(x509);
964  return 0;
965  }
966  }
967 
968  /* Add CA to the trusted root CA store */
969  st = SSL_CTX_get_cert_store(ctx);
970  add_ca_to_cert_store(st, x509);
971  X509_free(x509);
972  }
973  break;
974  default:
976  "*** setup_pki: (D)TLS: Unknown key type %d\n",
977  setup_data->pki_key.key_type);
978  return 0;
979  }
980  return 1;
981 }
982 
983 static char*
984 get_common_name_from_cert(X509* x509) {
985  if (x509) {
986  char *cn;
987  int n;
988  STACK_OF(GENERAL_NAME) *san_list;
989  char buffer[256];
990 
991  san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
992  if (san_list) {
993  int san_count = sk_GENERAL_NAME_num(san_list);
994 
995  for (n = 0; n < san_count; n++) {
996  const GENERAL_NAME * name = sk_GENERAL_NAME_value (san_list, n);
997 
998  if (name->type == GEN_DNS) {
999  const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
1000 
1001  /* Make sure that there is not an embedded NUL in the dns_name */
1002  if (ASN1_STRING_length(name->d.dNSName) != (int)strlen (dns_name))
1003  continue;
1004  cn = OPENSSL_strdup(dns_name);
1005  sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
1006  return cn;
1007  }
1008  }
1009  sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
1010  }
1011  /* Otherwise look for the CN= field */
1012  X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
1013 
1014  /* Need to emulate strcasestr() here. Looking for CN= */
1015  n = strlen(buffer) - 3;
1016  cn = buffer;
1017  while (n > 0) {
1018  if (((cn[0] == 'C') || (cn[0] == 'c')) &&
1019  ((cn[1] == 'N') || (cn[1] == 'n')) &&
1020  (cn[2] == '=')) {
1021  cn += 3;
1022  break;
1023  }
1024  cn++;
1025  n--;
1026  }
1027  if (n > 0) {
1028  char * ecn = strchr(cn, '/');
1029  if (ecn) {
1030  return OPENSSL_strndup(cn, ecn-cn);
1031  }
1032  else {
1033  return OPENSSL_strdup(cn);
1034  }
1035  }
1036  }
1037  return NULL;
1038 }
1039 
1040 static int
1041 tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
1042  SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
1043  SSL_get_ex_data_X509_STORE_CTX_idx());
1044  coap_session_t *session = SSL_get_app_data(ssl);
1045  coap_openssl_context_t *context =
1046  ((coap_openssl_context_t *)session->context->dtls_context);
1047  coap_dtls_pki_t *setup_data = &context->setup_data;
1048  int depth = X509_STORE_CTX_get_error_depth(ctx);
1049  int err = X509_STORE_CTX_get_error(ctx);
1050  X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
1051  char *cn = get_common_name_from_cert(x509);
1052  int keep_preverify_ok = preverify_ok;
1053 
1054  if (!preverify_ok) {
1055  switch (err) {
1056  case X509_V_ERR_CERT_NOT_YET_VALID:
1057  case X509_V_ERR_CERT_HAS_EXPIRED:
1058  if (setup_data->allow_expired_certs)
1059  preverify_ok = 1;
1060  break;
1061  case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
1062  if (setup_data->allow_self_signed)
1063  preverify_ok = 1;
1064  break;
1065  case X509_V_ERR_UNABLE_TO_GET_CRL:
1066  if (setup_data->allow_no_crl)
1067  preverify_ok = 1;
1068  break;
1069  case X509_V_ERR_CRL_NOT_YET_VALID:
1070  case X509_V_ERR_CRL_HAS_EXPIRED:
1071  if (setup_data->allow_expired_crl)
1072  preverify_ok = 1;
1073  break;
1074  default:
1075  break;
1076  }
1077  if (!preverify_ok) {
1079  " %s: %s: '%s' depth=%d\n",
1080  coap_session_str(session),
1081  X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1082  /* Invoke the CN callback function for this failure */
1083  keep_preverify_ok = 1;
1084  }
1085  else {
1087  " %s: %s: overridden: '%s' depth=%d\n",
1088  coap_session_str(session),
1089  X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1090  }
1091  }
1092  /* Certificate - depth == 0 is the Client Cert */
1093  if (setup_data->validate_cn_call_back && keep_preverify_ok) {
1094  int length = i2d_X509(x509, NULL);
1095  uint8_t *base_buf;
1096  uint8_t *base_buf2 = base_buf = OPENSSL_malloc(length);
1097 
1098  /* base_buf2 gets moved to the end */
1099  i2d_X509(x509, &base_buf2);
1100  if (!setup_data->validate_cn_call_back(cn, base_buf, length, session,
1101  depth, preverify_ok,
1102  setup_data->cn_call_back_arg)) {
1103  if (depth == 0) {
1104  X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
1105  }
1106  else {
1107  X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
1108  }
1109  preverify_ok = 0;
1110  }
1111  OPENSSL_free(base_buf);
1112  }
1113  OPENSSL_free(cn);
1114  return preverify_ok;
1115 }
1116 
1117 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1118 /*
1119  * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
1120  * it is possible to determine whether this is a PKI or PSK incoming
1121  * request and adjust the Ciphers if necessary
1122  *
1123  * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
1124  */
1125 static int
1126 tls_secret_call_back(SSL *ssl,
1127  void *secret UNUSED,
1128  int *secretlen UNUSED,
1129  STACK_OF(SSL_CIPHER) *peer_ciphers,
1130  const SSL_CIPHER **cipher UNUSED,
1131  void *arg
1132 ) {
1133  int ii;
1134  int psk_requested = 0;
1135  coap_session_t *session = SSL_get_app_data(ssl);
1136  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t*)arg;
1137 
1138  if (session && session->context->psk_key && session->context->psk_key_len) {
1139  /* Is PSK being requested - if so, we need to change algorithms */
1140  for (ii = 0; ii < sk_SSL_CIPHER_num (peer_ciphers); ii++) {
1141  const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
1142 
1143  if (strstr (SSL_CIPHER_get_name (peer_cipher), "PSK")) {
1144  psk_requested = 1;
1145  break;
1146  }
1147  }
1148  }
1149  if (!psk_requested) {
1150  if (session) {
1151  coap_log(LOG_DEBUG, " %s: Using PKI ciphers\n",
1152  coap_session_str(session));
1153  }
1154  else {
1155  coap_log(LOG_DEBUG, "Using PKI ciphers\n");
1156  }
1157  if (setup_data->verify_peer_cert) {
1158  if (setup_data->require_peer_cert) {
1159  SSL_set_verify(ssl,
1160  SSL_VERIFY_PEER |
1161  SSL_VERIFY_CLIENT_ONCE |
1162  SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1163  tls_verify_call_back);
1164  }
1165  else {
1166  SSL_set_verify(ssl,
1167  SSL_VERIFY_PEER |
1168  SSL_VERIFY_CLIENT_ONCE,
1169  tls_verify_call_back);
1170  }
1171  }
1172  else {
1173  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1174  }
1175 
1176  /* Check CA Chain */
1177  if (setup_data->cert_chain_validation)
1178  SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth);
1179 
1180  /* Certificate Revocation */
1181  if (setup_data->check_cert_revocation) {
1182  X509_VERIFY_PARAM *param;
1183 
1184  param = X509_VERIFY_PARAM_new();
1185  X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
1186  SSL_set1_param(ssl, param);
1187  X509_VERIFY_PARAM_free(param);
1188  }
1189  }
1190  else {
1191  if (session) {
1192  if (session->context->psk_key && session->context->psk_key_len) {
1193  memcpy(secret, session->context->psk_key, session->context->psk_key_len);
1194  *secretlen = session->context->psk_key_len;
1195  }
1196  coap_log(LOG_DEBUG, " %s: Setting PSK ciphers\n",
1197  coap_session_str(session));
1198  }
1199  else {
1200  coap_log(LOG_DEBUG, "Setting PSK ciphers\n");
1201  }
1202  /*
1203  * Force a PSK algorithm to be used, so we do PSK
1204  */
1205  SSL_set_cipher_list (ssl, "PSK:!NULL");
1206  SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1207  }
1208  if (setup_data->additional_tls_setup_call_back) {
1209  /* Additional application setup wanted */
1210  if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
1211  return 0;
1212  }
1213  return 0;
1214 }
1215 
1216 /*
1217  * During the SSL/TLS initial negotiations, tls_server_name_call_back() is called
1218  * so it is possible to set up an extra callback to determine whether this is
1219  * a PKI or PSK incoming request and adjust the Ciphers if necessary
1220  *
1221  * Set up by SSL_CTX_set_tlsext_servername_callback() in coap_dtls_context_set_pki()
1222  */
1223 static int
1224 tls_server_name_call_back(SSL *ssl,
1225  int *sd UNUSED,
1226  void *arg
1227 ) {
1228  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t*)arg;
1229 
1230  if (!ssl) {
1231  return SSL_TLSEXT_ERR_NOACK;
1232  }
1233 
1234  if (setup_data->validate_sni_call_back) {
1235  /* SNI checking requested */
1236  coap_session_t *session = (coap_session_t*)SSL_get_app_data(ssl);
1237  coap_openssl_context_t *context =
1238  ((coap_openssl_context_t *)session->context->dtls_context);
1239  const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
1240  size_t i;
1241 
1242  if (!sni || !sni[0]) {
1243  sni = "";
1244  }
1245  for (i = 0; i < context->sni_count; i++) {
1246  if (!strcmp(sni, context->sni_entry_list[i].sni)) {
1247  break;
1248  }
1249  }
1250  if (i == context->sni_count) {
1251  SSL_CTX *ctx;
1252  coap_dtls_pki_t sni_setup_data;
1253  coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni,
1254  setup_data->sni_call_back_arg);
1255  if (!new_entry) {
1256  return SSL_TLSEXT_ERR_ALERT_FATAL;
1257  }
1258  /* Need to set up a new SSL_CTX to switch to */
1259  if (session->proto == COAP_PROTO_DTLS) {
1260  /* Set up DTLS context */
1261  ctx = SSL_CTX_new(DTLS_method());
1262  if (!ctx)
1263  goto error;
1264  SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
1265  SSL_CTX_set_app_data(ctx, &context->dtls);
1266  SSL_CTX_set_read_ahead(ctx, 1);
1267  SSL_CTX_set_cipher_list(ctx, "TLSv1.2:TLSv1.0");
1268  SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
1269  SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
1270  SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
1271  SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
1272  }
1273  else {
1274  /* Set up TLS context */
1275  ctx = SSL_CTX_new(TLS_method());
1276  if (!ctx)
1277  goto error;
1278  SSL_CTX_set_app_data(ctx, &context->tls);
1279  SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
1280  SSL_CTX_set_cipher_list(ctx, "TLSv1.2:TLSv1.0");
1281  SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
1282  SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
1283  }
1284  memset(&sni_setup_data, 0, sizeof(sni_setup_data));
1285  sni_setup_data.pki_key.key_type = new_entry->key_type;
1286  sni_setup_data.pki_key.key.pem = new_entry->key.pem;
1287  sni_setup_data.pki_key.key.asn1 = new_entry->key.asn1;
1288  setup_pki_server(ctx, &sni_setup_data);
1289 
1290  context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
1291  (context->sni_count+1)*sizeof(sni_entry));
1292  context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
1293  context->sni_entry_list[context->sni_count].ctx = ctx;
1294  context->sni_count++;
1295  }
1296  SSL_set_SSL_CTX (ssl, context->sni_entry_list[i].ctx);
1297  SSL_clear_options (ssl, 0xFFFFFFFFL);
1298  SSL_set_options (ssl, SSL_CTX_get_options (context->sni_entry_list[i].ctx));
1299  }
1300 
1301  /*
1302  * Have to do extra call back next to get client algorithms
1303  * SSL_get_client_ciphers() does not work this early on
1304  */
1305  SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
1306  return SSL_TLSEXT_ERR_OK;
1307 
1308 error:
1309  return SSL_TLSEXT_ERR_ALERT_WARNING;
1310 }
1311 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1312 /*
1313  * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
1314  * called early in the Client Hello processing so it is possible to determine
1315  * whether this is a PKI or PSK incoming request and adjust the Ciphers if
1316  * necessary.
1317  *
1318  * Set up by SSL_CTX_set_client_hello_cb().
1319  */
1320 static int
1321 tls_client_hello_call_back(SSL *ssl,
1322  int *al,
1323  void *arg UNUSED
1324 ) {
1325  coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
1326  coap_openssl_context_t *dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
1327  coap_dtls_pki_t *setup_data = &dtls_context->setup_data;
1328  int psk_requested = 0;
1329  const unsigned char *out;
1330  size_t outlen;
1331 
1332  if (!ssl) {
1333  *al = SSL_AD_INTERNAL_ERROR;
1334  return SSL_CLIENT_HELLO_ERROR;
1335  }
1336 
1337  /*
1338  * See if PSK being requested
1339  */
1340  if (session && session->context->psk_key && session->context->psk_key_len) {
1341  int len = SSL_client_hello_get0_ciphers(ssl, &out);
1342  STACK_OF(SSL_CIPHER) *peer_ciphers = NULL;
1343  STACK_OF(SSL_CIPHER) *scsvc = NULL;
1344 
1345  if (len && SSL_bytes_to_cipher_list(ssl, out, len,
1346  SSL_client_hello_isv2(ssl),
1347  &peer_ciphers, &scsvc)) {
1348  int ii;
1349  for (ii = 0; ii < sk_SSL_CIPHER_num (peer_ciphers); ii++) {
1350  const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
1351 
1352  if (strstr (SSL_CIPHER_get_name (peer_cipher), "PSK")) {
1353  psk_requested = 1;
1354  break;
1355  }
1356  }
1357  }
1358  sk_SSL_CIPHER_free(peer_ciphers);
1359  sk_SSL_CIPHER_free(scsvc);
1360  }
1361 
1362  if (psk_requested) {
1363  /*
1364  * Client has requested PSK and it is supported
1365  */
1366  if (session) {
1367  coap_log(LOG_DEBUG, " %s: PSK request\n",
1368  coap_session_str(session));
1369  }
1370  else {
1371  coap_log(LOG_DEBUG, "PSK request\n");
1372  }
1373  SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1374  if (setup_data->additional_tls_setup_call_back) {
1375  /* Additional application setup wanted */
1376  if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
1377  return 0;
1378  }
1379  return SSL_CLIENT_HELLO_SUCCESS;
1380  }
1381 
1382  /*
1383  * Handle Certificate requests
1384  */
1385 
1386  /*
1387  * Determine what type of certificate is being requested
1388  */
1389  if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
1390  &out, &outlen)) {
1391  size_t ii;
1392  for (ii = 0; ii < outlen; ii++) {
1393  switch (out[ii]) {
1394  case 0:
1395  /* RFC6091 X.509 */
1396  if (outlen >= 2) {
1397  /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
1398  goto is_x509;
1399  }
1400  break;
1401  case 2:
1402  /* RFC7250 RPK - not yet supported */
1403  break;
1404  default:
1405  break;
1406  }
1407  }
1408  *al = SSL_AD_UNSUPPORTED_EXTENSION;
1409  return SSL_CLIENT_HELLO_ERROR;
1410  }
1411 
1412 is_x509:
1413  if (setup_data->validate_sni_call_back) {
1414  /*
1415  * SNI checking requested
1416  */
1417  coap_dtls_pki_t sni_setup_data;
1418  coap_openssl_context_t *context =
1419  ((coap_openssl_context_t *)session->context->dtls_context);
1420  const char *sni = "";
1421  char *sni_tmp = NULL;
1422  size_t i;
1423 
1424  if (SSL_client_hello_get0_ext (ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
1425  outlen > 5 &&
1426  (((out[0]<<8) + out[1] +2) == (int)outlen) &&
1427  out[2] == TLSEXT_NAMETYPE_host_name &&
1428  (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
1429  /* Skip over length, type and length */
1430  out += 5;
1431  outlen -= 5;
1432  sni_tmp = OPENSSL_malloc(outlen+1);
1433  sni_tmp[outlen] = '\000';
1434  memcpy(sni_tmp, out, outlen);
1435  sni = sni_tmp;
1436  }
1437  /* Is this a cached entry? */
1438  for (i = 0; i < context->sni_count; i++) {
1439  if (!strcmp(sni, context->sni_entry_list[i].sni)) {
1440  break;
1441  }
1442  }
1443  if (i == context->sni_count) {
1444  /*
1445  * New SNI request
1446  */
1447  coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni,
1448  setup_data->sni_call_back_arg);
1449  if (!new_entry) {
1450  *al = SSL_AD_UNRECOGNIZED_NAME;
1451  return SSL_CLIENT_HELLO_ERROR;
1452  }
1453 
1454 
1455  context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
1456  (context->sni_count+1)*sizeof(sni_entry));
1457  context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
1458  context->sni_entry_list[context->sni_count].pki_key = *new_entry;
1459  context->sni_count++;
1460  }
1461  if (sni_tmp) {
1462  OPENSSL_free(sni_tmp);
1463  }
1464  memset(&sni_setup_data, 0, sizeof(sni_setup_data));
1465  sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
1466  setup_pki_ssl(ssl, &sni_setup_data, 1);
1467  }
1468  else {
1469  setup_pki_ssl(ssl, setup_data, 1);
1470  }
1471 
1472  if (session) {
1473  coap_log(LOG_DEBUG, " %s: Using PKI ciphers\n",
1474  coap_session_str(session));
1475  }
1476  else {
1477  coap_log(LOG_DEBUG, "Using PKI ciphers\n");
1478  }
1479  if (setup_data->verify_peer_cert) {
1480  if (setup_data->require_peer_cert) {
1481  SSL_set_verify(ssl,
1482  SSL_VERIFY_PEER |
1483  SSL_VERIFY_CLIENT_ONCE |
1484  SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1485  tls_verify_call_back);
1486  }
1487  else {
1488  SSL_set_verify(ssl,
1489  SSL_VERIFY_PEER |
1490  SSL_VERIFY_CLIENT_ONCE,
1491  tls_verify_call_back);
1492  }
1493  }
1494  else {
1495  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1496  }
1497 
1498  /* Check CA Chain */
1499  if (setup_data->cert_chain_validation)
1500  SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth);
1501 
1502  /* Certificate Revocation */
1503  if (setup_data->check_cert_revocation) {
1504  X509_VERIFY_PARAM *param;
1505 
1506  param = X509_VERIFY_PARAM_new();
1507  X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
1508  SSL_set1_param(ssl, param);
1509  X509_VERIFY_PARAM_free(param);
1510  }
1511  if (setup_data->additional_tls_setup_call_back) {
1512  /* Additional application setup wanted */
1513  if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
1514  return 0;
1515  }
1516  return SSL_CLIENT_HELLO_SUCCESS;
1517 }
1518 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1519 
1520 int
1522  coap_dtls_pki_t *setup_data,
1523  coap_dtls_role_t role
1524 ) {
1525  coap_openssl_context_t *context =
1526  ((coap_openssl_context_t *)ctx->dtls_context);
1527  BIO *bio;
1528  if (!setup_data)
1529  return 0;
1530  context->setup_data = *setup_data;
1531  if (role == COAP_DTLS_ROLE_SERVER) {
1532  if (context->dtls.ctx) {
1533  /* SERVER DTLS */
1534 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1535  if (!setup_pki_server(context->dtls.ctx, setup_data))
1536  return 0;
1537 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1538  /* libcoap is managing TLS connection based on setup_data options */
1539  /* Need to set up logic to differentiate between a PSK or PKI session */
1540  /*
1541  * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
1542  * which is not in 1.1.0
1543  */
1544 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1545  if (SSLeay() >= 0x10101000L) {
1547  "OpenSSL compiled with %lux, linked with %lux, so "
1548  "no certificate checking\n",
1549  OPENSSL_VERSION_NUMBER, SSLeay());
1550  }
1551  SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
1552  SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
1553  tls_server_name_call_back);
1554 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1555  SSL_CTX_set_client_hello_cb(context->dtls.ctx,
1556  tls_client_hello_call_back,
1557  NULL);
1558 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1559  }
1560  if (context->tls.ctx) {
1561  /* SERVER TLS */
1562 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1563  if (!setup_pki_server(context->tls.ctx, setup_data))
1564  return 0;
1565 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1566  /* libcoap is managing TLS connection based on setup_data options */
1567  /* Need to set up logic to differentiate between a PSK or PKI session */
1568  /*
1569  * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
1570  * which is not in 1.1.0
1571  */
1572 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1573  if (SSLeay() >= 0x10101000L) {
1575  "OpenSSL compiled with %lux, linked with %lux, so "
1576  "no certificate checking\n",
1577  OPENSSL_VERSION_NUMBER, SSLeay());
1578  }
1579  SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
1580  SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
1581  tls_server_name_call_back);
1582 #else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1583  SSL_CTX_set_client_hello_cb(context->tls.ctx,
1584  tls_client_hello_call_back,
1585  NULL);
1586 #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1587  /* TLS Only */
1588  SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
1589  }
1590  }
1591 
1592  if (!context->dtls.ssl) {
1593  /* This is set up to handle new incoming sessions to a server */
1594  context->dtls.ssl = SSL_new(context->dtls.ctx);
1595  if (!context->dtls.ssl)
1596  return 0;
1597  bio = BIO_new(context->dtls.meth);
1598  if (!bio) {
1599  SSL_free (context->dtls.ssl);
1600  context->dtls.ssl = NULL;
1601  return 0;
1602  }
1603  SSL_set_bio(context->dtls.ssl, bio, bio);
1604  SSL_set_app_data(context->dtls.ssl, NULL);
1605  SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1606  SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
1607  }
1608  context->psk_pki_enabled |= IS_PKI;
1609  return 1;
1610 }
1611 
1612 int
1614  const char *ca_file,
1615  const char *ca_dir
1616 ) {
1617  coap_openssl_context_t *context =
1618  ((coap_openssl_context_t *)ctx->dtls_context);
1619  if (context->dtls.ctx) {
1620  if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
1621  coap_log(LOG_WARNING, "Unable to install root CAs (%s/%s)\n",
1622  ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
1623  return 0;
1624  }
1625  }
1626  if (context->tls.ctx) {
1627  if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
1628  coap_log(LOG_WARNING, "Unable to install root CAs (%s/%s)\n",
1629  ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
1630  return 0;
1631  }
1632  }
1633  return 1;
1634 }
1635 
1636 int
1638 {
1639  coap_openssl_context_t *context =
1640  ((coap_openssl_context_t *)ctx->dtls_context);
1641  return context->psk_pki_enabled ? 1 : 0;
1642 }
1643 
1644 
1645 void coap_dtls_free_context(void *handle) {
1646  size_t i;
1647  coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
1648 
1649  if (context->dtls.ssl)
1650  SSL_free(context->dtls.ssl);
1651  if (context->dtls.ctx)
1652  SSL_CTX_free(context->dtls.ctx);
1653  if (context->dtls.cookie_hmac)
1654  HMAC_CTX_free(context->dtls.cookie_hmac);
1655  if (context->dtls.meth)
1656  BIO_meth_free(context->dtls.meth);
1657  if (context->dtls.bio_addr)
1658  BIO_ADDR_free(context->dtls.bio_addr);
1659  if ( context->tls.ctx )
1660  SSL_CTX_free( context->tls.ctx );
1661  if ( context->tls.meth )
1662  BIO_meth_free( context->tls.meth );
1663  for (i = 0; i < context->sni_count; i++) {
1664  OPENSSL_free(context->sni_entry_list[i].sni);
1665 #if OPENSSL_VERSION_NUMBER < 0x10101000L
1666  SSL_CTX_free(context->sni_entry_list[i].ctx);
1667 #endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1668  }
1669  if (context->sni_count)
1670  OPENSSL_free(context->sni_entry_list);
1671  coap_free(context);
1672 }
1673 
1675  BIO *nbio = NULL;
1676  SSL *nssl = NULL, *ssl = NULL;
1677  coap_ssl_data *data;
1678  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
1679  int r;
1680 
1681  nssl = SSL_new(dtls->ctx);
1682  if (!nssl)
1683  goto error;
1684  nbio = BIO_new(dtls->meth);
1685  if (!nbio)
1686  goto error;
1687  SSL_set_bio(nssl, nbio, nbio);
1688  SSL_set_app_data(nssl, NULL);
1689  SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
1690  SSL_set_mtu(nssl, session->mtu);
1691  ssl = dtls->ssl;
1692  dtls->ssl = nssl;
1693  nssl = NULL;
1694  SSL_set_app_data(ssl, session);
1695 
1696  data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
1697  data->session = session;
1698 
1699  if (session->context->get_server_hint) {
1700  char hint[128] = "";
1701  size_t hint_len = session->context->get_server_hint(session, (uint8_t*)hint, sizeof(hint) - 1);
1702  if (hint_len > 0 && hint_len < sizeof(hint)) {
1703  hint[hint_len] = 0;
1704  SSL_use_psk_identity_hint(ssl, hint);
1705  }
1706  }
1707 
1708  r = SSL_accept(ssl);
1709  if (r == -1) {
1710  int err = SSL_get_error(ssl, r);
1711  if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
1712  r = 0;
1713  }
1714 
1715  if (r == 0) {
1716  SSL_free(ssl);
1717  return NULL;
1718  }
1719 
1720  return ssl;
1721 
1722 error:
1723  if (nssl)
1724  SSL_free(nssl);
1725  return NULL;
1726 }
1727 
1728 static int
1729 setup_client_ssl_session(coap_session_t *session, SSL *ssl
1730 ) {
1731  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
1732 
1733  if (context->psk_pki_enabled & IS_PSK) {
1734  SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
1735  SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1736  SSL_set_cipher_list(ssl, "PSK:!NULL");
1737  }
1738  if (context->psk_pki_enabled & IS_PKI) {
1739  coap_dtls_pki_t *setup_data = &context->setup_data;
1740  if (!setup_pki_ssl(ssl, setup_data, 0))
1741  return 0;
1742  /* libcoap is managing (D)TLS connection based on setup_data options */
1743  if (session->proto == COAP_PROTO_TLS)
1744  SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
1745 
1746  /* Issue SNI if requested */
1747  if (setup_data->client_sni &&
1748  SSL_set_tlsext_host_name (ssl, setup_data->client_sni) != 1) {
1749  coap_log(LOG_WARNING, "SSL_set_tlsext_host_name: set '%s' failed",
1750  setup_data->client_sni);
1751  }
1752  /* Certificate Revocation */
1753  if (setup_data->check_cert_revocation) {
1754  X509_VERIFY_PARAM *param;
1755 
1756  param = X509_VERIFY_PARAM_new();
1757  X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
1758  SSL_set1_param(ssl, param);
1759  X509_VERIFY_PARAM_free(param);
1760  }
1761 
1762  /* Verify Peer */
1763  if (setup_data->verify_peer_cert)
1764  SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_call_back);
1765  else
1766  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1767 
1768  /* Check CA Chain */
1769  if (setup_data->cert_chain_validation)
1770  SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth);
1771 
1772  }
1773  return 1;
1774 }
1775 
1777  BIO *bio = NULL;
1778  SSL *ssl = NULL;
1779  coap_ssl_data *data;
1780  int r;
1781  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
1782  coap_dtls_context_t *dtls = &context->dtls;
1783 
1784  ssl = SSL_new(dtls->ctx);
1785  if (!ssl)
1786  goto error;
1787  bio = BIO_new(dtls->meth);
1788  if (!bio)
1789  goto error;
1790  data = (coap_ssl_data *)BIO_get_data(bio);
1791  data->session = session;
1792  SSL_set_bio(ssl, bio, bio);
1793  SSL_set_app_data(ssl, session);
1794  SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
1795  SSL_set_mtu(ssl, session->mtu);
1796 
1797  if (!setup_client_ssl_session(session, ssl))
1798  goto error;
1799 
1800  session->dtls_timeout_count = 0;
1801 
1802  r = SSL_connect(ssl);
1803  if (r == -1) {
1804  int ret = SSL_get_error(ssl, r);
1805  if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
1806  r = 0;
1807  }
1808 
1809  if (r == 0)
1810  goto error;
1811 
1812  return ssl;
1813 
1814 error:
1815  if (ssl)
1816  SSL_free(ssl);
1817  return NULL;
1818 }
1819 
1821  SSL *ssl = (SSL *)session->tls;
1822  if (ssl)
1823  SSL_set_mtu(ssl, session->mtu);
1824 }
1825 
1826 void coap_dtls_free_session(coap_session_t *session) {
1827  SSL *ssl = (SSL *)session->tls;
1828  if (ssl) {
1829  if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
1830  int r = SSL_shutdown(ssl);
1831  if (r == 0) r = SSL_shutdown(ssl);
1832  }
1833  SSL_free(ssl);
1834  session->tls = NULL;
1835  }
1836 }
1837 
1838 int coap_dtls_send(coap_session_t *session,
1839  const uint8_t *data, size_t data_len) {
1840  int r;
1841  SSL *ssl = (SSL *)session->tls;
1842 
1843  assert(ssl != NULL);
1844 
1845  session->dtls_event = -1;
1846  r = SSL_write(ssl, data, (int)data_len);
1847 
1848  if (r <= 0) {
1849  int err = SSL_get_error(ssl, r);
1850  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1851  r = 0;
1852  } else {
1853  coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n");
1854  if (err == SSL_ERROR_ZERO_RETURN)
1856  else if (err == SSL_ERROR_SSL)
1857  session->dtls_event = COAP_EVENT_DTLS_ERROR;
1858  r = -1;
1859  }
1860  }
1861 
1862  if (session->dtls_event >= 0) {
1863  coap_handle_event(session->context, session->dtls_event, session);
1864  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1865  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1867  r = -1;
1868  }
1869  }
1870 
1871  return r;
1872 }
1873 
1874 int coap_dtls_is_context_timeout(void) {
1875  return 0;
1876 }
1877 
1878 coap_tick_t coap_dtls_get_context_timeout(void *dtls_context) {
1879  (void)dtls_context;
1880  return 0;
1881 }
1882 
1884  SSL *ssl = (SSL *)session->tls;
1885  coap_ssl_data *ssl_data;
1886 
1887  assert(ssl != NULL);
1888  ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
1889  return ssl_data->timeout;
1890 }
1891 
1893  SSL *ssl = (SSL *)session->tls;
1894 
1895  assert(ssl != NULL);
1896  if (((session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1897  (++session->dtls_timeout_count > session->max_retransmit)) ||
1898  (DTLSv1_handle_timeout(ssl) < 0)) {
1899  /* Too many retries */
1901  }
1902 }
1903 
1904 int coap_dtls_hello(coap_session_t *session,
1905  const uint8_t *data, size_t data_len) {
1906  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
1907  coap_ssl_data *ssl_data;
1908  int r;
1909 
1910  SSL_set_mtu(dtls->ssl, session->mtu);
1911  ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(dtls->ssl));
1912  ssl_data->session = session;
1913  ssl_data->pdu = data;
1914  ssl_data->pdu_len = (unsigned)data_len;
1915  r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
1916  if (r <= 0) {
1917  int err = SSL_get_error(dtls->ssl, r);
1918  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1919  /* Got a ClientHello, sent-out a VerifyRequest */
1920  r = 0;
1921  }
1922  } else {
1923  /* Got a valid answer to a VerifyRequest */
1924  r = 1;
1925  }
1926 
1927  return r;
1928 }
1929 
1930 int coap_dtls_receive(coap_session_t *session,
1931  const uint8_t *data, size_t data_len) {
1932  coap_ssl_data *ssl_data;
1933  SSL *ssl = (SSL *)session->tls;
1934  int r;
1935 
1936  assert(ssl != NULL);
1937 
1938  int in_init = SSL_in_init(ssl);
1940  ssl_data = (coap_ssl_data*)BIO_get_data(SSL_get_rbio(ssl));
1941  ssl_data->pdu = data;
1942  ssl_data->pdu_len = (unsigned)data_len;
1943 
1944  session->dtls_event = -1;
1945  r = SSL_read(ssl, pdu, (int)sizeof(pdu));
1946  if (r > 0) {
1947  return coap_handle_dgram(session->context, session, pdu, (size_t)r);
1948  } else {
1949  int err = SSL_get_error(ssl, r);
1950  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1951  if (in_init && SSL_is_init_finished(ssl)) {
1953  coap_session_connected(session);
1954  }
1955  r = 0;
1956  } else {
1957  if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
1959  else if (err == SSL_ERROR_SSL)
1960  session->dtls_event = COAP_EVENT_DTLS_ERROR;
1961  r = -1;
1962  }
1963  if (session->dtls_event >= 0) {
1964  coap_handle_event(session->context, session->dtls_event, session);
1965  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1966  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1968  r = -1;
1969  }
1970  }
1971  }
1972 
1973  return r;
1974 }
1975 
1976 unsigned int coap_dtls_get_overhead(coap_session_t *session) {
1977  unsigned int overhead = 37;
1978  const SSL_CIPHER *s_ciph = NULL;
1979  if (session->tls != NULL)
1980  s_ciph = SSL_get_current_cipher(session->tls);
1981  if ( s_ciph ) {
1982  unsigned int ivlen, maclen, blocksize = 1, pad = 0;
1983 
1984  const EVP_CIPHER *e_ciph;
1985  const EVP_MD *e_md;
1986  char cipher[128];
1987 
1988  e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
1989 
1990  switch (EVP_CIPHER_mode(e_ciph)) {
1991  case EVP_CIPH_GCM_MODE:
1992  ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
1993  maclen = EVP_GCM_TLS_TAG_LEN;
1994  break;
1995 
1996  case EVP_CIPH_CCM_MODE:
1997  ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
1998  SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
1999  if (strstr(cipher, "CCM8"))
2000  maclen = 8;
2001  else
2002  maclen = 16;
2003  break;
2004 
2005  case EVP_CIPH_CBC_MODE:
2006  e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
2007  blocksize = EVP_CIPHER_block_size(e_ciph);
2008  ivlen = EVP_CIPHER_iv_length(e_ciph);
2009  pad = 1;
2010  maclen = EVP_MD_size(e_md);
2011  break;
2012 
2013  case EVP_CIPH_STREAM_CIPHER:
2014  /* Seen with PSK-CHACHA20-POLY1305 */
2015  ivlen = 8;
2016  maclen = 8;
2017  break;
2018 
2019  default:
2020  SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
2021  coap_log(LOG_WARNING, "Unknown overhead for DTLS with cipher %s\n",
2022  cipher);
2023  ivlen = 8;
2024  maclen = 16;
2025  break;
2026  }
2027  overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
2028  }
2029  return overhead;
2030 }
2031 
2032 void *coap_tls_new_client_session(coap_session_t *session, int *connected) {
2033  BIO *bio = NULL;
2034  SSL *ssl = NULL;
2035  int r;
2036  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
2037  coap_tls_context_t *tls = &context->tls;
2038 
2039  *connected = 0;
2040  ssl = SSL_new(tls->ctx);
2041  if (!ssl)
2042  goto error;
2043  bio = BIO_new(tls->meth);
2044  if (!bio)
2045  goto error;
2046  BIO_set_data(bio, session);
2047  SSL_set_bio(ssl, bio, bio);
2048  SSL_set_app_data(ssl, session);
2049 
2050  if (!setup_client_ssl_session(session, ssl))
2051  return 0;
2052 
2053  r = SSL_connect(ssl);
2054  if (r == -1) {
2055  int ret = SSL_get_error(ssl, r);
2056  if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
2057  r = 0;
2058  if (ret == SSL_ERROR_WANT_READ)
2059  session->sock.flags |= COAP_SOCKET_WANT_READ;
2060  if (ret == SSL_ERROR_WANT_WRITE)
2061  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2062  }
2063 
2064  if (r == 0)
2065  goto error;
2066 
2067  *connected = SSL_is_init_finished(ssl);
2068 
2069  return ssl;
2070 
2071 error:
2072  if (ssl)
2073  SSL_free(ssl);
2074  return NULL;
2075 }
2076 
2077 void *coap_tls_new_server_session(coap_session_t *session, int *connected) {
2078  BIO *bio = NULL;
2079  SSL *ssl = NULL;
2080  coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
2081  int r;
2082 
2083  *connected = 0;
2084  ssl = SSL_new(tls->ctx);
2085  if (!ssl)
2086  goto error;
2087  bio = BIO_new(tls->meth);
2088  if (!bio)
2089  goto error;
2090  BIO_set_data(bio, session);
2091  SSL_set_bio(ssl, bio, bio);
2092  SSL_set_app_data(ssl, session);
2093 
2094  if (session->context->get_server_hint) {
2095  char hint[128] = "";
2096  size_t hint_len = session->context->get_server_hint(session, (uint8_t*)hint, sizeof(hint) - 1);
2097  if (hint_len > 0 && hint_len < sizeof(hint)) {
2098  hint[hint_len] = 0;
2099  SSL_use_psk_identity_hint(ssl, hint);
2100  }
2101  }
2102 
2103  r = SSL_accept(ssl);
2104  if (r == -1) {
2105  int err = SSL_get_error(ssl, r);
2106  if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
2107  r = 0;
2108  if (err == SSL_ERROR_WANT_READ)
2109  session->sock.flags |= COAP_SOCKET_WANT_READ;
2110  if (err == SSL_ERROR_WANT_WRITE)
2111  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2112  }
2113 
2114  if (r == 0)
2115  goto error;
2116 
2117  *connected = SSL_is_init_finished(ssl);
2118 
2119  return ssl;
2120 
2121 error:
2122  if (ssl)
2123  SSL_free(ssl);
2124  return NULL;
2125 }
2126 
2127 void coap_tls_free_session(coap_session_t *session) {
2128  SSL *ssl = (SSL *)session->tls;
2129  if (ssl) {
2130  if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
2131  int r = SSL_shutdown(ssl);
2132  if (r == 0) r = SSL_shutdown(ssl);
2133  }
2134  SSL_free(ssl);
2135  session->tls = NULL;
2136  }
2137 }
2138 
2139 ssize_t coap_tls_write(coap_session_t *session,
2140  const uint8_t *data,
2141  size_t data_len
2142 ) {
2143  SSL *ssl = (SSL *)session->tls;
2144  int r, in_init;
2145 
2146  if (ssl == NULL)
2147  return -1;
2148 
2149  in_init = !SSL_is_init_finished(ssl);
2150  session->dtls_event = -1;
2151  r = SSL_write(ssl, data, (int)data_len);
2152 
2153  if (r <= 0) {
2154  int err = SSL_get_error(ssl, r);
2155  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2156  if (in_init && SSL_is_init_finished(ssl)) {
2158  coap_session_send_csm(session);
2159  }
2160  if (err == SSL_ERROR_WANT_READ)
2161  session->sock.flags |= COAP_SOCKET_WANT_READ;
2162  if (err == SSL_ERROR_WANT_WRITE)
2163  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2164  r = 0;
2165  } else {
2166  coap_log(LOG_WARNING, "***%s: coap_tls_write: cannot send PDU\n",
2167  coap_session_str(session));
2168  if (err == SSL_ERROR_ZERO_RETURN)
2170  else if (err == SSL_ERROR_SSL)
2171  session->dtls_event = COAP_EVENT_DTLS_ERROR;
2172  r = -1;
2173  }
2174  } else if (in_init && SSL_is_init_finished(ssl)) {
2176  coap_session_send_csm(session);
2177  }
2178 
2179  if (session->dtls_event >= 0) {
2180  coap_handle_event(session->context, session->dtls_event, session);
2181  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2182  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2184  r = -1;
2185  }
2186  }
2187 
2188  return r;
2189 }
2190 
2191 ssize_t coap_tls_read(coap_session_t *session,
2192  uint8_t *data,
2193  size_t data_len
2194 ) {
2195  SSL *ssl = (SSL *)session->tls;
2196  int r, in_init;
2197 
2198  if (ssl == NULL)
2199  return -1;
2200 
2201  in_init = !SSL_is_init_finished(ssl);
2202  session->dtls_event = -1;
2203  r = SSL_read(ssl, data, (int)data_len);
2204  if (r <= 0) {
2205  int err = SSL_get_error(ssl, r);
2206  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
2207  if (in_init && SSL_is_init_finished(ssl)) {
2209  coap_session_send_csm(session);
2210  }
2211  if (err == SSL_ERROR_WANT_READ)
2212  session->sock.flags |= COAP_SOCKET_WANT_READ;
2213  if (err == SSL_ERROR_WANT_WRITE)
2214  session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2215  r = 0;
2216  } else {
2217  if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
2219  else if (err == SSL_ERROR_SSL)
2220  session->dtls_event = COAP_EVENT_DTLS_ERROR;
2221  r = -1;
2222  }
2223  } else if (in_init && SSL_is_init_finished(ssl)) {
2225  coap_session_send_csm(session);
2226  }
2227 
2228  if (session->dtls_event >= 0) {
2229  coap_handle_event(session->context, session->dtls_event, session);
2230  if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2231  session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2233  r = -1;
2234  }
2235  }
2236 
2237  return r;
2238 }
2239 
2240 #else /* !HAVE_OPENSSL */
2241 
2242 #ifdef __clang__
2243 /* Make compilers happy that do not like empty modules. As this function is
2244  * never used, we ignore -Wunused-function at the end of compiling this file
2245  */
2246 #pragma GCC diagnostic ignored "-Wunused-function"
2247 #endif
2248 static inline void dummy(void) {
2249 }
2250 
2251 #endif /* HAVE_OPENSSL */
unsigned mtu
path or CSM mtu
Definition: coap_session.h:63
void coap_dtls_set_log_level(int level)
Sets the log level to the specified value.
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)
Returns the current log level.
#define COAP_TLS_LIBRARY_OPENSSL
Using OpenSSL library.
Definition: coap_dtls.h:40
#define COAP_PROTO_DTLS
Definition: pdu.h:345
void * coap_dtls_new_client_session(coap_session_t *session UNUSED)
Definition: coap_notls.c:98
Internal function invoked for server.
Definition: coap_dtls.h:266
HKDF type.
Definition: coap_dtls.h:125
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_dtls.c:891
int coap_dtls_context_set_pki(coap_context_t *ctx UNUSED, coap_dtls_pki_t *setup_data UNUSED, coap_dtls_role_t role UNUSED)
Definition: coap_notls.c:41
void * coap_tls_new_server_session(coap_session_t *session UNUSED, int *connected UNUSED)
Definition: coap_notls.c:155
ssize_t coap_tls_write(coap_session_t *session UNUSED, const uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:162
void * sni_call_back_arg
Passed in to the sni call-back function.
Definition: coap_dtls.h:227
ssize_t coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len)
Definition: coap_io.c:665
ssize_t coap_session_send(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for datagram data transmission.
Definition: coap_session.c:218
int dtls_event
Tracking any (D)TLS events on this sesison.
Definition: coap_session.h:93
uint8_t verify_peer_cert
Set to 1 to support this version of the struct.
Definition: coap_dtls.h:195
Debug.
Definition: coap_debug.h:49
uint8_t allow_no_crl
1 ignore if CRL not there
Definition: coap_dtls.h:202
uint64_t version
(D)TLS runtime Library Version
Definition: coap_dtls.h:48
size_t(* get_client_psk)(const coap_session_t *session, const uint8_t *hint, size_t hint_len, uint8_t *identity, size_t *identity_len, size_t max_identity_len, uint8_t *psk, size_t max_psk_len)
Definition: net.h:203
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
void coap_dtls_free_session(coap_dtls_session_t *session UNUSED)
Definition: coap_dtls.c:925
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
struct coap_dtls_context_t coap_dtls_context_t
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
coap_tls_version_t * coap_get_tls_library_version(void)
Determine the type and version of the underlying (D)TLS library.
Definition: coap_notls.c:33
const char * private_key
File location of Private Key in PEM format.
Definition: coap_dtls.h:142
int type
Library type.
Definition: coap_dtls.h:49
uint8_t require_peer_cert
1 if peer cert is required
Definition: coap_dtls.h:196
coap_proto_t proto
protocol used
Definition: coap_session.h:58
coap_dtls_key_t pki_key
PKI key definition.
Definition: coap_dtls.h:240
coap_pki_key_pem_t pem
for PEM keys
Definition: coap_dtls.h:164
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition: coap_dtls.h:236
Warning.
Definition: coap_debug.h:46
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:85
#define assert(...)
Definition: mem.c:18
The structure that holds the PKI key information.
Definition: coap_dtls.h:161
unsigned int coap_dtls_get_overhead(coap_session_t *session UNUSED)
Definition: coap_notls.c:147
const uint8_t * public_cert
ASN1 (DER) Public Cert.
Definition: coap_dtls.h:150
const char * ca_file
File location of Common CA in PEM format.
Definition: coap_dtls.h:140
size_t ca_cert_len
ASN1 CA Cert length.
Definition: coap_dtls.h:152
The PKI key type is PEM.
Definition: coap_dtls.h:132
RSA type.
Definition: coap_dtls.h:112
#define UNUSED
Definition: coap_dtls.c:21
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
int coap_dtls_context_set_psk(coap_context_t *ctx UNUSED, const char *hint UNUSED, coap_dtls_role_t role UNUSED)
Definition: coap_notls.c:57
#define COAP_PROTO_TLS
Definition: pdu.h:347
uint8_t cert_chain_validation
1 if to check cert_chain_verify_depth
Definition: coap_dtls.h:199
COAP_STATIC_INLINE void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:82
Error.
Definition: coap_debug.h:45
void * dtls_context
Definition: net.h:207
union coap_dtls_key_t::@1 key
coap_session_state_t state
current state of relationaship with peer
Definition: coap_session.h:60
const uint8_t * private_key
ASN1 (DER) Private Key.
Definition: coap_dtls.h:151
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
coap_dtls_role_t
Definition: coap_dtls.h:264
size_t(* get_server_hint)(const coap_session_t *session, uint8_t *hint, size_t max_hint_len)
Definition: net.h:205
#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
void coap_dtls_free_context(struct coap_dtls_context_t *dtls_context)
Definition: coap_dtls.c:901
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
struct coap_dtls_context_t * coap_dtls_new_context(struct coap_context_t *coap_context UNUSED)
Definition: coap_dtls.c:896
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
int coap_dtls_send(struct coap_context_t *coap_context UNUSED, struct coap_dtls_session_t *session UNUSED, const unsigned char *data UNUSED, size_t data_len UNUSED)
Definition: coap_dtls.c:912
DSA2 type.
Definition: coap_dtls.h:116
coap_context_t * ctx
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 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
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