libcoap  4.3.0rc2
coap_tinydtls.c
Go to the documentation of this file.
1 /*
2  * coap_tinydtls.c -- Datagram Transport Layer Support for libcoap with tinydtls
3  *
4  * Copyright (C) 2016-2020 Olaf Bergmann <bergmann@tzi.org>
5  * Copyright (C) 2020 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 "coap3/coap_internal.h"
12 
13 #ifdef HAVE_LIBTINYDTLS
14 
15 /* We want TinyDTLS versions of these, not libcoap versions */
16 #undef PACKAGE_BUGREPORT
17 #undef PACKAGE_NAME
18 #undef PACKAGE_STRING
19 #undef PACKAGE_TARNAME
20 #undef PACKAGE_URL
21 #undef PACKAGE_VERSION
22 
23 #include <tinydtls.h>
24 #include <dtls.h>
25 #include <dtls_debug.h>
26 
27 typedef struct coap_tiny_context_t {
28  struct dtls_context_t *dtls_context;
29  coap_context_t *coap_context;
30 #ifdef DTLS_ECC
31  coap_dtls_pki_t setup_data;
32  coap_binary_t *priv_key;
33  coap_binary_t *pub_key;
34 #endif /* DTLS_ECC */
35 } coap_tiny_context_t;
36 
37 static dtls_tick_t dtls_tick_0 = 0;
38 static coap_tick_t coap_tick_0 = 0;
39 
40 int
42  return 1;
43 }
44 
45 void coap_dtls_startup(void) {
46  dtls_init();
47  dtls_ticks(&dtls_tick_0);
48  coap_ticks(&coap_tick_0);
49 }
50 
51 void coap_dtls_shutdown(void) {
52 }
53 
54 void *
55 coap_dtls_get_tls(const coap_session_t *c_session,
56  coap_tls_library_t *tls_lib) {
57  if (tls_lib)
58  *tls_lib = COAP_TLS_LIBRARY_TINYDTLS;
59  if (c_session && c_session->context && c_session->context->dtls_context) {
60  const coap_tiny_context_t *t_context =
61  (const coap_tiny_context_t *)c_session->context->dtls_context;
62 
63  return t_context->dtls_context;
64  }
65  return NULL;
66 }
67 
68 void
69 coap_dtls_set_log_level(int level) {
70  dtls_set_log_level(level);
71 }
72 
73 int
75  return dtls_get_log_level();
76 }
77 
78 static void get_session_addr(const session_t *s, coap_address_t *a) {
79 #ifdef WITH_CONTIKI
80  a->addr = s->addr;
81  a->port = s->port;
82 #else
83  if (s->addr.sa.sa_family == AF_INET6) {
84  a->size = (socklen_t)sizeof(a->addr.sin6);
85  a->addr.sin6 = s->addr.sin6;
86  } else if (s->addr.sa.sa_family == AF_INET) {
87  a->size = (socklen_t)sizeof(a->addr.sin);
88  a->addr.sin = s->addr.sin;
89  } else {
90  a->size = (socklen_t)s->size;
91  a->addr.sa = s->addr.sa;
92  }
93 #endif
94 }
95 
96 static void put_session_addr(const coap_address_t *a, session_t *s) {
97 #ifdef WITH_CONTIKI
98  s->size = (unsigned char)sizeof(s->addr);
99  s->addr = a->addr;
100  s->port = a->port;
101 #else
102  if (a->addr.sa.sa_family == AF_INET6) {
103  s->size = (socklen_t)sizeof(s->addr.sin6);
104  s->addr.sin6 = a->addr.sin6;
105  } else if (a->addr.sa.sa_family == AF_INET) {
106  s->size = (socklen_t)sizeof(s->addr.sin);
107  s->addr.sin = a->addr.sin;
108  } else {
109  s->size = (socklen_t)a->size;
110  s->addr.sa = a->addr.sa;
111  }
112 #endif
113 }
114 
115 static int
116 dtls_send_to_peer(struct dtls_context_t *dtls_context,
117  session_t *dtls_session, uint8 *data, size_t len) {
118  coap_tiny_context_t *t_context =
119  (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
120  coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
121  coap_session_t *coap_session;
122  coap_address_t remote_addr;
123 
124  assert(coap_context);
125  get_session_addr(dtls_session, &remote_addr);
126  coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
127  if (!coap_session) {
128  coap_log(LOG_WARNING, "dtls_send_to_peer: cannot find local interface\n");
129  return -3;
130  }
131  return (int)coap_session_send(coap_session, data, len);
132 }
133 
134 static int
135 dtls_application_data(struct dtls_context_t *dtls_context,
136  session_t *dtls_session, uint8 *data, size_t len) {
137  coap_tiny_context_t *t_context =
138  (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
139  coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
140  coap_session_t *coap_session;
141  coap_address_t remote_addr;
142 
143  assert(coap_context);
144  get_session_addr(dtls_session, &remote_addr);
145  coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
146  if (!coap_session) {
148  "dropped message that was received on invalid interface\n");
149  return -1;
150  }
151 
152  return coap_handle_dgram(coap_context, coap_session, data, len);
153 }
154 
155 static int coap_event_dtls = 0;
156 
157 static int
158 dtls_event(struct dtls_context_t *dtls_context,
159  session_t *dtls_session,
160  dtls_alert_level_t level,
161  uint16_t code) {
162  (void)dtls_context;
163  (void)dtls_session;
164 
165  if (level == DTLS_ALERT_LEVEL_FATAL)
166  coap_event_dtls = COAP_EVENT_DTLS_ERROR;
167 
168  /* handle DTLS events */
169  switch (code) {
170  case DTLS_ALERT_CLOSE_NOTIFY:
171  {
172  coap_event_dtls = COAP_EVENT_DTLS_CLOSED;
173  break;
174  }
175  case DTLS_EVENT_CONNECTED:
176  {
177  coap_event_dtls = COAP_EVENT_DTLS_CONNECTED;
178  break;
179  }
180  case DTLS_EVENT_RENEGOTIATE:
181  {
182  coap_event_dtls = COAP_EVENT_DTLS_RENEGOTIATE;
183  break;
184  }
185  default:
186  ;
187  }
188 
189  return 0;
190 }
191 
192 /* This function is the "key store" for tinyDTLS. It is called to
193  * retrieve a key for the given identity within this particular
194  * session. */
195 static int
196 get_psk_info(struct dtls_context_t *dtls_context,
197  const session_t *dtls_session,
198  dtls_credentials_type_t type,
199  const uint8_t *id, size_t id_len,
200  unsigned char *result, size_t result_length) {
201 
202  coap_tiny_context_t *t_context =
203  (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
204  coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
205  coap_session_t *coap_session;
206  int fatal_error = DTLS_ALERT_INTERNAL_ERROR;
207  size_t identity_length;
208  uint8_t psk[128];
209  size_t psk_len = 0;
210  coap_address_t remote_addr;
211  coap_dtls_cpsk_t *setup_cdata;
212  coap_dtls_spsk_t *setup_sdata;
213  coap_bin_const_t temp;
214 
215  assert(coap_context);
216  get_session_addr(dtls_session, &remote_addr);
217  coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
218  if (!coap_session) {
219  coap_log(LOG_DEBUG, "cannot get PSK, session not found\n");
220  goto error;
221  }
222 
223  switch (type) {
224  case DTLS_PSK_IDENTITY:
225 
226  if (!coap_context || !coap_context->get_client_psk ||
227  coap_session->type != COAP_SESSION_TYPE_CLIENT)
228  goto error;
229 
230  setup_cdata = &coap_session->cpsk_setup_data;
231 
232  temp.s = id;
233  temp.length = id_len;
234  coap_session_refresh_psk_hint(coap_session, &temp);
235 
236  coap_log(LOG_DEBUG, "got psk_identity_hint: '%.*s'\n", (int)id_len, id ? (const char*)id : "");
237 
238  if (setup_cdata->validate_ih_call_back) {
239  coap_str_const_t lhint;
240  lhint.length = id_len;
241  lhint.s = id;
242  const coap_dtls_cpsk_info_t *psk_info =
243  setup_cdata->validate_ih_call_back(&lhint,
244  coap_session,
245  setup_cdata->ih_call_back_arg);
246 
247  if (psk_info == NULL)
248  return 0;
249  if (psk_info->identity.length >= result_length)
250  return 0;
251  if (psk_info->key.length > sizeof(psk))
252  return 0;
253 
254  if (coap_session->psk_identity) {
255  coap_delete_bin_const(coap_session->psk_identity);
256  }
257  identity_length = psk_info->identity.length;
258  coap_session->psk_identity = coap_new_bin_const(psk_info->identity.s, identity_length);
259  memcpy(result, psk_info->identity.s, identity_length);
260  result[identity_length] = '\000';
261 
262  coap_session_refresh_psk_key(coap_session, &psk_info->key);
263 
264  return identity_length;
265  }
266 
267  identity_length = 0;
268  /* result_length is max size of the returned identity */
269  psk_len = coap_context->get_client_psk(coap_session, (const uint8_t*)id, id_len, (uint8_t*)result, &identity_length, result_length, psk, sizeof(psk));
270  if (!psk_len) {
271  coap_log(LOG_WARNING, "no PSK identity for given realm or buffer too small\n");
272  fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
273  goto error;
274  }
275  return (int)identity_length;
276 
277  case DTLS_PSK_KEY:
278  if (coap_session->type == COAP_SESSION_TYPE_CLIENT) {
279  if (!coap_context || !coap_context->get_client_psk)
280  goto error;
281  identity_length = 0;
282  /* Use psk[] as a scratch area for returning the unused identity */
283  psk_len = coap_context->get_client_psk(coap_session, (const uint8_t*)id, id_len, psk, &identity_length, sizeof(psk), result, result_length);
284  if (!psk_len) {
285  coap_log(LOG_WARNING, "no pre-shared key for given realm or buffer too small\n");
286  fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
287  goto error;
288  }
289  return (int)psk_len;
290  }
291  if (coap_context->get_server_psk) {
292  setup_sdata = &coap_session->context->spsk_setup_data;
293 
294  if (!id)
295  id = (const uint8_t *)"";
296 
297  /* Track the Identity being used */
298  if (coap_session->psk_identity)
299  coap_delete_bin_const(coap_session->psk_identity);
300  coap_session->psk_identity = coap_new_bin_const(id, id_len);
301 
302  coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n",
303  (int)id_len, id);
304 
305  if (setup_sdata->validate_id_call_back) {
306  coap_bin_const_t lidentity;
307  lidentity.length = id_len;
308  lidentity.s = (const uint8_t*)id;
309  const coap_bin_const_t *psk_key =
310  setup_sdata->validate_id_call_back(&lidentity,
311  coap_session,
312  setup_sdata->id_call_back_arg);
313 
314  if (psk_key == NULL)
315  return 0;
316  if (psk_key->length > result_length)
317  return 0;
318  memcpy(result, psk_key->s, psk_key->length);
319  coap_session_refresh_psk_key(coap_session, psk_key);
320  return psk_key->length;
321  }
322 
323  return (int)coap_context->get_server_psk(coap_session, (const uint8_t*)id, id_len, (uint8_t*)result, result_length);
324  }
325  return 0;
326 
327  case DTLS_PSK_HINT:
328  if (coap_context->get_server_hint)
329  return (int)coap_context->get_server_hint(coap_session, (uint8_t *)result, result_length);
330  return 0;
331 
332  default:
333  coap_log(LOG_WARNING, "unsupported request type: %d\n", type);
334  }
335 
336 error:
337  return dtls_alert_fatal_create(fatal_error);
338 }
339 
340 #ifdef DTLS_ECC
341 static int
342 get_ecdsa_key(struct dtls_context_t *dtls_context,
343  const session_t *dtls_session COAP_UNUSED,
344  const dtls_ecdsa_key_t **result) {
345  static dtls_ecdsa_key_t ecdsa_key;
346  coap_tiny_context_t *t_context =
347  (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
348 
349  ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1;
350  ecdsa_key.priv_key = t_context->priv_key->s;
351  ecdsa_key.pub_key_x = t_context->pub_key->s;
352  ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE];
353 
354  *result = &ecdsa_key;
355  return 0;
356 }
357 
358 /* first part of Raw public key, the is the start of the Subject Public Key */
359 static const unsigned char cert_asn1_header[] = {
360  0x30, 0x59, /* SEQUENCE, length 89 bytes */
361  0x30, 0x13, /* SEQUENCE, length 19 bytes */
362  0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */
363  0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
364  0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */
365  0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
366  0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */
367  0x04 /* uncompressed, followed by the r and s values of the public key */
368 };
369 #define DTLS_CE_LENGTH (3 + 27 + key_size + key_size)
370 #define DTLS_EC_SUBJECTPUBLICKEY_SIZE (2 * key_size + sizeof(cert_asn1_header))
371 
372 static int
373 verify_ecdsa_key(struct dtls_context_t *dtls_context COAP_UNUSED,
374  const session_t *dtls_session COAP_UNUSED,
375  const uint8_t *other_pub_x,
376  const uint8_t *other_pub_y,
377  size_t key_size) {
378  coap_tiny_context_t *t_context =
379  (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
380  if (t_context && t_context->setup_data.validate_cn_call_back) {
381  /* Need to build asn.1 certificate - code taken from tinydtls */
382  uint8 *p;
383  uint8 buf[DTLS_CE_LENGTH];
384  coap_session_t *c_session;
385  coap_address_t remote_addr;
386 
387  /* Certificate
388  *
389  * Start message construction at beginning of buffer. */
390  p = buf;
391 
392  /* length of this certificate */
393  dtls_int_to_uint24(p, DTLS_EC_SUBJECTPUBLICKEY_SIZE);
394  p += sizeof(uint24);
395 
396  memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
397  p += sizeof(cert_asn1_header);
398 
399  memcpy(p, other_pub_x, key_size);
400  p += key_size;
401 
402  memcpy(p, other_pub_y, key_size);
403  p += key_size;
404 
405  assert(p <= (buf + sizeof(buf)));
406 
407  get_session_addr(dtls_session, &remote_addr);
408  c_session = coap_session_get_by_peer(t_context->coap_context,
409  &remote_addr, dtls_session->ifindex);
410  if (!c_session)
411  return -3;
412  if (!t_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN,
413  buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg)) {
414  return -1;
415  }
416  }
417  return 0;
418 }
419 static dtls_handler_t ec_cb = {
420  .write = dtls_send_to_peer,
421  .read = dtls_application_data,
422  .event = dtls_event,
423  .get_psk_info = NULL,
424  .get_ecdsa_key = get_ecdsa_key,
425  .verify_ecdsa_key = verify_ecdsa_key
426 };
427 #endif /* DTLS_ECC */
428 
429 static dtls_handler_t psk_cb = {
430  .write = dtls_send_to_peer,
431  .read = dtls_application_data,
432  .event = dtls_event,
433  .get_psk_info = get_psk_info,
434 #ifdef DTLS_ECC
435  .get_ecdsa_key = NULL,
436  .verify_ecdsa_key = NULL
437 #endif
438 };
439 
440 void *
441 coap_dtls_new_context(coap_context_t *coap_context) {
442  coap_tiny_context_t *t_context = coap_malloc(sizeof(coap_tiny_context_t));
443  struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL;
444  if (!dtls_context)
445  goto error;
446  memset(t_context, 0, sizeof(coap_tiny_context_t));
447  t_context->coap_context = coap_context;
448  t_context->dtls_context = dtls_context;
449  dtls_set_handler(dtls_context, &psk_cb);
450  return t_context;
451 error:
452  if (t_context)
453  coap_free(t_context);
454  if (dtls_context)
455  coap_dtls_free_context(dtls_context);
456  return NULL;
457 }
458 
459 void
460 coap_dtls_free_context(void *handle) {
461  if (handle) {
462  coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
463 #ifdef DTLS_ECC
464  if (t_context->priv_key) {
465  coap_delete_binary(t_context->priv_key);
466  t_context->priv_key = NULL;
467  }
468  if (t_context->pub_key) {
469  coap_delete_binary(t_context->pub_key);
470  t_context->pub_key = NULL;
471  }
472 #endif /* DTLS_ECC */
473  if (t_context->dtls_context)
474  dtls_free_context(t_context->dtls_context);
475  coap_free(t_context);
476  }
477 }
478 
479 static session_t *
480 coap_dtls_new_session(coap_session_t *session) {
481  session_t *dtls_session = coap_malloc_type(COAP_DTLS_SESSION, sizeof(session_t));
482 
483  if (dtls_session) {
484  /* create tinydtls session object from remote address and local
485  * endpoint handle */
486  dtls_session_init(dtls_session);
487  put_session_addr(&session->addr_info.remote, dtls_session);
488  dtls_session->ifindex = session->ifindex;
489  coap_log(LOG_DEBUG, "***new session %p\n", (void *)dtls_session);
490  }
491 
492  return dtls_session;
493 }
494 
496  return coap_dtls_new_session(session);
497 }
498 
500  dtls_peer_t *peer;
501  coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
502  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
503  session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL;
504 
505  if (!dtls_session)
506  return NULL;
507  peer =
508  dtls_get_peer(dtls_context, dtls_session);
509 
510  if (!peer) {
511  /* The peer connection does not yet exist. */
512  /* dtls_connect() returns a value greater than zero if a new
513  * connection attempt is made, 0 for session reuse. */
514  if (dtls_connect(dtls_context, dtls_session) >= 0) {
515  peer =
516  dtls_get_peer(dtls_context, dtls_session);
517  }
518  }
519 
520  if (!peer) {
521  /* delete existing session because the peer object has been invalidated */
522  coap_free_type(COAP_DTLS_SESSION, dtls_session);
523  dtls_session = NULL;
524  }
525 
526  return dtls_session;
527 }
528 
529 void
531  (void)session;
532 }
533 
534 void
535 coap_dtls_free_session(coap_session_t *coap_session) {
536  coap_tiny_context_t *t_context =
537  (coap_tiny_context_t *)coap_session->context->dtls_context;
538  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
539 
540  if (dtls_context == NULL)
541  return;
542  if (coap_session->tls && dtls_context) {
543  dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->tls);
544  if ( peer )
545  dtls_reset_peer(dtls_context, peer);
546  else
547  dtls_close(dtls_context, (session_t *)coap_session->tls);
548  coap_log(LOG_DEBUG, "***removed session %p\n", coap_session->tls);
549  coap_free_type(COAP_DTLS_SESSION, coap_session->tls);
550  coap_session->tls = NULL;
551  coap_handle_event(coap_session->context, COAP_EVENT_DTLS_CLOSED, coap_session);
552  }
553 }
554 
555 int
557  const uint8_t *data,
558  size_t data_len
559 ) {
560  int res;
561  uint8_t *data_rw;
562  coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
563  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
564 
565  assert(dtls_context);
566  coap_log(LOG_DEBUG, "call dtls_write\n");
567 
568  coap_event_dtls = -1;
569  /* Need to do this to not get a compiler warning about const parameters */
570  memcpy (&data_rw, &data, sizeof(data_rw));
571  res = dtls_write(dtls_context,
572  (session_t *)session->tls, data_rw, data_len);
573 
574  if (res < 0)
575  coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n");
576 
577  if (coap_event_dtls >= 0) {
578  /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
579  if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
580  coap_handle_event(session->context, coap_event_dtls, session);
581  if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
582  coap_session_connected(session);
583  else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
585  }
586 
587  return res;
588 }
589 
591  return 1;
592 }
593 
594 coap_tick_t coap_dtls_get_context_timeout(void *tiny_context) {
595  clock_time_t next = 0;
596  coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
597  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
598  if (tiny_context)
599  dtls_check_retransmit(dtls_context, &next);
600  if (next > 0)
601  return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND + coap_tick_0;
602  return 0;
603 }
604 
606  (void)session;
607  (void)now;
608  return 0;
609 }
610 
612  (void)session;
613  return;
614 }
615 
616 int
618  const uint8_t *data,
619  size_t data_len
620 ) {
621  session_t *dtls_session = (session_t *)session->tls;
622  int err;
623  uint8_t *data_rw;
624  coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
625  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
626 
627  assert(dtls_context);
628  coap_event_dtls = -1;
629  /* Need to do this to not get a compiler warning about const parameters */
630  memcpy (&data_rw, &data, sizeof(data_rw));
631  err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len);
632 
633  if (err){
634  coap_event_dtls = COAP_EVENT_DTLS_ERROR;
635  }
636 
637  if (coap_event_dtls >= 0) {
638  /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
639  if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
640  coap_handle_event(session->context, coap_event_dtls, session);
641  if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
642  coap_session_connected(session);
643  else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
645  }
646 
647  return err;
648 }
649 
650 int
652  const uint8_t *data,
653  size_t data_len
654 ) {
655  session_t dtls_session;
656  coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
657  dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
658  uint8_t *data_rw;
659 
660  assert(dtls_context);
661  dtls_session_init(&dtls_session);
662  put_session_addr(&session->addr_info.remote, &dtls_session);
663  dtls_session.ifindex = session->ifindex;
664  /* Need to do this to not get a compiler warning about const parameters */
665  memcpy (&data_rw, &data, sizeof(data_rw));
666  int res = dtls_handle_message(dtls_context, &dtls_session,
667  data_rw, (int)data_len);
668  if (res >= 0) {
669  if (dtls_get_peer(dtls_context, &dtls_session))
670  res = 1;
671  else
672  res = 0;
673  }
674  return res;
675 }
676 
677 unsigned int coap_dtls_get_overhead(coap_session_t *session) {
678  (void)session;
679  return 13 + 8 + 8;
680 }
681 
682 int coap_tls_is_supported(void) {
683  return 0;
684 }
685 
688  static coap_tls_version_t version;
689  const char *vers = dtls_package_version();
690 
691  version.version = 0;
692  if (vers) {
693  long int p1, p2 = 0, p3 = 0;
694  char* endptr;
695 
696  p1 = strtol(vers, &endptr, 10);
697  if (*endptr == '.') {
698  p2 = strtol(endptr+1, &endptr, 10);
699  if (*endptr == '.') {
700  p3 = strtol(endptr+1, &endptr, 10);
701  }
702  }
703  version.version = (p1 << 16) | (p2 << 8) | p3;
704  }
705  version.built_version = version.version;
707  return &version;
708 }
709 
710 #ifdef DTLS_ECC
711 static const uint8_t b64_6[256] =
712  {
713  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
714  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
715 /* + / */
716  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
717 /* 0 1 2 3 4 5 6 7 8 9 = */
718  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
719 /* A B C D E F G H I J K L M N O */
720  64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
721 /* P Q R S T U V W X Y Z */
722  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
723 /* a b c d e f g h i j k l m n o */
724  64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
725 /* p q r s t u v w x y z */
726  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
727  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
728  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
729  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
730  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
731  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
732  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
733  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
734  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
735  };
736 
737 /* caller must free off returned coap_binary_t* */
738 static coap_binary_t *
739 pem_base64_decode (const uint8_t *data, size_t size)
740 {
741  uint8_t *tbuf = coap_malloc(size);
742  size_t nbytesdecoded;
743  size_t i;
744  coap_binary_t *decoded;
745  uint8_t *ptr;
746  uint8_t *out;
747  size_t nb64bytes = 0;
748 
749  for (i = 0; i < size; i++) {
750  switch (data[i]) {
751  case ' ':
752  case '\r':
753  case '\n':
754  case '\t':
755  break;
756  default:
757  if (b64_6[data[i]] == 64)
758  goto end;
759  tbuf[nb64bytes++] = data[i];
760  break;
761  }
762  }
763 
764 end:
765  nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
766  decoded = coap_new_binary(nbytesdecoded + 1);
767  if (!decoded)
768  return NULL;
769 
770  out = decoded->s;
771  ptr = tbuf;
772 
773  while (nb64bytes > 4) {
774  *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
775  *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
776  *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
777  ptr += 4;
778  nb64bytes -= 4;
779  }
780 
781  /* Note: (nb64bytes == 1) is an error */
782  if (nb64bytes > 1) {
783  *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
784  }
785  if (nb64bytes > 2) {
786  *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
787  }
788  if (nb64bytes > 3) {
789  *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
790  }
791 
792  decoded->length = nbytesdecoded - ((4 - nb64bytes) & 3);
793  coap_free(tbuf);
794  return decoded;
795 }
796 
797 typedef coap_binary_t * (*asn1_callback)(const uint8_t *data, size_t size);
798 
799 static int
800 asn1_verify_privkey(const uint8_t *data, size_t size)
801 {
802  /* Check if we have the private key (with optional leading 0x00) */
803  /* skip leading 0x00 */
804  if (size - 1 == DTLS_EC_KEY_SIZE && *data == '\000') {
805  --size;
806  ++data;
807  }
808 
809  /* Check if we have the private key */
810  if (size != DTLS_EC_KEY_SIZE)
811  return 0;
812 
813  return 1;
814 }
815 
816 static int
817 asn1_verify_pubkey(const uint8_t *data, size_t size)
818 {
819  (void)data;
820 
821  /* We have the public key
822  (with a leading 0x00 (no unused bits) 0x04 (not compressed() */
823  if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
824  return 0;
825 
826  return 1;
827 }
828 
829 static int
830 asn1_verify_curve(const uint8_t *data, size_t size)
831 {
832  static uint8_t prime256v1_oid[] =
833  /* OID 1.2.840.10045.3.1.7 */
834  { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
835 
836  /* Check that we have the correct EC (only one supported) */
837  if (size != sizeof(prime256v1_oid) ||
838  memcmp(data, prime256v1_oid, size) != 0)
839  return 0;
840 
841  return 1;
842 }
843 
844 static int
845 asn1_verify_pkcs8_version(const uint8_t *data, size_t size)
846 {
847  /* Check that we have the version */
848  if (size != 1 || *data != 0)
849  return 0;
850 
851  return 1;
852 }
853 
854 static int
855 asn1_verify_ec_identifier(const uint8_t *data, size_t size)
856 {
857  static uint8_t ec_public_key_oid[] =
858  /* OID 1.2.840.10045.2.1 */
859  { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
860 
861  /* Check that we have the correct ecPublicKey */
862  if (size != sizeof(ec_public_key_oid) ||
863  memcmp(data, ec_public_key_oid, size) != 0)
864  return 0;
865 
866  return 1;
867 }
868 
869 static int
870 asn1_verify_ec_key(const uint8_t *data, size_t size)
871 {
872  (void)data;
873 
874  if (size == 0)
875  return 0;
876 
877  return 1;
878 }
879 
880 static int
881 asn1_derive_keys(coap_tiny_context_t *t_context,
882  const uint8_t *priv_data, size_t priv_len,
883  const uint8_t *pub_data, size_t pub_len,
884  int is_pkcs8)
885 {
886  coap_binary_t *test;
887 
888  t_context->priv_key = get_asn1_tag(COAP_ASN1_OCTETSTRING, priv_data,
889  priv_len, asn1_verify_privkey);
890  if (!t_context->priv_key) {
891  coap_log(LOG_INFO, "EC Private Key (RPK) invalid\n");
892  return 0;
893  }
894  /* skip leading 0x00 */
895  if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
896  t_context->priv_key->s[0] == '\000') {
897  t_context->priv_key->length--;
898  t_context->priv_key->s++;
899  }
900 
901  if (!is_pkcs8) {
902  /* pkcs8 abstraction tested for valid eliptic curve */
903  test = get_asn1_tag(COAP_ASN1_IDENTIFIER, priv_data, priv_len,
904  asn1_verify_curve);
905  if (!test) {
906  coap_log(LOG_INFO, "EC Private Key (RPK) invalid elliptic curve\n");
907  coap_delete_binary(t_context->priv_key);
908  t_context->priv_key = NULL;
909  return 0;
910  }
911  coap_delete_binary(test);
912  }
913 
914  t_context->pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, pub_data, pub_len,
915  asn1_verify_pubkey);
916  if (!t_context->pub_key) {
917  coap_log(LOG_INFO, "EC Public Key (RPK) invalid\n");
918  coap_delete_binary(t_context->priv_key);
919  t_context->priv_key = NULL;
920  return 0;
921  }
922  /* Drop leading 0x00 and 0x04 */
923  t_context->pub_key->s += 2;
924  t_context->pub_key->length -= 2;
925  dtls_set_handler(t_context->dtls_context, &ec_cb);
926  return 1;
927 }
928 
929 static coap_binary_t *
930 ec_abstract_pkcs8_asn1(const uint8_t *asn1_ptr, size_t asn1_length)
931 {
932  coap_binary_t *test;
933 
934  test = get_asn1_tag(COAP_ASN1_INTEGER, asn1_ptr, asn1_length,
935  asn1_verify_pkcs8_version);
936  if (!test)
937  return 0;
938 
939  coap_delete_binary(test);
940 
941  test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
942  asn1_verify_ec_identifier);
943  if (!test)
944  return 0;
945  coap_delete_binary(test);
946 
947  test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
948  asn1_verify_curve);
949  if (!test) {
950  coap_log(LOG_INFO, "EC Private Key (RPK) invalid elliptic curve\n");
951  return 0;
952  }
953  coap_delete_binary(test);
954 
955  test = get_asn1_tag(COAP_ASN1_OCTETSTRING, asn1_ptr, asn1_length,
956  asn1_verify_ec_key);
957  return test;
958 }
959 
960 static coap_binary_t *
961 pem_decode_mem_asn1(const char *begstr, const uint8_t *str)
962 {
963  char *bcp = str ? strstr((const char*)str, begstr) : NULL;
964  char *tcp = bcp ? strstr(bcp, "-----END ") : NULL;
965 
966  if (bcp && tcp) {
967  bcp += strlen(begstr);
968  return pem_base64_decode ((const uint8_t *)bcp, tcp - bcp);
969  }
970  return NULL;
971 }
972 
973 #endif /* DTLS_ECC */
974 
975 int
977  const coap_dtls_pki_t* setup_data,
978  const coap_dtls_role_t role COAP_UNUSED
979 ) {
980 #ifdef DTLS_ECC
981  coap_tiny_context_t *t_context;
982  coap_binary_t *asn1_priv;
983  coap_binary_t *asn1_pub;
984  coap_binary_t *asn1_temp;
985  int is_pkcs8 = 0;
986 
987  if (!setup_data)
988  return 0;
989  if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION)
990  return 0;
991  if (!setup_data->is_rpk_not_cert) {
992  coap_log(LOG_WARNING, "Only RPK, not full PKI is supported\n");
993  return 0;
994  }
995  if (!ctx)
996  return 0;
997  t_context = (coap_tiny_context_t *)ctx->dtls_context;
998  if (!t_context)
999  return 0;
1000  if (t_context->priv_key) {
1001  coap_delete_binary(t_context->priv_key);
1002  t_context->priv_key = NULL;
1003  }
1004  if (t_context->pub_key) {
1005  coap_delete_binary(t_context->pub_key);
1006  t_context->pub_key = NULL;
1007  }
1008  t_context->setup_data = *setup_data;
1009 
1010  /* All should be RPK only now */
1011  switch (setup_data->pki_key.key_type) {
1012  case COAP_PKI_KEY_PEM:
1013  coap_log(LOG_WARNING, "RPK keys cannot be in COAP_PKI_KEY_PEM format\n");
1014  break;
1015  case COAP_PKI_KEY_PEM_BUF:
1016  if (setup_data->pki_key.key.pem_buf.public_cert &&
1017  setup_data->pki_key.key.pem_buf.public_cert[0] &&
1018  setup_data->pki_key.key.pem_buf.private_key &&
1019  setup_data->pki_key.key.pem_buf.private_key[0]) {
1020  /* Need to take PEM memory information and convert to binary */
1021  asn1_priv = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1022  setup_data->pki_key.key.pem_buf.private_key);
1023  if (!asn1_priv) {
1024  asn1_priv = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1025  setup_data->pki_key.key.pem_buf.private_key);
1026  if (!asn1_priv) {
1027  coap_log(LOG_INFO, "Private Key (RPK) invalid\n");
1028  return 0;
1029  }
1030  asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->s, asn1_priv->length);
1031  if (!asn1_temp) {
1032  coap_log(LOG_INFO, "PKCS#8 Private Key (RPK) invalid\n");
1033  coap_delete_binary(asn1_priv);
1034  return 0;
1035  }
1036  coap_delete_binary(asn1_priv);
1037  asn1_priv = asn1_temp;
1038  is_pkcs8 = 1;
1039  }
1040  asn1_pub = pem_decode_mem_asn1(
1041  "-----BEGIN PUBLIC KEY-----",
1042  setup_data->pki_key.key.pem_buf.public_cert);
1043  if (!asn1_pub) {
1044  asn1_pub = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1045  setup_data->pki_key.key.pem_buf.private_key);
1046  if (!asn1_pub) {
1047  asn1_pub = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1048  setup_data->pki_key.key.pem_buf.private_key);
1049  if (!asn1_pub) {
1050  coap_log(LOG_INFO, "Public Key (RPK) invalid\n");
1051  coap_delete_binary(asn1_priv);
1052  return 0;
1053  }
1054  asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->s, asn1_pub->length);
1055  if (!asn1_temp) {
1056  coap_log(LOG_INFO, "PKCS#8 Private Key (RPK) invalid\n");
1057  coap_delete_binary(asn1_priv);
1058  coap_delete_binary(asn1_pub);
1059  return 0;
1060  }
1061  coap_delete_binary(asn1_pub);
1062  asn1_pub = asn1_temp;
1063  is_pkcs8 = 1;
1064  }
1065  }
1066  if (!asn1_derive_keys(t_context, asn1_priv->s, asn1_priv->length,
1067  asn1_pub->s, asn1_pub->length, is_pkcs8)) {
1068  coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n");
1069  coap_delete_binary(asn1_priv);
1070  coap_delete_binary(asn1_pub);
1071  return 0;
1072  }
1073  coap_delete_binary(asn1_priv);
1074  coap_delete_binary(asn1_pub);
1075  return 1;
1076  }
1077  break;
1078  case COAP_PKI_KEY_ASN1:
1079  if (setup_data->pki_key.key.asn1.private_key &&
1080  setup_data->pki_key.key.asn1.private_key_len &&
1082  const uint8_t* private_key = setup_data->pki_key.key.asn1.private_key;
1083  size_t private_key_len = setup_data->pki_key.key.asn1.private_key_len;
1084 
1085  /* Check to see whether this is in pkcs8 format or not */
1086  asn1_temp = ec_abstract_pkcs8_asn1(
1087  setup_data->pki_key.key.asn1.private_key,
1088  setup_data->pki_key.key.asn1.private_key_len);
1089  if (asn1_temp) {
1090  private_key = asn1_temp->s;
1091  private_key_len = asn1_temp->length;
1092  is_pkcs8 = 1;
1093  }
1094  /* Need to take ASN1 memory information and convert to binary */
1095  if (setup_data->pki_key.key.asn1.public_cert &&
1096  setup_data->pki_key.key.asn1.public_cert_len) {
1097  if (!asn1_derive_keys(t_context,
1098  private_key,
1099  private_key_len,
1100  setup_data->pki_key.key.asn1.public_cert,
1101  setup_data->pki_key.key.asn1.public_cert_len,
1102  is_pkcs8)) {
1103  coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n");
1104  if (asn1_temp) coap_delete_binary(asn1_temp);
1105  return 0;
1106  }
1107  }
1108  else {
1109  if (!asn1_derive_keys(t_context,
1110  private_key,
1111  private_key_len,
1112  private_key,
1113  private_key_len,
1114  is_pkcs8)) {
1115  coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n");
1116  if (asn1_temp) coap_delete_binary(asn1_temp);
1117  return 0;
1118  }
1119  }
1120  return 1;
1121  }
1122  break;
1123  case COAP_PKI_KEY_PKCS11:
1124  coap_log(LOG_WARNING, "RPK keys cannot be in COAP_PKI_KEY_PCKS11 format\n");
1125  break;
1126  default:
1127  break;
1128  }
1129 #else /* ! DTLS_ECC */
1130  (void)ctx;
1131  (void)setup_data;
1132 #endif /* ! DTLS_ECC */
1133  return 0;
1134 }
1135 
1136 int
1138  const char *ca_file COAP_UNUSED,
1139  const char *ca_path COAP_UNUSED
1140 ) {
1141  coap_log(LOG_WARNING, "Root CAs PKI not supported\n");
1142  return 0;
1143 }
1144 
1145 int
1147  coap_dtls_cpsk_t *setup_data
1148 ) {
1149  if (!setup_data)
1150  return 0;
1151 
1152  return 1;
1153 }
1154 
1155 int
1157  coap_dtls_spsk_t *setup_data
1158 ) {
1159  if (!setup_data)
1160  return 0;
1161 
1162  if (setup_data->validate_sni_call_back) {
1164  "CoAP Server with TinyDTLS does not support SNI selection\n");
1165  }
1166 
1167  return 1;
1168 }
1169 
1170 int
1172 {
1173  return 1;
1174 }
1175 
1176 #if !COAP_DISABLE_TCP
1177 void *coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) {
1178  return NULL;
1179 }
1180 
1181 void *coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) {
1182  return NULL;
1183 }
1184 
1185 void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED) {
1186 }
1187 
1188 ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED,
1189  const uint8_t *data COAP_UNUSED,
1190  size_t data_len COAP_UNUSED
1191 ) {
1192  return -1;
1193 }
1194 
1195 ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED,
1196  uint8_t *data COAP_UNUSED,
1197  size_t data_len COAP_UNUSED
1198 ) {
1199  return -1;
1200 }
1201 #endif /* !COAP_DISABLE_TCP */
1202 
1204 coap_digest_setup(void) {
1205  dtls_sha256_ctx *digest_ctx = coap_malloc(sizeof(dtls_sha256_ctx));
1206 
1207  if (digest_ctx) {
1208  dtls_sha256_init(digest_ctx);
1209  }
1210 
1211  return digest_ctx;
1212 }
1213 
1214 void
1215 coap_digest_free(coap_digest_ctx_t *digest_ctx) {
1216  coap_free(digest_ctx);
1217 }
1218 
1219 int
1221  const uint8_t *data,
1222  size_t data_len) {
1223  dtls_sha256_update(digest_ctx, data, data_len);
1224 
1225  return 1;
1226 }
1227 
1228 int
1230  coap_digest_t *digest_buffer) {
1231  dtls_sha256_final((uint8_t*)digest_buffer, digest_ctx);
1232 
1233  coap_digest_free(digest_ctx);
1234  return 1;
1235 }
1236 
1237 #else /* !HAVE_LIBTINYDTLS */
1238 
1239 #ifdef __clang__
1240 /* Make compilers happy that do not like empty modules. As this function is
1241  * never used, we ignore -Wunused-function at the end of compiling this file
1242  */
1243 #pragma GCC diagnostic ignored "-Wunused-function"
1244 #endif
1245 static inline void dummy(void) {
1246 }
1247 
1248 #endif /* HAVE_LIBTINYDTLS */
Pulls together all the internal only header files.
@ COAP_NACK_TLS_FAILED
Definition: coap_io.h:66
void * coap_dtls_new_server_session(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:103
int coap_dtls_context_set_spsk(coap_context_t *ctx COAP_UNUSED, coap_dtls_spsk_t *setup_data COAP_UNUSED)
Definition: coap_notls.c:56
void coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:138
int coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, const coap_dtls_pki_t *setup_data COAP_UNUSED, const coap_dtls_role_t role COAP_UNUSED)
Definition: coap_notls.c:33
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition: coap_notls.c:134
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition: coap_notls.c:95
int coap_dtls_send(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:118
void * coap_dtls_new_client_session(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:107
ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED, uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:179
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition: coap_notls.c:129
int coap_dtls_receive(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:142
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:157
void * coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:161
void * coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:165
int coap_dtls_hello(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:150
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition: coap_notls.c:63
int coap_dtls_context_set_cpsk(coap_context_t *ctx COAP_UNUSED, coap_dtls_cpsk_t *setup_data COAP_UNUSED)
Definition: coap_notls.c:49
ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:172
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:114
int coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED, const char *ca_file COAP_UNUSED, const char *ca_path COAP_UNUSED)
Definition: coap_notls.c:41
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition: coap_notls.c:100
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:111
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition: coap_notls.c:74
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:169
coap_session_t * coap_session_get_by_peer(const coap_context_t *ctx, const coap_address_t *remote_addr, int ifindex)
static void dummy(void)
coap_binary_t * get_asn1_tag(coap_asn1_tag_t ltag, const uint8_t *ptr, size_t tlen, asn1_validate validate)
Get the asn1 tag and data from the current ptr.
Definition: coap_asn1.c:61
@ COAP_ASN1_OCTETSTRING
@ COAP_ASN1_INTEGER
@ COAP_ASN1_BITSTRING
@ COAP_ASN1_IDENTIFIER
void coap_digest_free(coap_digest_ctx_t *digest_ctx)
Free off coap_digest_ctx_t.
Definition: coap_notls.c:203
coap_digest_ctx_t * coap_digest_setup(void)
Initialize a coap_digest.
Definition: coap_notls.c:192
int coap_digest_final(coap_digest_ctx_t *digest_ctx, coap_digest_t *digest_buffer)
Finalize the coap_digest information into the provided digest_buffer.
Definition: coap_notls.c:220
int coap_digest_update(coap_digest_ctx_t *digest_ctx, const uint8_t *data, size_t data_len)
Update the coap_digest information with the next chunk of data.
Definition: coap_notls.c:208
void coap_digest_ctx_t
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:120
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition: coap_time.h:135
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:1898
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:3155
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition: coap_notls.c:70
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition: coap_notls.c:125
void coap_dtls_shutdown(void)
Close down the underlying (D)TLS Library layer.
Definition: coap_notls.c:81
coap_dtls_role_t
Definition: coap_dtls.h:27
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition: coap_notls.c:20
#define COAP_DTLS_PKI_SETUP_VERSION
Latest PKI setup version.
Definition: coap_dtls.h:235
#define COAP_DTLS_RPK_CERT_CN
Definition: coap_dtls.h:32
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:25
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_notls.c:15
coap_tls_library_t
Definition: coap_dtls.h:48
@ COAP_PKI_KEY_PKCS11
The PKI key type is PKCS11 (DER)
Definition: coap_dtls.h:148
@ COAP_PKI_KEY_PEM_BUF
The PKI key type is PEM buffer.
Definition: coap_dtls.h:147
@ COAP_PKI_KEY_PEM
The PKI key type is PEM file.
Definition: coap_dtls.h:145
@ COAP_PKI_KEY_ASN1
The PKI key type is ASN.1 (DER) buffer.
Definition: coap_dtls.h:146
@ COAP_ASN1_PKEY_EC
EC type.
Definition: coap_dtls.h:134
@ COAP_TLS_LIBRARY_TINYDTLS
Using TinyDTLS library.
Definition: coap_dtls.h:50
#define COAP_EVENT_DTLS_RENEGOTIATE
Definition: coap_event.h:32
#define COAP_EVENT_DTLS_ERROR
Definition: coap_event.h:33
#define COAP_EVENT_DTLS_CLOSED
(D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
Definition: coap_event.h:30
#define COAP_EVENT_DTLS_CONNECTED
Definition: coap_event.h:31
void coap_dtls_set_log_level(int level)
Sets the (D)TLS logging level to the specified level.
Definition: coap_notls.c:85
int coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition: coap_notls.c:90
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:150
@ LOG_INFO
Information.
Definition: coap_debug.h:56
@ LOG_WARNING
Warning.
Definition: coap_debug.h:54
@ LOG_DEBUG
Debug.
Definition: coap_debug.h:57
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
Definition: coap_session.c:997
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:275
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
Definition: coap_session.c:397
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:454
@ COAP_SESSION_TYPE_CLIENT
client-side
Definition: coap_session.h:41
void coap_delete_bin_const(coap_bin_const_t *s)
Deletes the given const binary data and releases any memory allocated.
Definition: str.c:102
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition: str.c:89
coap_bin_const_t * coap_new_bin_const(const uint8_t *data, size_t size)
Take the specified byte array (text) and create a coap_bin_const_t * Returns a new const binary objec...
Definition: str.c:93
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition: str.c:65
#define COAP_UNUSED
Definition: libcoap.h:53
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
COAP_STATIC_INLINE void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
Definition: mem.h:96
COAP_STATIC_INLINE void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:103
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
coap_address_t remote
remote address and port
Definition: coap_io.h:49
multi-purpose address abstraction
Definition: address.h:94
socklen_t size
size of addr
Definition: address.h:95
struct sockaddr_in sin
Definition: address.h:98
struct sockaddr_in6 sin6
Definition: address.h:99
struct sockaddr sa
Definition: address.h:97
union coap_address_t::@0 addr
CoAP binary data definition with const data.
Definition: str.h:56
size_t length
length of binary data
Definition: str.h:57
const uint8_t * s
read-only binary data
Definition: str.h:58
CoAP binary data definition.
Definition: str.h:48
size_t length
length of binary data
Definition: str.h:49
uint8_t * s
binary data
Definition: str.h:50
The CoAP stack's global state is stored in a coap_context_t object.
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)
size_t(* get_server_hint)(const coap_session_t *session, uint8_t *hint, size_t max_hint_len)
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)
coap_dtls_spsk_t spsk_setup_data
Contains the initial PSK server setup data.
The structure that holds the Client PSK information.
Definition: coap_dtls.h:303
coap_bin_const_t key
Definition: coap_dtls.h:305
coap_bin_const_t identity
Definition: coap_dtls.h:304
The structure used for defining the Client PSK setup data to be used.
Definition: coap_dtls.h:334
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition: coap_dtls.h:355
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition: coap_dtls.h:354
union coap_dtls_key_t::@2 key
coap_pki_key_pem_buf_t pem_buf
for PEM memory keys
Definition: coap_dtls.h:212
coap_pki_key_t key_type
key format type
Definition: coap_dtls.h:209
coap_pki_key_asn1_t asn1
for ASN.1 (DER) memory keys
Definition: coap_dtls.h:213
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:240
uint8_t version
Definition: coap_dtls.h:241
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition: coap_dtls.h:258
coap_dtls_key_t pki_key
PKI key definition.
Definition: coap_dtls.h:297
The structure used for defining the Server PSK setup data to be used.
Definition: coap_dtls.h:421
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition: coap_dtls.h:448
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition: coap_dtls.h:440
void * id_call_back_arg
Passed in to the Identity callback function.
Definition: coap_dtls.h:441
const uint8_t * private_key
ASN1 (DER) Private Key.
Definition: coap_dtls.h:186
coap_asn1_privatekey_type_t private_key_type
Private Key Type.
Definition: coap_dtls.h:190
size_t public_cert_len
ASN1 Public Cert length.
Definition: coap_dtls.h:188
size_t private_key_len
ASN1 Private Key length.
Definition: coap_dtls.h:189
const uint8_t * public_cert
ASN1 (DER) Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:185
const uint8_t * private_key
PEM buffer Private Key If RPK and 'EC PRIVATE KEY' this can be used for both the public_cert and priv...
Definition: coap_dtls.h:172
const uint8_t * public_cert
PEM buffer Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:171
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_bin_const_t * psk_identity
If client, this field contains the current identity for server; When this field is NULL,...
coap_addr_tuple_t addr_info
key: remote/local address info
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
void * tls
security parameters
coap_session_type_t type
client or server side socket
coap_context_t * context
session's context
int ifindex
interface index
CoAP string data definition with const data.
Definition: str.h:38
const uint8_t * s
read-only string data
Definition: str.h:40
size_t length
length of string
Definition: str.h:39
The structure used for returning the underlying (D)TLS library information.
Definition: coap_dtls.h:60
uint64_t built_version
(D)TLS Built against Library Version
Definition: coap_dtls.h:63
coap_tls_library_t type
Library type.
Definition: coap_dtls.h:62
uint64_t version
(D)TLS runtime Library Version
Definition: coap_dtls.h:61