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