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