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