libcoap 4.3.5rc1
Loading...
Searching...
No Matches
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-2024 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
19
20#ifdef COAP_WITH_LIBTINYDTLS
21
22/* We want TinyDTLS versions of these, not libcoap versions */
23#undef PACKAGE_BUGREPORT
24#undef PACKAGE_NAME
25#undef PACKAGE_STRING
26#undef PACKAGE_TARNAME
27#undef PACKAGE_URL
28#undef PACKAGE_VERSION
29
30#ifndef RIOT_VERSION
31#include <tinydtls/tinydtls.h>
32#include <tinydtls/dtls.h>
33#include <tinydtls/dtls_debug.h>
34#include <tinydtls/dtls_time.h>
35#else /* RIOT_VERSION */
36#include <tinydtls.h>
37#include <dtls.h>
38#include <dtls_debug.h>
39#include <dtls_time.h>
40#endif /* RIOT_VERSION */
41
42typedef struct coap_tiny_context_t {
43 struct dtls_context_t *dtls_context;
44 coap_context_t *coap_context;
45#ifdef DTLS_ECC
46 coap_dtls_pki_t setup_data;
47 coap_binary_t *priv_key;
48 coap_binary_t *pub_key;
49#endif /* DTLS_ECC */
50} coap_tiny_context_t;
51
52#if ! defined(DTLS_PSK) && ! defined(DTLS_ECC)
53#error Neither DTLS_PSK or DTLS_ECC defined
54#endif /* ! DTLS_PSK && ! DTLS_ECC */
55
56static dtls_tick_t dtls_tick_0 = 0;
57static coap_tick_t coap_tick_0 = 0;
58
59int
61 return 1;
62}
63
64/*
65 * return 0 failed
66 * 1 passed
67 */
68int
70#ifdef DTLS_PSK
71 return 1;
72#else /* ! DTLS_PSK */
73 return 0;
74#endif /* ! DTLS_PSK */
75}
76
77/*
78 * return 0 failed
79 * 1 passed
80 */
81int
83 return 0;
84}
85
86/*
87 * return 0 failed
88 * 1 passed
89 */
90int
92 return 0;
93}
94
95/*
96 * return 0 failed
97 * 1 passed
98 */
99int
101#ifdef DTLS_ECC
102 return 1;
103#else /* ! DTLS_ECC */
104 return 0;
105#endif /* ! DTLS_ECC */
106}
107
108static coap_log_t
109dtls_map_logging(log_t d_level) {
110 /* DTLS_LOG_ERR is missing, so account for the gap */
111 switch (d_level) {
112 case DTLS_LOG_EMERG:
113 return COAP_LOG_EMERG;
114 break;
115 case DTLS_LOG_ALERT:
116 return COAP_LOG_ALERT;
117 break;
118 case DTLS_LOG_CRIT:
119 return COAP_LOG_CRIT;
120 break;
121 case DTLS_LOG_WARN:
122 return COAP_LOG_WARN;
123 break;
124 case DTLS_LOG_NOTICE:
125 return COAP_LOG_NOTICE;
126 break;
127 case DTLS_LOG_INFO:
128 return COAP_LOG_INFO;
129 break;
130 case DTLS_LOG_DEBUG:
131 default:
132 return COAP_LOG_DEBUG;
133 break;
134 }
135 return COAP_LOG_DEBUG;
136}
137#ifdef HAVE_DTLS_SET_LOG_HANDLER
138/* Valid after TinyDTLS submodule has been updated */
139static void
140dtls_logging(log_t d_level, const char *message) {
141 coap_log_t c_level = dtls_map_logging(d_level);
142
143 coap_dtls_log(c_level, "%s", message);
144}
145#endif /* HAVE_DTLS_SET_LOG_HANDLER */
146
147void
148coap_dtls_startup(void) {
149 dtls_init();
150 dtls_ticks(&dtls_tick_0);
151 coap_ticks(&coap_tick_0);
152#ifdef HAVE_DTLS_SET_LOG_HANDLER
153 /* Valid after TinyDTLS submodule has been updated */
154 dtls_set_log_handler(dtls_logging);
155#endif /* HAVE_DTLS_SET_LOG_HANDLER */
157}
158
159void
160coap_dtls_shutdown(void) {
162}
163
164void *
165coap_dtls_get_tls(const coap_session_t *c_session,
166 coap_tls_library_t *tls_lib) {
167 if (tls_lib)
168 *tls_lib = COAP_TLS_LIBRARY_TINYDTLS;
169 if (c_session && c_session->context && c_session->context->dtls_context) {
170 const coap_tiny_context_t *t_context =
171 (const coap_tiny_context_t *)c_session->context->dtls_context;
172
173 return t_context->dtls_context;
174 }
175 return NULL;
176}
177
178void
180 log_t d_level;
181
182 /* DTLS_LOG_ERR is missing, so account for the gap */
183 switch (c_level) {
184 case COAP_LOG_EMERG:
185 d_level = DTLS_LOG_EMERG;
186 break;
187 case COAP_LOG_ALERT:
188 d_level = DTLS_LOG_ALERT;
189 break;
190 case COAP_LOG_CRIT:
191 case COAP_LOG_ERR:
192 d_level = DTLS_LOG_CRIT;
193 break;
194 case COAP_LOG_WARN:
195 d_level = DTLS_LOG_WARN;
196 break;
197 case COAP_LOG_NOTICE:
198 d_level = DTLS_LOG_NOTICE;
199 break;
200 case COAP_LOG_INFO:
201 d_level = DTLS_LOG_INFO;
202 break;
203 case COAP_LOG_DEBUG:
204 case COAP_LOG_OSCORE:
206 default:
207 d_level = DTLS_LOG_DEBUG;
208 break;
209 }
210 dtls_set_log_level(d_level);
211}
212
215 log_t d_level = dtls_get_log_level();
216
217 return dtls_map_logging(d_level);
218}
219
220static void
221get_session_addr(const session_t *s, coap_address_t *a) {
222#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
223#if LWIP_SOCKET
224 memset(&a->addr, 0, sizeof(a->addr));
225 switch (s->addr.sa.sa_family) {
226#if LWIP_IPV4
227 case AF_INET:
228 memcpy(&a->addr, &s->addr.sin.sin_addr, sizeof(s->addr.sin.sin_addr));
229 a->port = s->addr.sin.sin_port;
230 break;
231#endif /* LWIP_IPV4 */
232#if LWIP_IPV6
233 case AF_INET6:
234 memcpy(&a->addr, &s->addr.sin6.sin6_addr, sizeof(s->addr.sin6.sin6_addr));
235 a->port = s->addr.sin6.sin6_port;
236 break;
237#endif /* LWIP_IPV6 */
238 default:
239 break;
240 }
241#else /* ! LWIP_SOCKET */
242 a->addr = s->addr;
243 a->port = s->port;
244#endif /* ! LWIP_SOCKET */
245#elif defined(WITH_RIOT_SOCK)
246 if (s->addr.family == AF_INET6) {
247 a->riot.family = s->addr.family;
248 memcpy(&a->riot.addr.ipv6, &s->addr.ipv6,
249 sizeof(a->riot.addr.ipv6));
250 a->riot.port = ntohs(s->addr.port);
251 a->riot.netif = 0;
252#ifdef SOCK_HAS_IPV4
253 } else if (s->addr.family == AF_INET) {
254 a->riot.family = s->addr.family;
255 memcpy(&a->riot.addr.ipv4, &s->addr.ipv4, sizeof(a->riot.addr.ipv4));
256 a->riot.port = ntohs(s->addr.port);
257 a->riot.netif = 0;
258#endif /* SOCK_HAS_IPV4 */
259 }
260#else /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
261 if (s->addr.sa.sa_family == AF_INET6) {
262 a->size = (socklen_t)sizeof(a->addr.sin6);
263 a->addr.sin6 = s->addr.sin6;
264 } else if (s->addr.sa.sa_family == AF_INET) {
265 a->size = (socklen_t)sizeof(a->addr.sin);
266 a->addr.sin = s->addr.sin;
267 } else {
268 a->size = (socklen_t)s->size;
269 a->addr.sa = s->addr.sa;
270 }
271#endif /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
272}
273
274static void
275put_session_addr(const coap_address_t *a, session_t *s) {
276#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
277#if LWIP_SOCKET
278#if LWIP_IPV6 && LWIP_IPV4
279 if (a->addr.type == IPADDR_TYPE_V6) {
280 s->addr.sa.sa_family = AF_INET6;
281 s->size = (socklen_t)sizeof(s->addr.sin6);
282 memcpy(&s->addr.sin6.sin6_addr, &a->addr, sizeof(s->addr.sin6.sin6_addr));
283 s->addr.sin6.sin6_port = a->port;
284 } else if (a->addr.type == IPADDR_TYPE_V4) {
285 s->addr.sa.sa_family = AF_INET;
286 s->size = (socklen_t)sizeof(s->addr.sin);
287 memcpy(&s->addr.sin.sin_addr, &a->addr, sizeof(s->addr.sin.sin_addr));
288 s->addr.sin.sin_port = a->port;
289 }
290#else /* ! LWIP_IPV6 || ! LWIP_IPV4 */
291#endif /* ! LWIP_IPV6 || ! LWIP_IPV4 */
292#else /* ! LWIP_SOCKET */
293 s->size = (unsigned char)sizeof(s->addr);
294 s->addr = a->addr;
295 s->port = a->port;
296#endif /* ! LWIP_SOCKET */
297#elif defined(WITH_RIOT_SOCK)
298 if (a->riot.family == AF_INET6) {
299 s->size = sizeof(s->addr.ipv6);
300 s->addr.family = a->riot.family;
301 memcpy(&s->addr.ipv6, &a->riot.addr.ipv6,
302 sizeof(s->addr.ipv6));
303 s->addr.port = htons(a->riot.port);
304#ifdef SOCK_HAS_IPV4
305 } else if (a->r.family == AF_INET) {
306 s->size = sizeof(s->addr.ipv4);
307 s->addr.family = a->r.family;
308 memcpy(&a->addr.ipv4, &s->r.addr.ipv4, sizeof(a->addr.ipv4));
309 s->addr.port = htons(a->r.port);
310#endif /* SOCK_HAS_IPV4 */
311 }
312#else /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
313 if (a->addr.sa.sa_family == AF_INET6) {
314 s->size = (socklen_t)sizeof(s->addr.sin6);
315 s->addr.sin6 = a->addr.sin6;
316 } else if (a->addr.sa.sa_family == AF_INET) {
317 s->size = (socklen_t)sizeof(s->addr.sin);
318 s->addr.sin = a->addr.sin;
319 } else {
320 s->size = (socklen_t)a->size;
321 s->addr.sa = a->addr.sa;
322 }
323#endif /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
324}
325
326static int
327dtls_send_to_peer(struct dtls_context_t *dtls_context,
328 session_t *dtls_session, uint8 *data, size_t len) {
329 coap_tiny_context_t *t_context =
330 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
331 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
332 coap_session_t *coap_session;
333 coap_address_t remote_addr;
334
335 assert(coap_context);
336 get_session_addr(dtls_session, &remote_addr);
337 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
338 if (!coap_session) {
339 coap_log_warn("dtls_send_to_peer: cannot find local interface\n");
340 return -3;
341 }
342 return (int)coap_session->sock.lfunc[COAP_LAYER_TLS].l_write(coap_session,
343 data, len);
344}
345
346static int
347dtls_application_data(struct dtls_context_t *dtls_context,
348 session_t *dtls_session, uint8 *data, size_t len) {
349 coap_tiny_context_t *t_context =
350 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
351 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
352 coap_session_t *coap_session;
353 coap_address_t remote_addr;
354
355 assert(coap_context);
356 get_session_addr(dtls_session, &remote_addr);
357 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
358 if (!coap_session) {
359 coap_log_debug("dropped message that was received on invalid interface\n");
360 return -1;
361 }
362
363 coap_log_debug("* %s: dtls: recv %4d bytes\n",
364 coap_session_str(coap_session), (int)len);
365 return coap_handle_dgram(coap_context, coap_session, data, len);
366}
367
368static int coap_event_dtls = 0;
369
370static int
371dtls_event(struct dtls_context_t *dtls_context,
372 session_t *dtls_session,
373 dtls_alert_level_t level,
374 unsigned short code) {
375 (void)dtls_context;
376 (void)dtls_session;
377
378 if (level == DTLS_ALERT_LEVEL_FATAL)
379 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
380
381 /* handle DTLS events */
382 switch (code) {
383 case DTLS_ALERT_CLOSE_NOTIFY: {
384 coap_event_dtls = COAP_EVENT_DTLS_CLOSED;
385 break;
386 }
387 case DTLS_EVENT_CONNECTED: {
388 coap_event_dtls = COAP_EVENT_DTLS_CONNECTED;
389 break;
390 }
391#ifdef DTLS_EVENT_RENEGOTIATE
392 case DTLS_EVENT_RENEGOTIATE: {
393 coap_event_dtls = COAP_EVENT_DTLS_RENEGOTIATE;
394 break;
395 }
396#endif
397 default:
398 ;
399 }
400
401 return 0;
402}
403
404#ifdef DTLS_PSK
405/* This function is the "key store" for tinyDTLS. It is called to
406 * retrieve a key for the given identity within this particular
407 * session. */
408static int
409get_psk_info(struct dtls_context_t *dtls_context,
410 const session_t *dtls_session,
411 dtls_credentials_type_t type,
412 const uint8_t *id, size_t id_len,
413 unsigned char *result, size_t result_length) {
414
415 coap_tiny_context_t *t_context =
416 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
417 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
418 coap_session_t *coap_session;
419 int fatal_error = DTLS_ALERT_INTERNAL_ERROR;
420 coap_address_t remote_addr;
421#if COAP_CLIENT_SUPPORT
422 coap_dtls_cpsk_t *setup_cdata;
423 const coap_bin_const_t *psk_identity;
424 const coap_dtls_cpsk_info_t *cpsk_info;
425#endif /* COAP_CLIENT_SUPPORT */
426 const coap_bin_const_t *psk_key;
427#if COAP_SERVER_SUPPORT
428 coap_dtls_spsk_t *setup_sdata;
429 const coap_bin_const_t *psk_hint;
430#endif /* COAP_SERVER_SUPPORT */
431
432 assert(coap_context);
433 get_session_addr(dtls_session, &remote_addr);
434 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
435 if (!coap_session) {
436 coap_log_debug("cannot get PSK, session not found\n");
437 goto error;
438 }
439
440 switch (type) {
441 case DTLS_PSK_IDENTITY:
442
443#if COAP_CLIENT_SUPPORT
444 if (coap_session->type != COAP_SESSION_TYPE_CLIENT)
445 goto error;
446
447 setup_cdata = &coap_session->cpsk_setup_data;
448
449 coap_bin_const_t temp;
450 temp.s = id;
451 temp.length = id_len;
452 coap_session_refresh_psk_hint(coap_session, &temp);
453
454 coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)id_len,
455 id ? (const char *)id : "");
456
457 if (setup_cdata->validate_ih_call_back) {
458 coap_str_const_t lhint;
459
460 lhint.length = id_len;
461 lhint.s = id;
462 cpsk_info =
463 setup_cdata->validate_ih_call_back(&lhint,
464 coap_session,
465 setup_cdata->ih_call_back_arg);
466 if (cpsk_info) {
467 psk_identity = &cpsk_info->identity;
468 coap_session_refresh_psk_identity(coap_session, &cpsk_info->identity);
469 coap_session_refresh_psk_key(coap_session, &cpsk_info->key);
470 } else {
471 psk_identity = NULL;
472 }
473 } else {
474 psk_identity = coap_get_session_client_psk_identity(coap_session);
475 }
476 if (psk_identity == NULL) {
477 coap_log_warn("no PSK identity given\n");
478 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
479 goto error;
480 }
481 if (psk_identity->length > result_length) {
482 coap_log_warn("psk_identity too large, truncated to %zd bytes\n",
483 result_length);
484 } else {
485 /* Reduce to match */
486 result_length = psk_identity->length;
487 }
488 memcpy(result, psk_identity->s, result_length);
489 return result_length;
490#else /* ! COAP_CLIENT_SUPPORT */
491 return 0;
492#endif /* ! COAP_CLIENT_SUPPORT */
493
494 case DTLS_PSK_KEY:
495#if COAP_CLIENT_SUPPORT
496 if (coap_session->type == COAP_SESSION_TYPE_CLIENT) {
497 psk_key = coap_get_session_client_psk_key(coap_session);
498 if (psk_key == NULL) {
499 coap_log_warn("no PSK key given\n");
500 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
501 goto error;
502 }
503 if (psk_key->length > result_length) {
504 coap_log_warn("psk_key too large, truncated to %zd bytes\n",
505 result_length);
506 } else {
507 /* Reduce to match */
508 result_length = psk_key->length;
509 }
510 memcpy(result, psk_key->s, result_length);
511 return result_length;
512 }
513#endif /* COAP_CLIENT_SUPPORT */
514#if COAP_SERVER_SUPPORT
515 if (coap_session->type != COAP_SESSION_TYPE_CLIENT) {
516 coap_bin_const_t lidentity;
517
518 lidentity.length = id ? id_len : 0;
519 lidentity.s = id ? (const uint8_t *)id : (const uint8_t *)"";
520 setup_sdata = &coap_session->context->spsk_setup_data;
521
522 /* Track the Identity being used */
523 coap_session_refresh_psk_identity(coap_session, &lidentity);
524
525 coap_log_debug("got psk_identity: '%.*s'\n",
526 (int)lidentity.length, lidentity.s);
527
528 if (setup_sdata->validate_id_call_back) {
529 psk_key =
530 setup_sdata->validate_id_call_back(&lidentity,
531 coap_session,
532 setup_sdata->id_call_back_arg);
533 } else {
534 psk_key = coap_get_session_server_psk_key(coap_session);
535 }
536
537 if (psk_key == NULL) {
538 coap_log_warn("no PSK key given\n");
539 return 0;
540 }
541 if (setup_sdata->validate_id_call_back)
542 coap_session_refresh_psk_key(coap_session, psk_key);
543 if (psk_key->length > result_length) {
544 coap_log_warn("psk_key too large, truncated to %zd bytes\n",
545 result_length);
546 } else {
547 /* Reduce to match */
548 result_length = psk_key->length;
549 }
550 memcpy(result, psk_key->s, result_length);
551 return result_length;
552 }
553#endif /* COAP_SERVER_SUPPORT */
554 return 0;
555
556 case DTLS_PSK_HINT:
557#if COAP_SERVER_SUPPORT
558 psk_hint = coap_get_session_server_psk_hint(coap_session);
559 if (psk_hint == NULL)
560 return 0;
561 if (psk_hint->length > result_length) {
562 coap_log_warn("psk_hint too large, truncated to %zd bytes\n",
563 result_length);
564 } else {
565 /* Reduce to match */
566 result_length = psk_hint->length;
567 }
568 memcpy(result, psk_hint->s, result_length);
569 return result_length;
570#else /* COAP_SERVER_SUPPORT */
571 return 0;
572#endif /* COAP_SERVER_SUPPORT */
573
574 default:
575 coap_log_warn("unsupported request type: %d\n", type);
576 }
577
578error:
579 return dtls_alert_fatal_create(fatal_error);
580}
581#endif /* DTLS_PSK */
582
583#ifdef DTLS_ECC
584static int
585get_ecdsa_key(struct dtls_context_t *dtls_context,
586 const session_t *dtls_session COAP_UNUSED,
587 const dtls_ecdsa_key_t **result) {
588 static dtls_ecdsa_key_t ecdsa_key;
589 coap_tiny_context_t *t_context =
590 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
591
592 ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1;
593 ecdsa_key.priv_key = t_context->priv_key->s;
594 ecdsa_key.pub_key_x = t_context->pub_key->s;
595 ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE];
596
597 *result = &ecdsa_key;
598 return 0;
599}
600
601/* first part of Raw public key, the is the start of the Subject Public Key */
602static const unsigned char cert_asn1_header[] = {
603 0x30, 0x59, /* SEQUENCE, length 89 bytes */
604 0x30, 0x13, /* SEQUENCE, length 19 bytes */
605 0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */
606 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
607 0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */
608 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
609 0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */
610 0x04 /* uncompressed, followed by the r and s values of the public key */
611};
612#define DTLS_CE_LENGTH (sizeof(cert_asn1_header) + key_size + key_size)
613
614static int
615verify_ecdsa_key(struct dtls_context_t *dtls_context COAP_UNUSED,
616 const session_t *dtls_session COAP_UNUSED,
617 const uint8_t *other_pub_x,
618 const uint8_t *other_pub_y,
619 size_t key_size) {
620 coap_tiny_context_t *t_context =
621 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
622 if (t_context && t_context->setup_data.validate_cn_call_back) {
623 /* Need to build asn.1 certificate - code taken from tinydtls */
624 uint8 *p;
625 uint8 buf[DTLS_CE_LENGTH];
626 coap_session_t *c_session;
627 coap_address_t remote_addr;
628
629 /* Certificate
630 *
631 * Start message construction at beginning of buffer. */
632 p = buf;
633
634 memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
635 p += sizeof(cert_asn1_header);
636
637 memcpy(p, other_pub_x, key_size);
638 p += key_size;
639
640 memcpy(p, other_pub_y, key_size);
641 p += key_size;
642
643 assert(p <= (buf + sizeof(buf)));
644
645 get_session_addr(dtls_session, &remote_addr);
646 c_session = coap_session_get_by_peer(t_context->coap_context,
647 &remote_addr, dtls_session->ifindex);
648 if (!c_session)
649 return -3;
650 if (!t_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN,
651 buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg)) {
652 return -1;
653 }
654 }
655 return 0;
656}
657static dtls_handler_t ec_cb = {
658 .write = dtls_send_to_peer,
659 .read = dtls_application_data,
660 .event = dtls_event,
661#ifdef DTLS_PSK
662 .get_psk_info = NULL,
663#endif /* DTLS_PSK */
664 .get_ecdsa_key = get_ecdsa_key,
665 .verify_ecdsa_key = verify_ecdsa_key
666};
667#endif /* DTLS_ECC */
668
669static dtls_handler_t psk_cb = {
670 .write = dtls_send_to_peer,
671 .read = dtls_application_data,
672 .event = dtls_event,
673#ifdef DTLS_PSK
674 .get_psk_info = get_psk_info,
675#endif /* DTLS_PSK */
676#ifdef DTLS_ECC
677 .get_ecdsa_key = NULL,
678 .verify_ecdsa_key = NULL
679#endif /* DTLS_ECC */
680};
681
682void *
684 coap_tiny_context_t *t_context = coap_malloc_type(COAP_DTLS_CONTEXT, sizeof(coap_tiny_context_t));
685 struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL;
686 if (!dtls_context)
687 goto error;
688 memset(t_context, 0, sizeof(coap_tiny_context_t));
689 t_context->coap_context = coap_context;
690 t_context->dtls_context = dtls_context;
691 dtls_set_handler(dtls_context, &psk_cb);
692 return t_context;
693error:
694 if (t_context)
696 if (dtls_context)
697 coap_dtls_free_context(dtls_context);
698 return NULL;
699}
700
701void
702coap_dtls_free_context(void *handle) {
703 if (handle) {
704 coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
705#ifdef DTLS_ECC
706 if (t_context->priv_key) {
707 coap_delete_binary(t_context->priv_key);
708 t_context->priv_key = NULL;
709 }
710 if (t_context->pub_key) {
711 coap_delete_binary(t_context->pub_key);
712 t_context->pub_key = NULL;
713 }
714#endif /* DTLS_ECC */
715 if (t_context->dtls_context)
716 dtls_free_context(t_context->dtls_context);
718 }
719}
720
721static session_t *
722coap_dtls_new_session(coap_session_t *session) {
723 session_t *dtls_session = coap_malloc_type(COAP_DTLS_SESSION, sizeof(session_t));
724
725 if (dtls_session) {
726 /* create tinydtls session object from remote address and local
727 * endpoint handle */
728 dtls_session_init(dtls_session);
729 put_session_addr(&session->addr_info.remote, dtls_session);
730 dtls_session->ifindex = session->ifindex;
731 coap_log_debug("***new session %p\n", (void *)dtls_session);
732 }
733
734 return dtls_session;
735}
736
737#if COAP_SERVER_SUPPORT
738void *
740 return coap_dtls_new_session(session);
741}
742#endif /* COAP_SERVER_SUPPORT */
743
744#if COAP_CLIENT_SUPPORT
745void *
747 dtls_peer_t *peer;
748 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
749 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
750 session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL;
751
752 if (!dtls_session)
753 return NULL;
754 peer =
755 dtls_get_peer(dtls_context, dtls_session);
756
757 if (!peer) {
758 /* The peer connection does not yet exist. */
759 /* dtls_connect() returns a value greater than zero if a new
760 * connection attempt is made, 0 for session reuse. */
761 if (dtls_connect(dtls_context, dtls_session) >= 0) {
762 peer =
763 dtls_get_peer(dtls_context, dtls_session);
764 }
765 }
766
767 if (!peer) {
768 /* delete existing session because the peer object has been invalidated */
769 coap_free_type(COAP_DTLS_SESSION, dtls_session);
770 dtls_session = NULL;
771 }
772
773 return dtls_session;
774}
775#endif /* COAP_CLIENT_SUPPORT */
776
777void
779 (void)session;
780}
781
782void
784 coap_tiny_context_t *t_context =
785 (coap_tiny_context_t *)coap_session->context->dtls_context;
786 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
787
788 if (dtls_context == NULL)
789 return;
790 if (coap_session->tls && dtls_context) {
791 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->tls);
792 if (peer)
793 dtls_reset_peer(dtls_context, peer);
794 else
795 dtls_close(dtls_context, (session_t *)coap_session->tls);
796 coap_log_debug("***removed session %p\n", coap_session->tls);
797 coap_free_type(COAP_DTLS_SESSION, coap_session->tls);
798 coap_session->tls = NULL;
799 coap_handle_event_lkd(coap_session->context, COAP_EVENT_DTLS_CLOSED, coap_session);
800 }
801}
802
803ssize_t
805 const uint8_t *data,
806 size_t data_len) {
807 int res;
808 uint8_t *data_rw;
809 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
810 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
811
812 assert(dtls_context);
813
814 coap_event_dtls = -1;
815 coap_log_debug("* %s: dtls: sent %4d bytes\n",
816 coap_session_str(session), (int)data_len);
817 /* Need to do this to not get a compiler warning about const parameters */
818 memcpy(&data_rw, &data, sizeof(data_rw));
819 res = dtls_write(dtls_context,
820 (session_t *)session->tls, data_rw, data_len);
821
822 if (res < 0)
823 coap_log_warn("coap_dtls_send: cannot send PDU\n");
824
825 if (coap_event_dtls >= 0) {
826 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
827 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
828 coap_handle_event_lkd(session->context, coap_event_dtls, session);
829 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
830 coap_session_connected(session);
831 else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
833 }
834
835 return res;
836}
837
838int
840 return 1;
841}
842
844coap_dtls_get_context_timeout(void *tiny_context) {
845 clock_time_t next = 0;
846 coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
847 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
848 if (tiny_context)
849 dtls_check_retransmit(dtls_context, &next);
850 if (next > 0)
851 return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND +
852 coap_tick_0;
853 return 0;
854}
855
858 (void)session;
859 (void)now;
860 return 0;
861}
862
863/*
864 * return 1 timed out
865 * 0 still timing out
866 */
867int
869 (void)session;
870 return 0;
871}
872
873int
875 const uint8_t *data,
876 size_t data_len
877 ) {
878 session_t *dtls_session = (session_t *)session->tls;
879 int err;
880 uint8_t *data_rw;
881 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
882 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
883
884 assert(dtls_context);
885 coap_event_dtls = -1;
886 /* Need to do this to not get a compiler warning about const parameters */
887 memcpy(&data_rw, &data, sizeof(data_rw));
888 err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len);
889
890 if (err) {
891 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
892 }
893
894 if (coap_event_dtls >= 0) {
895 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
896 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
897 coap_handle_event_lkd(session->context, coap_event_dtls, session);
898 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
899 coap_session_connected(session);
900 else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) {
902 err = -1;
903 }
904 }
905
906 return err;
907}
908
909#if COAP_SERVER_SUPPORT
910int
912 const uint8_t *data,
913 size_t data_len
914 ) {
915 session_t dtls_session;
916 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
917 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
918 uint8_t *data_rw;
919
920 assert(dtls_context);
921 dtls_session_init(&dtls_session);
922 put_session_addr(&session->addr_info.remote, &dtls_session);
923 dtls_session.ifindex = session->ifindex;
924 /* Need to do this to not get a compiler warning about const parameters */
925 memcpy(&data_rw, &data, sizeof(data_rw));
926 int res = dtls_handle_message(dtls_context, &dtls_session,
927 data_rw, (int)data_len);
928 if (res >= 0) {
929 if (dtls_get_peer(dtls_context, &dtls_session))
930 res = 1;
931 else
932 res = 0;
933 }
934 return res;
935}
936#endif /* COAP_SERVER_SUPPORT */
937
938unsigned int
940 (void)session;
941 return 13 + 8 + 8;
942}
943
944int
946 return 0;
947}
948
951 static coap_tls_version_t version;
952 const char *vers = dtls_package_version();
953
954 version.version = 0;
955 if (vers) {
956 long int p1, p2 = 0, p3 = 0;
957 char *endptr;
958
959 p1 = strtol(vers, &endptr, 10);
960 if (*endptr == '.') {
961 p2 = strtol(endptr+1, &endptr, 10);
962 if (*endptr == '.') {
963 p3 = strtol(endptr+1, &endptr, 10);
964 }
965 }
966 version.version = (p1 << 16) | (p2 << 8) | p3;
967 }
968 version.built_version = version.version;
970 return &version;
971}
972
973#ifdef DTLS_ECC
974static const uint8_t b64_6[256] = {
975 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
976 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
977 /* + / */
978 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
979 /* 0 1 2 3 4 5 6 7 8 9 = */
980 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
981 /* A B C D E F G H I J K L M N O */
982 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
983 /* P Q R S T U V W X Y Z */
984 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
985 /* a b c d e f g h i j k l m n o */
986 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
987 /* p q r s t u v w x y z */
988 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
989 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
990 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
991 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
992 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
993 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
994 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
995 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
996 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
997};
998
999/* caller must free off returned coap_binary_t* */
1000static coap_binary_t *
1001pem_base64_decode(const uint8_t *data, size_t size) {
1002 uint8_t *tbuf = coap_malloc_type(COAP_STRING, size);
1003 size_t nbytesdecoded;
1004 size_t i;
1005 coap_binary_t *decoded;
1006 uint8_t *ptr;
1007 uint8_t *out;
1008 size_t nb64bytes = 0;
1009
1010 for (i = 0; i < size; i++) {
1011 switch (data[i]) {
1012 case ' ':
1013 case '\r':
1014 case '\n':
1015 case '\t':
1016 break;
1017 default:
1018 if (b64_6[data[i]] == 64)
1019 goto end;
1020 tbuf[nb64bytes++] = data[i];
1021 break;
1022 }
1023 }
1024
1025end:
1026 nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
1027 decoded = coap_new_binary(nbytesdecoded + 1);
1028 if (!decoded)
1029 return NULL;
1030
1031 out = decoded->s;
1032 ptr = tbuf;
1033
1034 while (nb64bytes > 4) {
1035 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1036 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1037 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1038 ptr += 4;
1039 nb64bytes -= 4;
1040 }
1041
1042 /* Note: (nb64bytes == 1) is an error */
1043 if (nb64bytes > 1) {
1044 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1045 }
1046 if (nb64bytes > 2) {
1047 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1048 }
1049 if (nb64bytes > 3) {
1050 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1051 }
1052
1053 decoded->length = nbytesdecoded - ((4 - nb64bytes) & 3);
1055 return decoded;
1056}
1057
1058typedef coap_binary_t *(*asn1_callback)(const uint8_t *data, size_t size);
1059
1060static int
1061asn1_verify_privkey(const uint8_t *data, size_t size) {
1062 /* Check if we have the private key (with optional leading 0x00) */
1063 /* skip leading 0x00 */
1064 if (size - 1 == DTLS_EC_KEY_SIZE && *data == '\000') {
1065 --size;
1066 ++data;
1067 }
1068
1069 /* Check if we have the private key */
1070 if (size != DTLS_EC_KEY_SIZE)
1071 return 0;
1072
1073 return 1;
1074}
1075
1076static int
1077asn1_verify_pubkey(const uint8_t *data, size_t size) {
1078 (void)data;
1079
1080 /* We have the public key
1081 (with a leading 0x00 (no unused bits) 0x04 (not compressed() */
1082 if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
1083 return 0;
1084
1085 return 1;
1086}
1087
1088static int
1089asn1_verify_curve(const uint8_t *data, size_t size) {
1090 static uint8_t prime256v1_oid[] =
1091 /* OID 1.2.840.10045.3.1.7 */
1092 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
1093
1094 /* Check that we have the correct EC (only one supported) */
1095 if (size != sizeof(prime256v1_oid) ||
1096 memcmp(data, prime256v1_oid, size) != 0)
1097 return 0;
1098
1099 return 1;
1100}
1101
1102static int
1103asn1_verify_pkcs8_version(const uint8_t *data, size_t size) {
1104 /* Check that we have the version */
1105 if (size != 1 || *data != 0)
1106 return 0;
1107
1108 return 1;
1109}
1110
1111static int
1112asn1_verify_ec_identifier(const uint8_t *data, size_t size) {
1113 static uint8_t ec_public_key_oid[] =
1114 /* OID 1.2.840.10045.2.1 */
1115 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
1116
1117 /* Check that we have the correct ecPublicKey */
1118 if (size != sizeof(ec_public_key_oid) ||
1119 memcmp(data, ec_public_key_oid, size) != 0)
1120 return 0;
1121
1122 return 1;
1123}
1124
1125static int
1126asn1_verify_ec_key(const uint8_t *data, size_t size) {
1127 (void)data;
1128
1129 if (size == 0)
1130 return 0;
1131
1132 return 1;
1133}
1134
1135static int
1136asn1_derive_keys(coap_tiny_context_t *t_context,
1137 const uint8_t *priv_data, size_t priv_len,
1138 const uint8_t *pub_data, size_t pub_len,
1139 int is_pkcs8) {
1140 coap_binary_t *test;
1141
1142 t_context->priv_key = get_asn1_tag(COAP_ASN1_OCTETSTRING, priv_data,
1143 priv_len, asn1_verify_privkey);
1144 if (!t_context->priv_key) {
1145 coap_log_info("EC Private Key (RPK) invalid\n");
1146 return 0;
1147 }
1148 /* skip leading 0x00 */
1149 if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
1150 t_context->priv_key->s[0] == '\000') {
1151 t_context->priv_key->length--;
1152 t_context->priv_key->s++;
1153 }
1154
1155 if (!is_pkcs8) {
1156 /* pkcs8 abstraction tested for valid eliptic curve */
1157 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, priv_data, priv_len,
1158 asn1_verify_curve);
1159 if (!test) {
1160 coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1161 coap_delete_binary(t_context->priv_key);
1162 t_context->priv_key = NULL;
1163 return 0;
1164 }
1165 coap_delete_binary(test);
1166 }
1167
1168 t_context->pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, pub_data, pub_len,
1169 asn1_verify_pubkey);
1170 if (!t_context->pub_key) {
1171 coap_log_info("EC Public Key (RPK) invalid\n");
1172 coap_delete_binary(t_context->priv_key);
1173 t_context->priv_key = NULL;
1174 return 0;
1175 }
1176 /* Drop leading 0x00 and 0x04 */
1177 t_context->pub_key->s += 2;
1178 t_context->pub_key->length -= 2;
1179 dtls_set_handler(t_context->dtls_context, &ec_cb);
1180 return 1;
1181}
1182
1183static coap_binary_t *
1184ec_abstract_pkcs8_asn1(const uint8_t *asn1_ptr, size_t asn1_length) {
1185 coap_binary_t *test;
1186
1187 test = get_asn1_tag(COAP_ASN1_INTEGER, asn1_ptr, asn1_length,
1188 asn1_verify_pkcs8_version);
1189 if (!test)
1190 return 0;
1191
1192 coap_delete_binary(test);
1193
1194 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1195 asn1_verify_ec_identifier);
1196 if (!test)
1197 return 0;
1198 coap_delete_binary(test);
1199
1200 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1201 asn1_verify_curve);
1202 if (!test) {
1203 coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1204 return 0;
1205 }
1206 coap_delete_binary(test);
1207
1208 test = get_asn1_tag(COAP_ASN1_OCTETSTRING, asn1_ptr, asn1_length,
1209 asn1_verify_ec_key);
1210 return test;
1211}
1212
1213static coap_binary_t *
1214pem_decode_mem_asn1(const char *begstr, const uint8_t *str) {
1215 char *bcp = str ? strstr((const char *)str, begstr) : NULL;
1216 char *tcp = bcp ? strstr(bcp, "-----END ") : NULL;
1217
1218 if (bcp && tcp) {
1219 bcp += strlen(begstr);
1220 return pem_base64_decode((const uint8_t *)bcp, tcp - bcp);
1221 }
1222 return NULL;
1223}
1224
1225#endif /* DTLS_ECC */
1226
1227int
1229 const coap_dtls_pki_t *setup_data,
1230 const coap_dtls_role_t role) {
1231#ifdef DTLS_ECC
1232 coap_tiny_context_t *t_context;
1233 coap_binary_t *asn1_priv = NULL;
1234 coap_binary_t *asn1_pub = NULL;
1235 coap_binary_t *asn1_temp;
1236 int is_pkcs8 = 0;
1237 coap_dtls_key_t key;
1238
1239 if (!setup_data->is_rpk_not_cert) {
1240 coap_log_warn("Only RPK, not full PKI is supported\n");
1241 return 0;
1242 }
1243 if (!ctx)
1244 return 0;
1245
1246 t_context = (coap_tiny_context_t *)ctx->dtls_context;
1247 if (!t_context)
1248 return 0;
1249 if (t_context->priv_key) {
1250 coap_delete_binary(t_context->priv_key);
1251 t_context->priv_key = NULL;
1252 }
1253 if (t_context->pub_key) {
1254 coap_delete_binary(t_context->pub_key);
1255 t_context->pub_key = NULL;
1256 }
1257 t_context->setup_data = *setup_data;
1258
1259 /* Map over to the new define format to save code duplication */
1260 coap_dtls_map_key_type_to_define(setup_data, &key);
1261
1262 assert(key.key_type == COAP_PKI_KEY_DEFINE);
1263
1264 /*
1265 * Configure the Private Key
1266 */
1267 if (key.key.define.private_key.u_byte &&
1268 key.key.define.private_key.u_byte[0]) {
1269 switch (key.key.define.private_key_def) {
1270 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1271 /* Need to take PEM memory information and convert to binary */
1272 asn1_priv = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1274 if (!asn1_priv) {
1275 asn1_priv = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1277 if (!asn1_priv) {
1280 &key, role, 0);
1281 }
1282 asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->s, asn1_priv->length);
1283 if (!asn1_temp) {
1284 coap_log_info("*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1285 coap_delete_binary(asn1_priv);
1288 &key, role, 0);
1289 }
1290 coap_delete_binary(asn1_priv);
1291 asn1_priv = asn1_temp;
1292 is_pkcs8 = 1;
1293 }
1294 asn1_pub = pem_decode_mem_asn1("-----BEGIN PUBLIC KEY-----",
1296 if (!asn1_pub) {
1297 asn1_pub = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1299 if (!asn1_pub) {
1300 asn1_pub = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1302 if (!asn1_pub) {
1303 coap_log_info("*** setup_pki: (D)TLS: Public Key (RPK) invalid\n");
1304 coap_delete_binary(asn1_priv);
1307 &key, role, 0);
1308 }
1309 asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->s, asn1_pub->length);
1310 if (!asn1_temp) {
1311 coap_log_info("*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1312 coap_delete_binary(asn1_priv);
1313 coap_delete_binary(asn1_pub);
1316 &key, role, 0);
1317 }
1318 coap_delete_binary(asn1_pub);
1319 asn1_pub = asn1_temp;
1320 is_pkcs8 = 1;
1321 }
1322 }
1323 if (!asn1_derive_keys(t_context, asn1_priv->s, asn1_priv->length,
1324 asn1_pub->s, asn1_pub->length, is_pkcs8)) {
1325 coap_log_info("*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1326 coap_delete_binary(asn1_priv);
1327 coap_delete_binary(asn1_pub);
1328 return 0;
1329 }
1330 coap_delete_binary(asn1_priv);
1331 coap_delete_binary(asn1_pub);
1332 return 1;
1333 break;
1334 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1335 if (key.key.define.private_key_len > 0 &&
1337 const uint8_t *private_key = key.key.define.private_key.u_byte;
1338 size_t private_key_len = key.key.define.private_key_len;
1339
1340 /* Check to see whether this is in pkcs8 format or not */
1341 asn1_temp = ec_abstract_pkcs8_asn1(key.key.define.private_key.u_byte,
1343 if (asn1_temp) {
1344 private_key = asn1_temp->s;
1345 private_key_len = asn1_temp->length;
1346 is_pkcs8 = 1;
1347 }
1348 /* Need to take ASN1 memory information and convert to binary */
1349 if (key.key.define.public_cert.u_byte &&
1351 if (!asn1_derive_keys(t_context,
1352 private_key,
1353 private_key_len,
1356 is_pkcs8)) {
1357 coap_log_info("*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1358 coap_delete_binary(asn1_temp);
1359 return 0;
1360 }
1361 } else {
1362 if (!asn1_derive_keys(t_context,
1363 private_key,
1364 private_key_len,
1365 private_key,
1366 private_key_len,
1367 is_pkcs8)) {
1368 coap_log_info("*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1369 coap_delete_binary(asn1_temp);
1370 return 0;
1371 }
1372 }
1373 coap_delete_binary(asn1_temp);
1374 return 1;
1375 } else {
1378 &key, role, 0);
1379 }
1380 break;
1387 default:
1390 &key, role, 0);
1391 }
1392 } else {
1395 &key, role, 0);
1396 }
1397
1398 /*
1399 * Configure the Public Certificate / Key
1400 */
1401 if (key.key.define.public_cert.u_byte &&
1402 key.key.define.public_cert.u_byte[0]) {
1403 switch (key.key.define.public_cert_def) {
1406 /* done under private key */
1407 break;
1414 default:
1417 &key, role, 0);
1418 }
1419 }
1420
1421 /*
1422 * Configure the CA
1423 */
1424 if (key.key.define.ca.u_byte &&
1425 key.key.define.ca.u_byte[0]) {
1426 switch (key.key.define.ca_def) {
1429 /* Ignore if set */
1430 break;
1437 default:
1440 &key, role, 0);
1441 }
1442 }
1443
1444 return 1;
1445#else /* ! DTLS_ECC */
1446 (void)ctx;
1447 (void)setup_data;
1448 (void)role;
1449 coap_log_warn("TinyDTLS not compiled with ECC support\n");
1450 return 0;
1451#endif /* ! DTLS_ECC */
1452}
1453
1454int
1456 const char *ca_file COAP_UNUSED,
1457 const char *ca_path COAP_UNUSED
1458 ) {
1459 coap_log_warn("Root CAs PKI not supported\n");
1460 return 0;
1461}
1462
1463#if COAP_CLIENT_SUPPORT
1464int
1466 coap_dtls_cpsk_t *setup_data
1467 ) {
1468 if (!setup_data)
1469 return 0;
1470
1471#ifdef DTLS_PSK
1472 return 1;
1473#else /* ! DTLS_PSK */
1474 coap_log_warn("TinyDTLS not compiled with PSK support\n");
1475 return 0;
1476#endif /* ! DTLS_PSK */
1477}
1478#endif /* COAP_CLIENT_SUPPORT */
1479
1480#if COAP_SERVER_SUPPORT
1481int
1483 coap_dtls_spsk_t *setup_data
1484 ) {
1485 if (!setup_data)
1486 return 0;
1487
1488#ifdef DTLS_PSK
1489 if (setup_data->validate_sni_call_back) {
1490 coap_log_warn("CoAP Server with TinyDTLS does not support SNI selection\n");
1491 }
1492
1493 return 1;
1494#else /* ! DTLS_PSK */
1495 coap_log_warn("TinyDTLS not compiled with PSK support\n");
1496 return 0;
1497#endif /* ! DTLS_PSK */
1498}
1499#endif /* COAP_SERVER_SUPPORT */
1500
1501int
1503 return 1;
1504}
1505
1506#if !COAP_DISABLE_TCP
1507#if COAP_CLIENT_SUPPORT
1508void *
1510 return NULL;
1511}
1512#endif /* COAP_CLIENT_SUPPORT */
1513
1514#if COAP_SERVER_SUPPORT
1515void *
1517 return NULL;
1518}
1519#endif /* COAP_SERVER_SUPPORT */
1520
1521void
1523}
1524
1525/*
1526 * strm
1527 * return +ve Number of bytes written.
1528 * -1 Error (error in errno).
1529 */
1530ssize_t
1532 const uint8_t *data COAP_UNUSED,
1533 size_t data_len COAP_UNUSED
1534 ) {
1535 return -1;
1536}
1537
1538/*
1539 * strm
1540 * return >=0 Number of bytes read.
1541 * -1 Error (error in errno).
1542 */
1543ssize_t
1545 uint8_t *data COAP_UNUSED,
1546 size_t data_len COAP_UNUSED) {
1547 errno = ENODEV;
1548 return -1;
1549}
1550#endif /* !COAP_DISABLE_TCP */
1551
1552#if COAP_SERVER_SUPPORT
1554coap_digest_setup(void) {
1555 dtls_sha256_ctx *digest_ctx = coap_malloc_type(COAP_STRING, sizeof(dtls_sha256_ctx));
1556
1557 if (digest_ctx) {
1558 dtls_sha256_init(digest_ctx);
1559 }
1560
1561 return digest_ctx;
1562}
1563
1564void
1566 coap_free_type(COAP_STRING, digest_ctx);
1567}
1568
1569int
1571 const uint8_t *data,
1572 size_t data_len) {
1573 dtls_sha256_update(digest_ctx, data, data_len);
1574
1575 return 1;
1576}
1577
1578int
1580 coap_digest_t *digest_buffer) {
1581 dtls_sha256_final((uint8_t *)digest_buffer, digest_ctx);
1582
1583 coap_digest_free(digest_ctx);
1584 return 1;
1585}
1586#endif /* COAP_SERVER_SUPPORT */
1587
1588#if COAP_WS_SUPPORT
1589int
1591 const coap_bin_const_t *data,
1592 coap_bin_const_t **hash) {
1593 SHA1Context sha1_context;
1594 coap_binary_t *dummy = NULL;
1595
1596 (void)alg;
1597
1598 SHA1Reset(&sha1_context);
1599 if (SHA1Input(&sha1_context, data->s, data->length) != shaSuccess)
1600 return 0;
1602 if (!dummy)
1603 return 0;
1604 if (SHA1Result(&sha1_context, dummy->s) != shaSuccess) {
1606 return 0;
1607 }
1608 *hash = (coap_bin_const_t *)(dummy);
1609 return 1;
1610}
1611#endif /* COAP_WS_SUPPORT */
1612
1613#if COAP_OSCORE_SUPPORT
1614
1615int
1617 return 1;
1618}
1619
1620/*
1621 * The struct cipher_algs and the function get_cipher_alg() are used to
1622 * determine which cipher type to use for creating the required cipher
1623 * suite object.
1624 */
1625static struct cipher_algs {
1626 cose_alg_t alg;
1627 u_int cipher_type;
1628} ciphers[] = {
1630};
1631
1632static u_int
1633get_cipher_alg(cose_alg_t alg) {
1634 size_t idx;
1635
1636 for (idx = 0; idx < sizeof(ciphers)/sizeof(struct cipher_algs); idx++) {
1637 if (ciphers[idx].alg == alg)
1638 return ciphers[idx].cipher_type;
1639 }
1640 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
1641 return 0;
1642}
1643
1644/*
1645 * The struct hmac_algs and the function get_hmac_alg() are used to
1646 * determine which hmac type to use for creating the required hmac
1647 * suite object.
1648 */
1649static struct hmac_algs {
1650 cose_hmac_alg_t hmac_alg;
1651 u_int hmac_type;
1652} hmacs[] = {
1654};
1655
1656static u_int
1657get_hmac_alg(cose_hmac_alg_t hmac_alg) {
1658 size_t idx;
1659
1660 for (idx = 0; idx < sizeof(hmacs)/sizeof(struct hmac_algs); idx++) {
1661 if (hmacs[idx].hmac_alg == hmac_alg)
1662 return hmacs[idx].hmac_type;
1663 }
1664 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
1665 return 0;
1666}
1667
1668int
1670 return get_cipher_alg(alg);
1671}
1672
1673int
1675 cose_hmac_alg_t hmac_alg;
1676
1677 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
1678 return 0;
1679 return get_hmac_alg(hmac_alg);
1680}
1681
1682int
1684 coap_bin_const_t *data,
1685 coap_bin_const_t *aad,
1686 uint8_t *result, size_t *max_result_len) {
1687 int num_bytes;
1688 const coap_crypto_aes_ccm_t *ccm;
1689 dtls_ccm_params_t dtls_params;
1690 coap_bin_const_t laad;
1691
1692 if (data == NULL)
1693 return 0;
1694
1695 assert(params);
1696
1697 if (get_cipher_alg(params->alg) == 0) {
1698 coap_log_debug("coap_crypto_encrypt: algorithm %d not supported\n",
1699 params->alg);
1700 return 0;
1701 }
1702
1703 ccm = &params->params.aes;
1704 if (*max_result_len < (data->length + ccm->tag_len)) {
1705 coap_log_warn("coap_encrypt: result buffer too small\n");
1706 return 0;
1707 }
1708
1709 dtls_params.nonce = ccm->nonce;
1710 dtls_params.tag_length = ccm->tag_len;
1711 dtls_params.l = ccm->l;
1712
1713 if (aad) {
1714 laad = *aad;
1715 } else {
1716 laad.s = NULL;
1717 laad.length = 0;
1718 }
1719
1720 num_bytes = dtls_encrypt_params(&dtls_params,
1721 data->s, data->length,
1722 result,
1723 ccm->key.s, ccm->key.length,
1724 laad.s, laad.length);
1725 if (num_bytes < 0) {
1726 return 0;
1727 }
1728 *max_result_len = num_bytes;
1729 return 1;
1730}
1731
1732int
1734 coap_bin_const_t *data,
1735 coap_bin_const_t *aad,
1736 uint8_t *result, size_t *max_result_len) {
1737 int num_bytes;
1738 const coap_crypto_aes_ccm_t *ccm;
1739 dtls_ccm_params_t dtls_params;
1740 coap_bin_const_t laad;
1741
1742 if (data == NULL)
1743 return 0;
1744
1745 assert(params);
1746
1747 if (get_cipher_alg(params->alg) == 0) {
1748 coap_log_debug("coap_crypto_decrypt: algorithm %d not supported\n",
1749 params->alg);
1750 return 0;
1751 }
1752
1753 ccm = &params->params.aes;
1754
1755 if ((*max_result_len + ccm->tag_len) < data->length) {
1756 coap_log_warn("coap_decrypt: result buffer too small\n");
1757 return 0;
1758 }
1759
1760 dtls_params.nonce = ccm->nonce;
1761 dtls_params.tag_length = ccm->tag_len;
1762 dtls_params.l = ccm->l;
1763
1764 if (aad) {
1765 laad = *aad;
1766 } else {
1767 laad.s = NULL;
1768 laad.length = 0;
1769 }
1770
1771 num_bytes = dtls_decrypt_params(&dtls_params,
1772 data->s, data->length,
1773 result,
1774 ccm->key.s, ccm->key.length,
1775 laad.s, laad.length);
1776 if (num_bytes < 0) {
1777 return 0;
1778 }
1779 *max_result_len = num_bytes;
1780 return 1;
1781}
1782
1783int
1785 coap_bin_const_t *data, coap_bin_const_t **hmac) {
1786 dtls_hmac_context_t hmac_context;
1787 int num_bytes;
1789
1790 if (data == NULL)
1791 return 0;
1792
1793 if (get_hmac_alg(hmac_alg) == 0) {
1794 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
1795 return 0;
1796 }
1797
1798 dummy = coap_new_binary(DTLS_SHA256_DIGEST_LENGTH);
1799 if (dummy == NULL)
1800 return 0;
1801
1802 dtls_hmac_init(&hmac_context, key->s, key->length);
1803 dtls_hmac_update(&hmac_context, data->s, data->length);
1804 num_bytes = dtls_hmac_finalize(&hmac_context, dummy->s);
1805
1806 if (num_bytes != DTLS_SHA256_DIGEST_LENGTH) {
1808 return 0;
1809 }
1810 *hmac = (coap_bin_const_t *)dummy;
1811 return 1;
1812}
1813
1814#endif /* COAP_OSCORE_SUPPORT */
1815
1816#else /* !COAP_WITH_LIBTINYDTLS */
1817
1818#ifdef __clang__
1819/* Make compilers happy that do not like empty modules. As this function is
1820 * never used, we ignore -Wunused-function at the end of compiling this file
1821 */
1822#pragma GCC diagnostic ignored "-Wunused-function"
1823#endif
1824static inline void
1825dummy(void) {
1826}
1827
1828#endif /* COAP_WITH_LIBTINYDTLS */
@ COAP_NACK_TLS_FAILED
Definition coap_io.h:73
@ COAP_LAYER_TLS
Library specific build wrapper for coap_internal.h.
@ COAP_DTLS_SESSION
Definition coap_mem.h:49
@ COAP_DTLS_CONTEXT
Definition coap_mem.h:59
@ COAP_STRING
Definition coap_mem.h:38
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.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
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:90
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition coap_notls.c:206
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:278
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition coap_notls.c:201
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:220
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition coap_notls.c:135
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:238
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:124
ssize_t 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:189
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:266
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:185
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:98
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:215
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition coap_notls.c:163
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:181
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition coap_notls.c:158
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:257
int SHA1Result(SHA1Context *, uint8_t Message_Digest[SHA1HashSize])
int SHA1Reset(SHA1Context *)
int SHA1Input(SHA1Context *, const uint8_t *, unsigned int)
@ shaSuccess
#define SHA1HashSize
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:65
@ 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.
int coap_digest_final(coap_digest_ctx_t *digest_ctx, coap_digest_t *digest_buffer)
Finalize the coap_digest information into the provided digest_buffer.
int coap_digest_update(coap_digest_ctx_t *digest_ctx, const uint8_t *data, size_t data_len)
Update the coap_digest information with the next chunk of data.
void coap_digest_ctx_t
coap_digest_ctx_t * coap_digest_setup(void)
Initialize a coap_digest.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:143
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition coap_time.h:158
int coap_handle_event_lkd(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 coap_net.c:4253
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 coap_net.c:2422
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
int coap_crypto_hmac(cose_hmac_alg_t hmac_alg, coap_bin_const_t *key, coap_bin_const_t *data, coap_bin_const_t **hmac)
Create a HMAC hash of the provided data.
int coap_crypto_aead_decrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Decrypt the provided encrypted data into plaintext.
int coap_crypto_aead_encrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Encrypt the provided plaintext data.
int coap_crypto_hash(cose_alg_t alg, const coap_bin_const_t *data, coap_bin_const_t **hash)
Create a hash of the provided data.
int coap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg)
Check whether the defined hkdf algorithm is supported by the underlying crypto library.
int coap_crypto_check_cipher_alg(cose_alg_t alg)
Check whether the defined cipher algorithm is supported by the underlying crypto library.
void * coap_tls_new_server_session(coap_session_t *coap_session)
Create a TLS new server-side session.
const coap_bin_const_t * coap_get_session_client_psk_identity(const coap_session_t *session)
Get the current client's PSK identity.
Definition coap_net.c:308
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition coap_notls.c:131
int coap_dtls_define_issue(coap_define_issue_key_t type, coap_define_issue_fail_t fail, coap_dtls_key_t *key, const coap_dtls_role_t role, int ret)
Report PKI DEFINE type issue.
Definition coap_dtls.c:165
void * coap_dtls_new_client_session(coap_session_t *coap_session)
Create a new client-side session.
void * coap_dtls_new_server_session(coap_session_t *coap_session)
Create a new DTLS server-side session.
int coap_dtls_hello(coap_session_t *coap_session, const uint8_t *data, size_t data_len)
Handling client HELLO messages from a new candiate peer.
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition coap_notls.c:196
int coap_dtls_context_set_cpsk(coap_context_t *coap_context, coap_dtls_cpsk_t *setup_data)
Set the DTLS context's default client PSK information.
int coap_dtls_context_set_spsk(coap_context_t *coap_context, coap_dtls_spsk_t *setup_data)
Set the DTLS context's default server PSK information.
void coap_dtls_shutdown(void)
Close down the underlying (D)TLS Library layer.
Definition coap_notls.c:143
const coap_bin_const_t * coap_get_session_client_psk_key(const coap_session_t *coap_session)
Get the current client's PSK key.
void * coap_tls_new_client_session(coap_session_t *coap_session)
Create a new TLS client-side session.
void coap_dtls_map_key_type_to_define(const coap_dtls_pki_t *setup_data, coap_dtls_key_t *key)
Map the PKI key definitions to the new DEFINE format.
Definition coap_dtls.c:26
const coap_bin_const_t * coap_get_session_server_psk_key(const coap_session_t *coap_session)
Get the current server's PSK key.
const coap_bin_const_t * coap_get_session_server_psk_hint(const coap_session_t *coap_session)
Get the current server's PSK identity hint.
@ COAP_DEFINE_KEY_PRIVATE
@ COAP_DEFINE_KEY_CA
@ COAP_DEFINE_KEY_PUBLIC
@ COAP_DEFINE_FAIL_NONE
@ COAP_DEFINE_FAIL_NOT_SUPPORTED
@ COAP_DEFINE_FAIL_BAD
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:82
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition coap_notls.c:50
coap_dtls_role_t
Definition coap_dtls.h:44
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition coap_notls.c:41
#define COAP_DTLS_RPK_CERT_CN
Definition coap_dtls.h:49
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition coap_notls.c:36
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition coap_notls.c:59
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition coap_notls.c:77
coap_tls_library_t
Definition coap_dtls.h:112
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition coap_notls.c:68
@ COAP_PKI_KEY_DEF_PKCS11
The PKI key type is PKCS11 (pkcs11:...).
Definition coap_dtls.h:287
@ COAP_PKI_KEY_DEF_DER_BUF
The PKI key type is DER buffer (ASN.1).
Definition coap_dtls.h:284
@ COAP_PKI_KEY_DEF_PEM_BUF
The PKI key type is PEM buffer.
Definition coap_dtls.h:278
@ COAP_PKI_KEY_DEF_PEM
The PKI key type is PEM file.
Definition coap_dtls.h:276
@ COAP_PKI_KEY_DEF_ENGINE
The PKI key type is to be passed to ENGINE.
Definition coap_dtls.h:293
@ COAP_PKI_KEY_DEF_RPK_BUF
The PKI key type is RPK in buffer.
Definition coap_dtls.h:280
@ COAP_PKI_KEY_DEF_DER
The PKI key type is DER file.
Definition coap_dtls.h:282
@ COAP_PKI_KEY_DEF_PKCS11_RPK
The PKI key type is PKCS11 w/ RPK (pkcs11:...).
Definition coap_dtls.h:290
@ COAP_PKI_KEY_DEFINE
The individual PKI key types are Definable.
Definition coap_dtls.h:214
@ COAP_ASN1_PKEY_EC
EC type.
Definition coap_dtls.h:199
@ COAP_TLS_LIBRARY_TINYDTLS
Using TinyDTLS library.
Definition coap_dtls.h:114
@ COAP_EVENT_DTLS_CLOSED
Triggerred when (D)TLS session closed.
Definition coap_event.h:39
@ COAP_EVENT_DTLS_CONNECTED
Triggered when (D)TLS session connected.
Definition coap_event.h:41
@ COAP_EVENT_DTLS_RENEGOTIATE
Triggered when (D)TLS session renegotiated.
Definition coap_event.h:43
@ COAP_EVENT_DTLS_ERROR
Triggered when (D)TLS error occurs.
Definition coap_event.h:45
#define coap_log_debug(...)
Definition coap_debug.h:120
coap_log_t
Logging type.
Definition coap_debug.h:50
coap_log_t coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition coap_notls.c:153
#define coap_dtls_log(level,...)
Logging function.
Definition coap_debug.h:300
void coap_dtls_set_log_level(coap_log_t level)
Sets the (D)TLS logging level to the specified level.
Definition coap_notls.c:148
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
Definition coap_debug.h:108
#define coap_log_warn(...)
Definition coap_debug.h:102
@ COAP_LOG_INFO
Definition coap_debug.h:57
@ COAP_LOG_OSCORE
Definition coap_debug.h:59
@ COAP_LOG_EMERG
Definition coap_debug.h:51
@ COAP_LOG_DTLS_BASE
Definition coap_debug.h:60
@ COAP_LOG_NOTICE
Definition coap_debug.h:56
@ COAP_LOG_DEBUG
Definition coap_debug.h:58
@ COAP_LOG_ALERT
Definition coap_debug.h:52
@ COAP_LOG_CRIT
Definition coap_debug.h:53
@ COAP_LOG_ERR
Definition coap_debug.h:54
@ COAP_LOG_WARN
Definition coap_debug.h:55
int cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg)
cose_hkdf_alg_t
cose_hmac_alg_t
cose_alg_t
@ COSE_HMAC_ALG_HMAC256_256
@ COSE_ALGORITHM_AES_CCM_16_64_128
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
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).
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.
int coap_session_refresh_psk_identity(coap_session_t *session, const coap_bin_const_t *psk_identity)
Refresh the session's current pre-shared identity (PSK).
void coap_session_disconnected_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
coap_session_t * coap_session_get_by_peer(const coap_context_t *ctx, const coap_address_t *remote_addr, int ifindex)
Get the session associated with the specified remote_addr and index.
@ COAP_SESSION_TYPE_CLIENT
client-side
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition coap_str.c:77
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition coap_str.c:105
#define COAP_UNUSED
Definition libcoap.h:70
coap_address_t remote
remote address and port
Definition coap_io.h:56
Multi-purpose address abstraction.
socklen_t size
size of addr
struct sockaddr_in sin
struct sockaddr_in6 sin6
struct sockaddr sa
union coap_address_t::@0 addr
CoAP binary data definition with const data.
Definition coap_str.h:64
size_t length
length of binary data
Definition coap_str.h:65
const uint8_t * s
read-only binary data
Definition coap_str.h:66
CoAP binary data definition.
Definition coap_str.h:56
size_t length
length of binary data
Definition coap_str.h:57
uint8_t * s
binary data
Definition coap_str.h:58
The CoAP stack's global state is stored in a coap_context_t object.
coap_dtls_spsk_t spsk_setup_data
Contains the initial PSK server setup data.
The structure that holds the AES Crypto information.
size_t l
The number of bytes in the length field.
const uint8_t * nonce
must be exactly 15 - l bytes
coap_crypto_key_t key
The Key to use.
size_t tag_len
The size of the Tag.
The common structure that holds the Crypto information.
union coap_crypto_param_t::@2 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
cose_alg_t alg
The COSE algorith to use.
The structure that holds the Client PSK information.
Definition coap_dtls.h:417
coap_bin_const_t key
Definition coap_dtls.h:419
coap_bin_const_t identity
Definition coap_dtls.h:418
The structure used for defining the Client PSK setup data to be used.
Definition coap_dtls.h:448
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition coap_dtls.h:469
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition coap_dtls.h:468
The structure that holds the PKI key information.
Definition coap_dtls.h:321
coap_pki_key_define_t define
for definable type keys
Definition coap_dtls.h:328
union coap_dtls_key_t::@3 key
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:322
The structure used for defining the PKI setup data to be used.
Definition coap_dtls.h:354
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition coap_dtls.h:372
The structure used for defining the Server PSK setup data to be used.
Definition coap_dtls.h:535
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:562
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition coap_dtls.h:554
void * id_call_back_arg
Passed in to the Identity callback function.
Definition coap_dtls.h:555
coap_layer_write_t l_write
coap_const_char_ptr_t public_cert
define: Public Cert
Definition coap_dtls.h:303
coap_asn1_privatekey_type_t private_key_type
define: ASN1 Private Key Type (if needed)
Definition coap_dtls.h:311
coap_const_char_ptr_t private_key
define: Private Key
Definition coap_dtls.h:304
coap_const_char_ptr_t ca
define: Common CA Certificate
Definition coap_dtls.h:302
size_t public_cert_len
define Public Cert length (if needed)
Definition coap_dtls.h:306
coap_pki_define_t private_key_def
define: Private Key type definition
Definition coap_dtls.h:310
size_t private_key_len
define Private Key length (if needed)
Definition coap_dtls.h:307
coap_pki_define_t ca_def
define: Common CA type definition
Definition coap_dtls.h:308
coap_pki_define_t public_cert_def
define: Public Cert type definition
Definition coap_dtls.h:309
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_socket_t sock
socket object for the session, if any
coap_addr_tuple_t addr_info
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_layer_func_t lfunc[COAP_LAYER_LAST]
Layer functions to use.
CoAP string data definition with const data.
Definition coap_str.h:46
const uint8_t * s
read-only string data
Definition coap_str.h:48
size_t length
length of string
Definition coap_str.h:47
The structure used for returning the underlying (D)TLS library information.
Definition coap_dtls.h:125
uint64_t built_version
(D)TLS Built against Library Version
Definition coap_dtls.h:128
coap_tls_library_t type
Library type.
Definition coap_dtls.h:127
uint64_t version
(D)TLS runtime Library Version
Definition coap_dtls.h:126
const uint8_t * u_byte
unsigned char ptr
Definition coap_str.h:74