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