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