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