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