libcoap 4.3.5-develop-daa4e05
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#ifdef COAP_WITH_LIBTINYDTLS
21
22/* We want TinyDTLS versions of these, not libcoap versions */
23#undef PACKAGE_BUGREPORT
24#undef PACKAGE_NAME
25#undef PACKAGE_STRING
26#undef PACKAGE_TARNAME
27#undef PACKAGE_URL
28#undef PACKAGE_VERSION
29
30#ifndef RIOT_VERSION
31#include <tinydtls/tinydtls.h>
32#include <tinydtls/dtls.h>
33#include <tinydtls/dtls_debug.h>
34#include <tinydtls/dtls_time.h>
35#else /* RIOT_VERSION */
36#include <tinydtls.h>
37#include <dtls.h>
38#include <dtls_debug.h>
39#include <dtls_time.h>
40#endif /* RIOT_VERSION */
41
42typedef struct coap_tiny_context_t {
43 struct dtls_context_t *dtls_context;
44 coap_context_t *coap_context;
45#ifdef DTLS_ECC
46 coap_dtls_pki_t setup_data;
47 coap_binary_t *priv_key;
48 coap_binary_t *pub_key;
49#endif /* DTLS_ECC */
50#if (DTLS_MAX_CID_LENGTH > 0)
51 uint8_t use_cid;
52#endif /* DTLS_MAX_CID_LENGTH > 0 */
53} coap_tiny_context_t;
54
55#if ! defined(DTLS_PSK) && ! defined(DTLS_ECC)
56#error Neither DTLS_PSK or DTLS_ECC defined
57#endif /* ! DTLS_PSK && ! DTLS_ECC */
58
59static dtls_tick_t dtls_tick_0 = 0;
60static coap_tick_t coap_tick_0 = 0;
61
62int
64 return 1;
65}
66
67/*
68 * return 0 failed
69 * 1 passed
70 */
71int
73#ifdef DTLS_PSK
74 return 1;
75#else /* ! DTLS_PSK */
76 return 0;
77#endif /* ! DTLS_PSK */
78}
79
80/*
81 * return 0 failed
82 * 1 passed
83 */
84int
86 return 0;
87}
88
89/*
90 * return 0 failed
91 * 1 passed
92 */
93int
95 return 0;
96}
97
98/*
99 * return 0 failed
100 * 1 passed
101 */
102int
104#ifdef DTLS_ECC
105 return 1;
106#else /* ! DTLS_ECC */
107 return 0;
108#endif /* ! DTLS_ECC */
109}
110
111/*
112 * return 0 failed
113 * 1 passed
114 */
115int
117#if (DTLS_MAX_CID_LENGTH > 0)
118 return 1;
119#else /* ! DTLS_MAX_CID_LENGTH > 0 */
120 return 0;
121#endif /* ! DTLS_MAX_CID_LENGTH > 0 */
122}
123
124#if COAP_CLIENT_SUPPORT
125/*
126 * TinyDTLS only supports client CID if compiled appropriately, and
127 * has CID support (i.e DTLS_MAX_CID_LENGTH is defined and used).
128 */
129int
130coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) {
131#if (DTLS_MAX_CID_LENGTH > 0)
132 c_context->testing_cids = every;
133 return 1;
134#else /* ! DTLS_MAX_CID_LENGTH > 0 */
135 (void)c_context;
136 (void)every;
137 return 0;
138#endif /* ! DTLS_MAX_CID_LENGTH > 0 */
139}
140#endif /* COAP_CLIENT_SUPPORT */
141
142static coap_log_t
143dtls_map_logging(log_t d_level) {
144 /* DTLS_LOG_ERR is missing, so account for the gap */
145 switch (d_level) {
146 case DTLS_LOG_EMERG:
147 return COAP_LOG_EMERG;
148 break;
149 case DTLS_LOG_ALERT:
150 return COAP_LOG_ALERT;
151 break;
152 case DTLS_LOG_CRIT:
153 return COAP_LOG_CRIT;
154 break;
155 case DTLS_LOG_WARN:
156 return COAP_LOG_WARN;
157 break;
158 case DTLS_LOG_NOTICE:
159 return COAP_LOG_NOTICE;
160 break;
161 case DTLS_LOG_INFO:
162 return COAP_LOG_INFO;
163 break;
164 case DTLS_LOG_DEBUG:
165 default:
166 return COAP_LOG_DEBUG;
167 break;
168 }
169 return COAP_LOG_DEBUG;
170}
171#ifdef HAVE_DTLS_SET_LOG_HANDLER
172/* Valid after TinyDTLS submodule has been updated */
173static void
174dtls_logging(log_t d_level, const char *message) {
175 coap_log_t c_level = dtls_map_logging(d_level);
176
177 coap_dtls_log(c_level, "%s", message);
178}
179#endif /* HAVE_DTLS_SET_LOG_HANDLER */
180
181void
182coap_dtls_startup(void) {
183 dtls_init();
184 dtls_ticks(&dtls_tick_0);
185 coap_ticks(&coap_tick_0);
186#ifdef HAVE_DTLS_SET_LOG_HANDLER
187 /* Valid after TinyDTLS submodule has been updated */
188 dtls_set_log_handler(dtls_logging);
189#endif /* HAVE_DTLS_SET_LOG_HANDLER */
191}
192
193void
194coap_dtls_shutdown(void) {
196}
197
198void *
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, coap_session->context,
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 /* Need to build asn.1 certificate - code taken from tinydtls */
677 uint8 *p;
678 uint8 buf[DTLS_CE_LENGTH];
679 coap_session_t *c_session;
680 coap_address_t remote_addr;
681
682 /* Certificate
683 *
684 * Start message construction at beginning of buffer. */
685 p = buf;
686
687 memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
688 p += sizeof(cert_asn1_header);
689
690 memcpy(p, other_pub_x, key_size);
691 p += key_size;
692
693 memcpy(p, other_pub_y, key_size);
694 p += key_size;
695
696 assert(p <= (buf + sizeof(buf)));
697
698 get_session_addr(dtls_session, &remote_addr);
699 c_session = coap_session_get_by_peer(t_context->coap_context,
700 &remote_addr, dtls_session->ifindex);
701 if (!c_session)
702 return -3;
703 coap_lock_callback_ret(ret, t_context->coap_context,
704 t_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN,
705 buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg));
706 if (!ret) {
707 return -1;
708 }
709 }
710 return 0;
711}
712
713static dtls_handler_t ec_cb = {
714 .write = dtls_send_to_peer,
715 .read = dtls_application_data,
716 .get_user_parameters = dtls_update_user_parameters,
717 .event = dtls_event,
718#ifdef DTLS_PSK
719 .get_psk_info = NULL,
720#endif /* DTLS_PSK */
721 .get_ecdsa_key = get_ecdsa_key,
722 .verify_ecdsa_key = verify_ecdsa_key
723};
724#endif /* DTLS_ECC */
725
726static dtls_handler_t psk_cb = {
727 .write = dtls_send_to_peer,
728 .read = dtls_application_data,
729 .get_user_parameters = dtls_update_user_parameters,
730 .event = dtls_event,
731#ifdef DTLS_PSK
732 .get_psk_info = get_psk_info,
733#endif /* DTLS_PSK */
734#ifdef DTLS_ECC
735 .get_ecdsa_key = NULL,
736 .verify_ecdsa_key = NULL
737#endif /* DTLS_ECC */
738};
739
740void *
742 coap_tiny_context_t *t_context = coap_malloc_type(COAP_DTLS_CONTEXT, sizeof(coap_tiny_context_t));
743 struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL;
744 if (!dtls_context)
745 goto error;
746 memset(t_context, 0, sizeof(coap_tiny_context_t));
747 t_context->coap_context = coap_context;
748 t_context->dtls_context = dtls_context;
749 dtls_set_handler(dtls_context, &psk_cb);
750 return t_context;
751error:
752 if (t_context)
754 if (dtls_context)
755 coap_dtls_free_context(dtls_context);
756 return NULL;
757}
758
759void
760coap_dtls_free_context(void *handle) {
761 if (handle) {
762 coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
763#ifdef DTLS_ECC
764 if (t_context->priv_key) {
765 coap_delete_binary(t_context->priv_key);
766 t_context->priv_key = NULL;
767 }
768 if (t_context->pub_key) {
769 coap_delete_binary(t_context->pub_key);
770 t_context->pub_key = NULL;
771 }
772#endif /* DTLS_ECC */
773 if (t_context->dtls_context)
774 dtls_free_context(t_context->dtls_context);
776 }
777}
778
779static session_t *
780coap_dtls_new_session(coap_session_t *session) {
781 session_t *dtls_session = coap_malloc_type(COAP_DTLS_SESSION, sizeof(session_t));
782
783 if (dtls_session) {
784 /* create tinydtls session object from remote address and local
785 * endpoint handle */
786 dtls_session_init(dtls_session);
787 put_session_addr(&session->addr_info.remote, dtls_session);
788 dtls_session->ifindex = session->ifindex;
789 coap_log_debug("***new session %p\n", (void *)dtls_session);
790 }
791
792 return dtls_session;
793}
794
795#if COAP_SERVER_SUPPORT
796void *
798 return coap_dtls_new_session(session);
799}
800#endif /* COAP_SERVER_SUPPORT */
801
802#if COAP_CLIENT_SUPPORT
803void *
805 dtls_peer_t *peer;
806 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
807 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
808 session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL;
809
810 if (!dtls_session)
811 return NULL;
812 peer =
813 dtls_get_peer(dtls_context, dtls_session);
814
815 if (!peer) {
816 /* The peer connection does not yet exist. */
817 /* dtls_connect() returns a value greater than zero if a new
818 * connection attempt is made, 0 for session reuse. */
819 if (dtls_connect(dtls_context, dtls_session) >= 0) {
820 peer =
821 dtls_get_peer(dtls_context, dtls_session);
822 }
823 }
824
825 if (!peer) {
826 /* delete existing session because the peer object has been invalidated */
827 coap_free_type(COAP_DTLS_SESSION, dtls_session);
828 dtls_session = NULL;
829 }
830
831 return dtls_session;
832}
833#endif /* COAP_CLIENT_SUPPORT */
834
835void
837 (void)session;
838}
839
840void
842 coap_tiny_context_t *t_context =
843 (coap_tiny_context_t *)coap_session->context->dtls_context;
844 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
845
846 if (dtls_context == NULL)
847 return;
848 if (coap_session->tls && dtls_context) {
849 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->tls);
850 if (peer)
851 dtls_reset_peer(dtls_context, peer);
852 else
853 dtls_close(dtls_context, (session_t *)coap_session->tls);
854 coap_log_debug("***removed session %p\n", coap_session->tls);
855 coap_free_type(COAP_DTLS_SESSION, coap_session->tls);
856 coap_session->tls = NULL;
857 coap_handle_event_lkd(coap_session->context, COAP_EVENT_DTLS_CLOSED, coap_session);
858 }
859}
860
861ssize_t
863 const uint8_t *data,
864 size_t data_len) {
865 int res;
866 uint8_t *data_rw;
867 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
868 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
869
870 assert(dtls_context);
871
872 coap_event_dtls = -1;
873 coap_log_debug("* %s: dtls: sent %4d bytes\n",
874 coap_session_str(session), (int)data_len);
875 /* Need to do this to not get a compiler warning about const parameters */
876 memcpy(&data_rw, &data, sizeof(data_rw));
877 res = dtls_write(dtls_context,
878 (session_t *)session->tls, data_rw, data_len);
879
880 if (res < 0)
881 coap_log_warn("coap_dtls_send: cannot send PDU\n");
882
883 if (coap_event_dtls >= 0) {
884 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
885 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
886 coap_handle_event_lkd(session->context, coap_event_dtls, session);
887 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) {
888#if (DTLS_MAX_CID_LENGTH > 0) && COAP_CLIENT_SUPPORT
889 if (session->type == COAP_SESSION_TYPE_CLIENT) {
890 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)session->tls);
891 dtls_security_parameters_t *security = dtls_security_params(peer);
892
893 if (security->write_cid_length > 0) {
894 session->negotiated_cid = 1;
895 } else {
896 coap_log_info("** %s: CID was not negotiated\n", coap_session_str(session));
897 session->negotiated_cid = 0;
898 }
899 }
900#endif /* DTLS_MAX_CID_LENGTH > 0 && COAP_CLIENT_SUPPORT */
901 coap_session_connected(session);
902 } else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) {
904 }
905 }
906
907 return res;
908}
909
910int
912 return 1;
913}
914
916coap_dtls_get_context_timeout(void *tiny_context) {
917 clock_time_t next = 0;
918 coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
919 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
920 if (tiny_context)
921 dtls_check_retransmit(dtls_context, &next);
922 if (next > 0)
923 return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND +
924 coap_tick_0;
925 return 0;
926}
927
930 (void)session;
931 (void)now;
932 return 0;
933}
934
935/*
936 * return 1 timed out
937 * 0 still timing out
938 */
939int
941 (void)session;
942 return 0;
943}
944
945int
947 const uint8_t *data,
948 size_t data_len
949 ) {
950 session_t *dtls_session = (session_t *)session->tls;
951 int err;
952 uint8_t *data_rw;
953 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
954 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
955
956 assert(dtls_context);
957 coap_event_dtls = -1;
958 /* Need to do this to not get a compiler warning about const parameters */
959 memcpy(&data_rw, &data, sizeof(data_rw));
960 err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len);
961
962 if (err) {
963 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
964 }
965
966 if (coap_event_dtls >= 0) {
967 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
968 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
969 coap_handle_event_lkd(session->context, coap_event_dtls, session);
970 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) {
971 coap_session_connected(session);
972#if (DTLS_MAX_CID_LENGTH > 0) && COAP_CLIENT_SUPPORT
973 if (session->type == COAP_SESSION_TYPE_CLIENT) {
974 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)session->tls);
975 dtls_security_parameters_t *security = dtls_security_params(peer);
976
977 if (security->write_cid_length > 0) {
978 session->negotiated_cid = 1;
979 } else {
980 session->negotiated_cid = 0;
981 }
982 }
983#endif /* DTLS_MAX_CID_LENGTH > 0 && COAP_CLIENT_SUPPORT */
984 } else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) {
986 err = -1;
987 }
988 }
989
990 return err;
991}
992
993#if COAP_SERVER_SUPPORT
994int
996 const uint8_t *data,
997 size_t data_len
998 ) {
999 session_t dtls_session;
1000 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
1001 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
1002 uint8_t *data_rw;
1003
1004 assert(dtls_context);
1005 dtls_session_init(&dtls_session);
1006 put_session_addr(&session->addr_info.remote, &dtls_session);
1007 dtls_session.ifindex = session->ifindex;
1008 /* Need to do this to not get a compiler warning about const parameters */
1009 memcpy(&data_rw, &data, sizeof(data_rw));
1010 int res = dtls_handle_message(dtls_context, &dtls_session,
1011 data_rw, (int)data_len);
1012 if (res >= 0) {
1013 if (dtls_get_peer(dtls_context, &dtls_session))
1014 res = 1;
1015 else
1016 res = 0;
1017 }
1018 return res;
1019}
1020#endif /* COAP_SERVER_SUPPORT */
1021
1022unsigned int
1024 (void)session;
1025 return 13 + 8 + 8;
1026}
1027
1028int
1030 return 0;
1031}
1032
1035 static coap_tls_version_t version;
1036 const char *vers = dtls_package_version();
1037
1038 version.version = 0;
1039 if (vers) {
1040 long int p1, p2 = 0, p3 = 0;
1041 char *endptr;
1042
1043 p1 = strtol(vers, &endptr, 10);
1044 if (*endptr == '.') {
1045 p2 = strtol(endptr+1, &endptr, 10);
1046 if (*endptr == '.') {
1047 p3 = strtol(endptr+1, &endptr, 10);
1048 }
1049 }
1050 version.version = (p1 << 16) | (p2 << 8) | p3;
1051 }
1052 version.built_version = version.version;
1054 return &version;
1055}
1056
1057#ifdef DTLS_ECC
1058static const uint8_t b64_6[256] = {
1059 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1060 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1061 /* + / */
1062 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
1063 /* 0 1 2 3 4 5 6 7 8 9 = */
1064 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
1065 /* A B C D E F G H I J K L M N O */
1066 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1067 /* P Q R S T U V W X Y Z */
1068 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
1069 /* a b c d e f g h i j k l m n o */
1070 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
1071 /* p q r s t u v w x y z */
1072 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 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 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
1081};
1082
1083/* caller must free off returned coap_binary_t* */
1084static coap_binary_t *
1085pem_base64_decode(const uint8_t *data, size_t size) {
1086 uint8_t *tbuf = coap_malloc_type(COAP_STRING, size);
1087 size_t nbytesdecoded;
1088 size_t i;
1089 coap_binary_t *decoded;
1090 uint8_t *ptr;
1091 uint8_t *out;
1092 size_t nb64bytes = 0;
1093
1094 for (i = 0; i < size; i++) {
1095 switch (data[i]) {
1096 case ' ':
1097 case '\r':
1098 case '\n':
1099 case '\t':
1100 break;
1101 default:
1102 if (b64_6[data[i]] == 64)
1103 goto end;
1104 tbuf[nb64bytes++] = data[i];
1105 break;
1106 }
1107 }
1108
1109end:
1110 nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
1111 decoded = coap_new_binary(nbytesdecoded + 1);
1112 if (!decoded)
1113 return NULL;
1114
1115 out = decoded->s;
1116 ptr = tbuf;
1117
1118 while (nb64bytes > 4) {
1119 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1120 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1121 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1122 ptr += 4;
1123 nb64bytes -= 4;
1124 }
1125
1126 /* Note: (nb64bytes == 1) is an error */
1127 if (nb64bytes > 1) {
1128 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1129 }
1130 if (nb64bytes > 2) {
1131 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1132 }
1133 if (nb64bytes > 3) {
1134 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1135 }
1136
1137 decoded->length = nbytesdecoded - ((4 - nb64bytes) & 3);
1139 return decoded;
1140}
1141
1142typedef coap_binary_t *(*asn1_callback)(const uint8_t *data, size_t size);
1143
1144static int
1145asn1_verify_privkey(const uint8_t *data, size_t size) {
1146 /* Check if we have the private key (with optional leading 0x00) */
1147 /* skip leading 0x00 */
1148 if (size - 1 == DTLS_EC_KEY_SIZE && *data == '\000') {
1149 --size;
1150 ++data;
1151 }
1152
1153 /* Check if we have the private key */
1154 if (size != DTLS_EC_KEY_SIZE)
1155 return 0;
1156
1157 return 1;
1158}
1159
1160static int
1161asn1_verify_pubkey(const uint8_t *data, size_t size) {
1162 (void)data;
1163
1164 /* We have the public key
1165 (with a leading 0x00 (no unused bits) 0x04 (not compressed() */
1166 if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
1167 return 0;
1168
1169 return 1;
1170}
1171
1172static int
1173asn1_verify_curve(const uint8_t *data, size_t size) {
1174 static uint8_t prime256v1_oid[] =
1175 /* OID 1.2.840.10045.3.1.7 */
1176 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
1177
1178 /* Check that we have the correct EC (only one supported) */
1179 if (size != sizeof(prime256v1_oid) ||
1180 memcmp(data, prime256v1_oid, size) != 0)
1181 return 0;
1182
1183 return 1;
1184}
1185
1186static int
1187asn1_verify_pkcs8_version(const uint8_t *data, size_t size) {
1188 /* Check that we have the version */
1189 if (size != 1 || *data != 0)
1190 return 0;
1191
1192 return 1;
1193}
1194
1195static int
1196asn1_verify_ec_identifier(const uint8_t *data, size_t size) {
1197 static uint8_t ec_public_key_oid[] =
1198 /* OID 1.2.840.10045.2.1 */
1199 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
1200
1201 /* Check that we have the correct ecPublicKey */
1202 if (size != sizeof(ec_public_key_oid) ||
1203 memcmp(data, ec_public_key_oid, size) != 0)
1204 return 0;
1205
1206 return 1;
1207}
1208
1209static int
1210asn1_verify_ec_key(const uint8_t *data, size_t size) {
1211 (void)data;
1212
1213 if (size == 0)
1214 return 0;
1215
1216 return 1;
1217}
1218
1219static int
1220asn1_derive_keys(coap_tiny_context_t *t_context,
1221 const uint8_t *priv_data, size_t priv_len,
1222 const uint8_t *pub_data, size_t pub_len,
1223 int is_pkcs8) {
1224 coap_binary_t *test;
1225
1226 t_context->priv_key = get_asn1_tag(COAP_ASN1_OCTETSTRING, priv_data,
1227 priv_len, asn1_verify_privkey);
1228 if (!t_context->priv_key) {
1229 coap_log_info("EC Private Key (RPK) invalid\n");
1230 return 0;
1231 }
1232 /* skip leading 0x00 */
1233 if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
1234 t_context->priv_key->s[0] == '\000') {
1235 t_context->priv_key->length--;
1236 t_context->priv_key->s++;
1237 }
1238
1239 if (!is_pkcs8) {
1240 /* pkcs8 abstraction tested for valid eliptic curve */
1241 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, priv_data, priv_len,
1242 asn1_verify_curve);
1243 if (!test) {
1244 coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1245 coap_delete_binary(t_context->priv_key);
1246 t_context->priv_key = NULL;
1247 return 0;
1248 }
1249 coap_delete_binary(test);
1250 }
1251
1252 t_context->pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, pub_data, pub_len,
1253 asn1_verify_pubkey);
1254 if (!t_context->pub_key) {
1255 coap_log_info("EC Public Key (RPK) invalid\n");
1256 coap_delete_binary(t_context->priv_key);
1257 t_context->priv_key = NULL;
1258 return 0;
1259 }
1260 /* Drop leading 0x00 and 0x04 */
1261 t_context->pub_key->s += 2;
1262 t_context->pub_key->length -= 2;
1263 dtls_set_handler(t_context->dtls_context, &ec_cb);
1264 return 1;
1265}
1266
1267static coap_binary_t *
1268ec_abstract_pkcs8_asn1(const uint8_t *asn1_ptr, size_t asn1_length) {
1269 coap_binary_t *test;
1270
1271 test = get_asn1_tag(COAP_ASN1_INTEGER, asn1_ptr, asn1_length,
1272 asn1_verify_pkcs8_version);
1273 if (!test)
1274 return 0;
1275
1276 coap_delete_binary(test);
1277
1278 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1279 asn1_verify_ec_identifier);
1280 if (!test)
1281 return 0;
1282 coap_delete_binary(test);
1283
1284 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1285 asn1_verify_curve);
1286 if (!test) {
1287 coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1288 return 0;
1289 }
1290 coap_delete_binary(test);
1291
1292 test = get_asn1_tag(COAP_ASN1_OCTETSTRING, asn1_ptr, asn1_length,
1293 asn1_verify_ec_key);
1294 return test;
1295}
1296
1297static coap_binary_t *
1298pem_decode_mem_asn1(const char *begstr, const uint8_t *str) {
1299 char *bcp = str ? strstr((const char *)str, begstr) : NULL;
1300 char *tcp = bcp ? strstr(bcp, "-----END ") : NULL;
1301
1302 if (bcp && tcp) {
1303 bcp += strlen(begstr);
1304 return pem_base64_decode((const uint8_t *)bcp, tcp - bcp);
1305 }
1306 return NULL;
1307}
1308
1309#endif /* DTLS_ECC */
1310
1311int
1313 const coap_dtls_pki_t *setup_data,
1314 const coap_dtls_role_t role) {
1315#ifdef DTLS_ECC
1316 coap_tiny_context_t *t_context;
1317 coap_binary_t *asn1_priv = NULL;
1318 coap_binary_t *asn1_pub = NULL;
1319 coap_binary_t *asn1_temp;
1320 int is_pkcs8 = 0;
1321 coap_dtls_key_t key;
1322
1323 if (!setup_data->is_rpk_not_cert) {
1324 coap_log_warn("Only RPK, not full PKI is supported\n");
1325 return 0;
1326 }
1327 if (!ctx)
1328 return 0;
1329
1330 t_context = (coap_tiny_context_t *)ctx->dtls_context;
1331 if (!t_context)
1332 return 0;
1333 if (t_context->priv_key) {
1334 coap_delete_binary(t_context->priv_key);
1335 t_context->priv_key = NULL;
1336 }
1337 if (t_context->pub_key) {
1338 coap_delete_binary(t_context->pub_key);
1339 t_context->pub_key = NULL;
1340 }
1341 t_context->setup_data = *setup_data;
1342
1343 /* Map over to the new define format to save code duplication */
1344 coap_dtls_map_key_type_to_define(setup_data, &key);
1345
1346 assert(key.key_type == COAP_PKI_KEY_DEFINE);
1347
1348 /*
1349 * Configure the Private Key
1350 */
1351 if (key.key.define.private_key.u_byte &&
1352 key.key.define.private_key.u_byte[0]) {
1353 switch (key.key.define.private_key_def) {
1354 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1355 /* Need to take PEM memory information and convert to binary */
1356 asn1_priv = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1358 if (!asn1_priv) {
1359 asn1_priv = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1361 if (!asn1_priv) {
1364 &key, role, 0);
1365 }
1366 asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->s, asn1_priv->length);
1367 if (!asn1_temp) {
1368 coap_log_info("*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1369 coap_delete_binary(asn1_priv);
1372 &key, role, 0);
1373 }
1374 coap_delete_binary(asn1_priv);
1375 asn1_priv = asn1_temp;
1376 is_pkcs8 = 1;
1377 }
1378 asn1_pub = pem_decode_mem_asn1("-----BEGIN PUBLIC KEY-----",
1380 if (!asn1_pub) {
1381 asn1_pub = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1383 if (!asn1_pub) {
1384 asn1_pub = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1386 if (!asn1_pub) {
1387 coap_log_info("*** setup_pki: (D)TLS: Public Key (RPK) invalid\n");
1388 coap_delete_binary(asn1_priv);
1391 &key, role, 0);
1392 }
1393 asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->s, asn1_pub->length);
1394 if (!asn1_temp) {
1395 coap_log_info("*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1396 coap_delete_binary(asn1_priv);
1397 coap_delete_binary(asn1_pub);
1400 &key, role, 0);
1401 }
1402 coap_delete_binary(asn1_pub);
1403 asn1_pub = asn1_temp;
1404 is_pkcs8 = 1;
1405 }
1406 }
1407 if (!asn1_derive_keys(t_context, asn1_priv->s, asn1_priv->length,
1408 asn1_pub->s, asn1_pub->length, is_pkcs8)) {
1409 coap_log_info("*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1410 coap_delete_binary(asn1_priv);
1411 coap_delete_binary(asn1_pub);
1412 return 0;
1413 }
1414 coap_delete_binary(asn1_priv);
1415 coap_delete_binary(asn1_pub);
1416 return 1;
1417 break;
1418 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1419 if (key.key.define.private_key_len > 0 &&
1421 const uint8_t *private_key = key.key.define.private_key.u_byte;
1422 size_t private_key_len = key.key.define.private_key_len;
1423
1424 /* Check to see whether this is in pkcs8 format or not */
1425 asn1_temp = ec_abstract_pkcs8_asn1(key.key.define.private_key.u_byte,
1427 if (asn1_temp) {
1428 private_key = asn1_temp->s;
1429 private_key_len = asn1_temp->length;
1430 is_pkcs8 = 1;
1431 }
1432 /* Need to take ASN1 memory information and convert to binary */
1433 if (key.key.define.public_cert.u_byte &&
1435 if (!asn1_derive_keys(t_context,
1436 private_key,
1437 private_key_len,
1440 is_pkcs8)) {
1441 coap_log_info("*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1442 coap_delete_binary(asn1_temp);
1443 return 0;
1444 }
1445 } else {
1446 if (!asn1_derive_keys(t_context,
1447 private_key,
1448 private_key_len,
1449 private_key,
1450 private_key_len,
1451 is_pkcs8)) {
1452 coap_log_info("*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1453 coap_delete_binary(asn1_temp);
1454 return 0;
1455 }
1456 }
1457 coap_delete_binary(asn1_temp);
1458 return 1;
1459 } else {
1462 &key, role, 0);
1463 }
1464 break;
1471 default:
1474 &key, role, 0);
1475 }
1476 } else {
1479 &key, role, 0);
1480 }
1481
1482 /*
1483 * Configure the Public Certificate / Key
1484 */
1485 if (key.key.define.public_cert.u_byte &&
1486 key.key.define.public_cert.u_byte[0]) {
1487 switch (key.key.define.public_cert_def) {
1490 /* done under private key */
1491 break;
1498 default:
1501 &key, role, 0);
1502 }
1503 }
1504
1505 /*
1506 * Configure the CA
1507 */
1508 if (key.key.define.ca.u_byte &&
1509 key.key.define.ca.u_byte[0]) {
1510 switch (key.key.define.ca_def) {
1513 /* Ignore if set */
1514 break;
1521 default:
1524 &key, role, 0);
1525 }
1526 }
1527
1528 if (setup_data->use_cid) {
1529#if (DTLS_MAX_CID_LENGTH == 0)
1530 coap_log_warn("TinyDTLS has no Connection-ID support\n");
1531#endif /* DTLS_MAX_CID_LENGTH == 0 */
1532 }
1533#if (DTLS_MAX_CID_LENGTH > 0)
1534 t_context->use_cid = setup_data->use_cid;
1535#endif /* DTLS_MAX_CID_LENGTH > 0 */
1536 return 1;
1537#else /* ! DTLS_ECC */
1538 (void)ctx;
1539 (void)setup_data;
1540 (void)role;
1541 coap_log_warn("TinyDTLS not compiled with ECC support\n");
1542 return 0;
1543#endif /* ! DTLS_ECC */
1544}
1545
1546int
1548 const char *ca_file COAP_UNUSED,
1549 const char *ca_path COAP_UNUSED
1550 ) {
1551 coap_log_warn("Root CAs PKI not supported\n");
1552 return 0;
1553}
1554
1555int
1557 return 0;
1558}
1559
1560#if COAP_CLIENT_SUPPORT
1561int
1563 coap_dtls_cpsk_t *setup_data) {
1564 coap_tiny_context_t *t_context;
1565
1566 if (!setup_data)
1567 return 0;
1568
1569 t_context = (coap_tiny_context_t *)coap_context->dtls_context;
1570 if (!t_context)
1571 return 0;
1572
1573 if (setup_data->use_cid) {
1574#if (DTLS_MAX_CID_LENGTH == 0)
1575 coap_log_warn("TinyDTLS has no Connection-ID support\n");
1576#endif /* DTLS_MAX_CID_LENGTH == 0 */
1577 }
1578#if (DTLS_MAX_CID_LENGTH > 0)
1579 t_context->use_cid = setup_data->use_cid;
1580#endif /* DTLS_MAX_CID_LENGTH > 0 */
1581#ifdef DTLS_PSK
1582 if (setup_data->ec_jpake) {
1583 coap_log_warn("TinyDTLS has no EC-JPAKE support\n");
1584 }
1585 return 1;
1586#else /* ! DTLS_PSK */
1587 coap_log_warn("TinyDTLS not compiled with PSK support\n");
1588 return 0;
1589#endif /* ! DTLS_PSK */
1590}
1591#endif /* COAP_CLIENT_SUPPORT */
1592
1593#if COAP_SERVER_SUPPORT
1594int
1596 coap_dtls_spsk_t *setup_data
1597 ) {
1598 if (!setup_data)
1599 return 0;
1600
1601#ifdef DTLS_PSK
1602 if (setup_data->validate_sni_call_back) {
1603 coap_log_warn("CoAP Server with TinyDTLS does not support SNI selection\n");
1604 }
1605
1606 if (setup_data->ec_jpake) {
1607 coap_log_warn("TinyDTLS has no EC-JPAKE support\n");
1608 }
1609 return 1;
1610#else /* ! DTLS_PSK */
1611 coap_log_warn("TinyDTLS not compiled with PSK support\n");
1612 return 0;
1613#endif /* ! DTLS_PSK */
1614}
1615#endif /* COAP_SERVER_SUPPORT */
1616
1617int
1619 return 1;
1620}
1621
1622#if !COAP_DISABLE_TCP
1623#if COAP_CLIENT_SUPPORT
1624void *
1626 return NULL;
1627}
1628#endif /* COAP_CLIENT_SUPPORT */
1629
1630#if COAP_SERVER_SUPPORT
1631void *
1633 return NULL;
1634}
1635#endif /* COAP_SERVER_SUPPORT */
1636
1637void
1639}
1640
1641/*
1642 * strm
1643 * return +ve Number of bytes written.
1644 * -1 Error (error in errno).
1645 */
1646ssize_t
1648 const uint8_t *data COAP_UNUSED,
1649 size_t data_len COAP_UNUSED
1650 ) {
1651 return -1;
1652}
1653
1654/*
1655 * strm
1656 * return >=0 Number of bytes read.
1657 * -1 Error (error in errno).
1658 */
1659ssize_t
1661 uint8_t *data COAP_UNUSED,
1662 size_t data_len COAP_UNUSED) {
1663 errno = ENODEV;
1664 return -1;
1665}
1666#endif /* !COAP_DISABLE_TCP */
1667
1668#if COAP_SERVER_SUPPORT
1670coap_digest_setup(void) {
1671 dtls_sha256_ctx *digest_ctx = coap_malloc_type(COAP_STRING, sizeof(dtls_sha256_ctx));
1672
1673 if (digest_ctx) {
1674 dtls_sha256_init(digest_ctx);
1675 }
1676
1677 return digest_ctx;
1678}
1679
1680void
1682 coap_free_type(COAP_STRING, digest_ctx);
1683}
1684
1685int
1687 const uint8_t *data,
1688 size_t data_len) {
1689 dtls_sha256_update(digest_ctx, data, data_len);
1690
1691 return 1;
1692}
1693
1694int
1696 coap_digest_t *digest_buffer) {
1697 dtls_sha256_final((uint8_t *)digest_buffer, digest_ctx);
1698
1699 coap_digest_free(digest_ctx);
1700 return 1;
1701}
1702#endif /* COAP_SERVER_SUPPORT */
1703
1704#if COAP_WS_SUPPORT
1705int
1707 const coap_bin_const_t *data,
1708 coap_bin_const_t **hash) {
1709 SHA1Context sha1_context;
1710 coap_binary_t *dummy = NULL;
1711
1712 (void)alg;
1713
1714 SHA1Reset(&sha1_context);
1715 if (SHA1Input(&sha1_context, data->s, data->length) != shaSuccess)
1716 return 0;
1718 if (!dummy)
1719 return 0;
1720 if (SHA1Result(&sha1_context, dummy->s) != shaSuccess) {
1722 return 0;
1723 }
1724 *hash = (coap_bin_const_t *)(dummy);
1725 return 1;
1726}
1727#endif /* COAP_WS_SUPPORT */
1728
1729#if COAP_OSCORE_SUPPORT
1730
1731int
1733 return 1;
1734}
1735
1736/*
1737 * The struct cipher_algs and the function get_cipher_alg() are used to
1738 * determine which cipher type to use for creating the required cipher
1739 * suite object.
1740 */
1741static struct cipher_algs {
1742 cose_alg_t alg;
1743 u_int cipher_type;
1744} ciphers[] = {
1746};
1747
1748static u_int
1749get_cipher_alg(cose_alg_t alg) {
1750 size_t idx;
1751
1752 for (idx = 0; idx < sizeof(ciphers)/sizeof(struct cipher_algs); idx++) {
1753 if (ciphers[idx].alg == alg)
1754 return ciphers[idx].cipher_type;
1755 }
1756 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
1757 return 0;
1758}
1759
1760/*
1761 * The struct hmac_algs and the function get_hmac_alg() are used to
1762 * determine which hmac type to use for creating the required hmac
1763 * suite object.
1764 */
1765static struct hmac_algs {
1766 cose_hmac_alg_t hmac_alg;
1767 u_int hmac_type;
1768} hmacs[] = {
1770};
1771
1772static u_int
1773get_hmac_alg(cose_hmac_alg_t hmac_alg) {
1774 size_t idx;
1775
1776 for (idx = 0; idx < sizeof(hmacs)/sizeof(struct hmac_algs); idx++) {
1777 if (hmacs[idx].hmac_alg == hmac_alg)
1778 return hmacs[idx].hmac_type;
1779 }
1780 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
1781 return 0;
1782}
1783
1784int
1786 return get_cipher_alg(alg);
1787}
1788
1789int
1791 cose_hmac_alg_t hmac_alg;
1792
1793 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
1794 return 0;
1795 return get_hmac_alg(hmac_alg);
1796}
1797
1798int
1800 coap_bin_const_t *data,
1801 coap_bin_const_t *aad,
1802 uint8_t *result, size_t *max_result_len) {
1803 int num_bytes;
1804 const coap_crypto_aes_ccm_t *ccm;
1805 dtls_ccm_params_t dtls_params;
1806 coap_bin_const_t laad;
1807
1808 if (data == NULL)
1809 return 0;
1810
1811 assert(params);
1812
1813 if (get_cipher_alg(params->alg) == 0) {
1814 coap_log_debug("coap_crypto_encrypt: algorithm %d not supported\n",
1815 params->alg);
1816 return 0;
1817 }
1818
1819 ccm = &params->params.aes;
1820 if (*max_result_len < (data->length + ccm->tag_len)) {
1821 coap_log_warn("coap_encrypt: result buffer too small\n");
1822 return 0;
1823 }
1824
1825 dtls_params.nonce = ccm->nonce;
1826 dtls_params.tag_length = ccm->tag_len;
1827 dtls_params.l = ccm->l;
1828
1829 if (aad) {
1830 laad = *aad;
1831 } else {
1832 laad.s = NULL;
1833 laad.length = 0;
1834 }
1835
1836 num_bytes = dtls_encrypt_params(&dtls_params,
1837 data->s, data->length,
1838 result,
1839 ccm->key.s, ccm->key.length,
1840 laad.s, laad.length);
1841 if (num_bytes < 0) {
1842 return 0;
1843 }
1844 *max_result_len = num_bytes;
1845 return 1;
1846}
1847
1848int
1850 coap_bin_const_t *data,
1851 coap_bin_const_t *aad,
1852 uint8_t *result, size_t *max_result_len) {
1853 int num_bytes;
1854 const coap_crypto_aes_ccm_t *ccm;
1855 dtls_ccm_params_t dtls_params;
1856 coap_bin_const_t laad;
1857
1858 if (data == NULL)
1859 return 0;
1860
1861 assert(params);
1862
1863 if (get_cipher_alg(params->alg) == 0) {
1864 coap_log_debug("coap_crypto_decrypt: algorithm %d not supported\n",
1865 params->alg);
1866 return 0;
1867 }
1868
1869 ccm = &params->params.aes;
1870
1871 if ((*max_result_len + ccm->tag_len) < data->length) {
1872 coap_log_warn("coap_decrypt: result buffer too small\n");
1873 return 0;
1874 }
1875
1876 dtls_params.nonce = ccm->nonce;
1877 dtls_params.tag_length = ccm->tag_len;
1878 dtls_params.l = ccm->l;
1879
1880 if (aad) {
1881 laad = *aad;
1882 } else {
1883 laad.s = NULL;
1884 laad.length = 0;
1885 }
1886
1887 num_bytes = dtls_decrypt_params(&dtls_params,
1888 data->s, data->length,
1889 result,
1890 ccm->key.s, ccm->key.length,
1891 laad.s, laad.length);
1892 if (num_bytes < 0) {
1893 return 0;
1894 }
1895 *max_result_len = num_bytes;
1896 return 1;
1897}
1898
1899int
1901 coap_bin_const_t *data, coap_bin_const_t **hmac) {
1902 dtls_hmac_context_t hmac_context;
1903 int num_bytes;
1905
1906 if (data == NULL)
1907 return 0;
1908
1909 if (get_hmac_alg(hmac_alg) == 0) {
1910 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
1911 return 0;
1912 }
1913
1914 dummy = coap_new_binary(DTLS_SHA256_DIGEST_LENGTH);
1915 if (dummy == NULL)
1916 return 0;
1917
1918 dtls_hmac_init(&hmac_context, key->s, key->length);
1919 dtls_hmac_update(&hmac_context, data->s, data->length);
1920 num_bytes = dtls_hmac_finalize(&hmac_context, dummy->s);
1921
1922 if (num_bytes != DTLS_SHA256_DIGEST_LENGTH) {
1924 return 0;
1925 }
1926 *hmac = (coap_bin_const_t *)dummy;
1927 return 1;
1928}
1929
1930#endif /* COAP_OSCORE_SUPPORT */
1931
1932#else /* !COAP_WITH_LIBTINYDTLS */
1933
1934#ifdef __clang__
1935/* Make compilers happy that do not like empty modules. As this function is
1936 * never used, we ignore -Wunused-function at the end of compiling this file
1937 */
1938#pragma GCC diagnostic ignored "-Wunused-function"
1939#endif
1940static inline void
1941dummy(void) {
1942}
1943
1944#endif /* COAP_WITH_LIBTINYDTLS */
@ COAP_NACK_TLS_FAILED
Definition coap_io.h:66
@ COAP_LAYER_TLS
Library specific build wrapper for coap_internal.h.
@ COAP_DTLS_SESSION
Definition coap_mem.h:50
@ COAP_DTLS_CONTEXT
Definition coap_mem.h:60
@ COAP_STRING
Definition coap_mem.h:39
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
int coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, const coap_dtls_pki_t *setup_data COAP_UNUSED, const coap_dtls_role_t role COAP_UNUSED)
Definition coap_notls.c:108
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition coap_notls.c: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:143
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition coap_time.h:158
int coap_handle_event_lkd(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
Definition coap_net.c:4783
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:2793
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
int coap_crypto_hmac(cose_hmac_alg_t hmac_alg, coap_bin_const_t *key, coap_bin_const_t *data, coap_bin_const_t **hmac)
Create a HMAC hash of the provided data.
int coap_crypto_aead_decrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Decrypt the provided encrypted data into plaintext.
int coap_crypto_aead_encrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Encrypt the provided plaintext data.
int coap_crypto_hash(cose_alg_t alg, const coap_bin_const_t *data, coap_bin_const_t **hash)
Create a hash of the provided data.
int coap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg)
Check whether the defined hkdf algorithm is supported by the underlying crypto library.
int coap_crypto_check_cipher_alg(cose_alg_t alg)
Check whether the defined cipher algorithm is supported by the underlying crypto library.
void * coap_tls_new_server_session(coap_session_t *coap_session)
Create a TLS new server-side session.
const coap_bin_const_t * coap_get_session_client_psk_identity(const coap_session_t *coap_session)
Get the current client's PSK identity.
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition coap_notls.c: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:44
#define COAP_DTLS_RPK_CERT_CN
Definition coap_dtls.h:49
coap_tls_library_t
Definition coap_dtls.h:70
@ COAP_PKI_KEY_DEF_PKCS11
The PKI key type is PKCS11 (pkcs11:...).
Definition coap_dtls.h:245
@ COAP_PKI_KEY_DEF_DER_BUF
The PKI key type is DER buffer (ASN.1).
Definition coap_dtls.h:242
@ COAP_PKI_KEY_DEF_PEM_BUF
The PKI key type is PEM buffer.
Definition coap_dtls.h:236
@ COAP_PKI_KEY_DEF_PEM
The PKI key type is PEM file.
Definition coap_dtls.h:234
@ COAP_PKI_KEY_DEF_ENGINE
The PKI key type is to be passed to ENGINE.
Definition coap_dtls.h:251
@ COAP_PKI_KEY_DEF_RPK_BUF
The PKI key type is RPK in buffer.
Definition coap_dtls.h:238
@ COAP_PKI_KEY_DEF_DER
The PKI key type is DER file.
Definition coap_dtls.h:240
@ COAP_PKI_KEY_DEF_PKCS11_RPK
The PKI key type is PKCS11 w/ RPK (pkcs11:...).
Definition coap_dtls.h:248
@ COAP_PKI_KEY_DEFINE
The individual PKI key types are Definable.
Definition coap_dtls.h:172
@ COAP_ASN1_PKEY_EC
EC type.
Definition coap_dtls.h:157
@ COAP_TLS_LIBRARY_TINYDTLS
Using TinyDTLS library.
Definition coap_dtls.h:72
@ COAP_EVENT_DTLS_CLOSED
Triggerred when (D)TLS session closed.
Definition coap_event.h:39
@ COAP_EVENT_DTLS_CONNECTED
Triggered when (D)TLS session connected.
Definition coap_event.h:41
@ COAP_EVENT_DTLS_RENEGOTIATE
Triggered when (D)TLS session renegotiated.
Definition coap_event.h:43
@ COAP_EVENT_DTLS_ERROR
Triggered when (D)TLS error occurs.
Definition coap_event.h:45
#define coap_lock_callback_ret(r, c, func)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:120
coap_log_t
Logging type.
Definition coap_debug.h:50
coap_log_t coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition coap_notls.c:176
#define coap_dtls_log(level,...)
Logging function.
Definition coap_debug.h:300
void coap_dtls_set_log_level(coap_log_t level)
Sets the (D)TLS logging level to the specified level.
Definition coap_notls.c:171
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
Definition coap_debug.h:108
#define coap_log_warn(...)
Definition coap_debug.h:102
@ COAP_LOG_INFO
Definition coap_debug.h:57
@ COAP_LOG_OSCORE
Definition coap_debug.h:59
@ COAP_LOG_EMERG
Definition coap_debug.h:51
@ COAP_LOG_DTLS_BASE
Definition coap_debug.h:60
@ COAP_LOG_NOTICE
Definition coap_debug.h:56
@ COAP_LOG_DEBUG
Definition coap_debug.h:58
@ COAP_LOG_ALERT
Definition coap_debug.h:52
@ COAP_LOG_CRIT
Definition coap_debug.h:53
@ COAP_LOG_ERR
Definition coap_debug.h:54
@ COAP_LOG_WARN
Definition coap_debug.h:55
int cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg)
cose_hkdf_alg_t
cose_hmac_alg_t
cose_alg_t
@ COSE_HMAC_ALG_HMAC256_256
@ COSE_ALGORITHM_AES_CCM_16_64_128
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
int coap_session_refresh_psk_identity(coap_session_t *session, const coap_bin_const_t *psk_identity)
Refresh the session's current pre-shared identity (PSK).
void coap_session_disconnected_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
coap_session_t * coap_session_get_by_peer(const coap_context_t *ctx, const coap_address_t *remote_addr, int ifindex)
Get the session associated with the specified remote_addr and index.
@ COAP_SESSION_TYPE_CLIENT
client-side
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition coap_str.c:77
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition coap_str.c:105
int coap_dtls_cid_is_supported(void)
Check whether (D)TLS CID is available.
Definition coap_notls.c:86
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition coap_notls.c:50
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition coap_notls.c:41
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition coap_notls.c:36
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition coap_notls.c:59
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition coap_notls.c:77
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition coap_notls.c:68
#define COAP_UNUSED
Definition libcoap.h:70
coap_address_t remote
remote address and port
Definition coap_io.h:56
Multi-purpose address abstraction.
socklen_t size
size of addr
struct sockaddr_in sin
struct sockaddr_in6 sin6
struct sockaddr sa
union coap_address_t::@0 addr
CoAP binary data definition with const data.
Definition coap_str.h:64
size_t length
length of binary data
Definition coap_str.h:65
const uint8_t * s
read-only binary data
Definition coap_str.h:66
CoAP binary data definition.
Definition coap_str.h:56
size_t length
length of binary data
Definition coap_str.h:57
uint8_t * s
binary data
Definition coap_str.h:58
The CoAP stack's global state is stored in a coap_context_t object.
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:379
coap_bin_const_t key
Definition coap_dtls.h:381
coap_bin_const_t identity
Definition coap_dtls.h:380
The structure used for defining the Client PSK setup data to be used.
Definition coap_dtls.h:410
uint8_t use_cid
Set to 1 if DTLS Connection ID is to be used.
Definition coap_dtls.h:417
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition coap_dtls.h:434
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition coap_dtls.h:433
uint8_t ec_jpake
Set to COAP_DTLS_CPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:415
The structure that holds the PKI key information.
Definition coap_dtls.h:279
coap_pki_key_define_t define
for definable type keys
Definition coap_dtls.h:286
union coap_dtls_key_t::@3 key
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:280
The structure used for defining the PKI setup data to be used.
Definition coap_dtls.h:312
uint8_t use_cid
1 if DTLS Connection ID is to be used (Client only, server always enabled) if supported
Definition coap_dtls.h:333
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition coap_dtls.h:330
The structure used for defining the Server PSK setup data to be used.
Definition coap_dtls.h:501
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:530
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition coap_dtls.h:522
void * id_call_back_arg
Passed in to the Identity callback function.
Definition coap_dtls.h:523
uint8_t ec_jpake
Set to COAP_DTLS_SPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:506
coap_layer_write_t l_write
coap_const_char_ptr_t public_cert
define: Public Cert
Definition coap_dtls.h:261
coap_asn1_privatekey_type_t private_key_type
define: ASN1 Private Key Type (if needed)
Definition coap_dtls.h:269
coap_const_char_ptr_t private_key
define: Private Key
Definition coap_dtls.h:262
coap_const_char_ptr_t ca
define: Common CA Certificate
Definition coap_dtls.h:260
size_t public_cert_len
define Public Cert length (if needed)
Definition coap_dtls.h:264
coap_pki_define_t private_key_def
define: Private Key type definition
Definition coap_dtls.h:268
size_t private_key_len
define Private Key length (if needed)
Definition coap_dtls.h:265
coap_pki_define_t ca_def
define: Common CA type definition
Definition coap_dtls.h:266
coap_pki_define_t public_cert_def
define: Public Cert type definition
Definition coap_dtls.h:267
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_socket_t sock
socket object for the session, if any
coap_addr_tuple_t addr_info
remote/local address info
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
uint8_t negotiated_cid
Set for a client if CID negotiated.
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:46
const uint8_t * s
read-only string data
Definition coap_str.h:48
size_t length
length of string
Definition coap_str.h:47
The structure used for returning the underlying (D)TLS library information.
Definition coap_dtls.h:83
uint64_t built_version
(D)TLS Built against Library Version
Definition coap_dtls.h:86
coap_tls_library_t type
Library type.
Definition coap_dtls.h:85
uint64_t version
(D)TLS runtime Library Version
Definition coap_dtls.h:84
const uint8_t * u_byte
unsigned char ptr
Definition coap_str.h:74