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