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