libcoap 4.3.5-develop-3f4d08f
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_handle_event_lkd(session->context, coap_event_dtls, session);
912 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) {
913#if (DTLS_MAX_CID_LENGTH > 0) && COAP_CLIENT_SUPPORT
914 if (session->type == COAP_SESSION_TYPE_CLIENT) {
915 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)session->tls);
916 dtls_security_parameters_t *security = dtls_security_params(peer);
917
918 if (security->write_cid_length > 0) {
919 session->negotiated_cid = 1;
920 } else {
921 coap_log_info("** %s: CID was not negotiated\n", coap_session_str(session));
922 session->negotiated_cid = 0;
923 }
924 }
925#endif /* DTLS_MAX_CID_LENGTH > 0 && COAP_CLIENT_SUPPORT */
926 coap_session_connected(session);
927 } else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) {
928 res = -1;
929 }
930 }
931
932 return res;
933}
934
935int
937 return 1;
938}
939
941coap_dtls_get_context_timeout(void *tiny_context) {
942 clock_time_t next = 0;
943 coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
944 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
945 if (tiny_context)
946 dtls_check_retransmit(dtls_context, &next);
947 if (next > 0)
948 return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND +
949 coap_tick_0;
950 return 0;
951}
952
955 (void)session;
956 (void)now;
957 return 0;
958}
959
960/*
961 * return 1 timed out
962 * 0 still timing out
963 */
964int
966 (void)session;
967 return 0;
968}
969
970int
972 const uint8_t *data,
973 size_t data_len
974 ) {
975 session_t *dtls_session = (session_t *)session->tls;
976 int err;
977 uint8_t *data_rw;
978 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
979 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
980
981 assert(dtls_context);
982 coap_event_dtls = -1;
983 /* Need to do this to not get a compiler warning about const parameters */
984 memcpy(&data_rw, &data, sizeof(data_rw));
985 err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len);
986
987 if (err) {
988 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
989 }
990
991 if (coap_event_dtls >= 0) {
992 coap_handle_event_lkd(session->context, coap_event_dtls, session);
993 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) {
994 coap_session_connected(session);
995#if (DTLS_MAX_CID_LENGTH > 0) && COAP_CLIENT_SUPPORT
996 if (session->type == COAP_SESSION_TYPE_CLIENT) {
997 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)session->tls);
998 dtls_security_parameters_t *security = dtls_security_params(peer);
999
1000 if (security->write_cid_length > 0) {
1001 session->negotiated_cid = 1;
1002 } else {
1003 session->negotiated_cid = 0;
1004 }
1005 }
1006#endif /* DTLS_MAX_CID_LENGTH > 0 && COAP_CLIENT_SUPPORT */
1007 } else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) {
1009 err = -1;
1010 }
1011 }
1012
1013 return err;
1014}
1015
1016#if COAP_SERVER_SUPPORT
1017int
1018coap_dtls_hello(coap_session_t *session,
1019 const uint8_t *data,
1020 size_t data_len
1021 ) {
1022 session_t dtls_session;
1023 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
1024 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
1025 uint8_t *data_rw;
1026
1027 assert(dtls_context);
1028 dtls_session_init(&dtls_session);
1029 put_session_addr(&session->addr_info.remote, &dtls_session);
1030 dtls_session.ifindex = session->ifindex;
1031 /* Need to do this to not get a compiler warning about const parameters */
1032 memcpy(&data_rw, &data, sizeof(data_rw));
1033 int res = dtls_handle_message(dtls_context, &dtls_session,
1034 data_rw, (int)data_len);
1035 if (res >= 0) {
1036 if (dtls_get_peer(dtls_context, &dtls_session))
1037 res = 1;
1038 else
1039 res = 0;
1040 }
1041 return res;
1042}
1043#endif /* COAP_SERVER_SUPPORT */
1044
1045unsigned int
1047 (void)session;
1048 return 13 + 8 + 8;
1049}
1050
1051int
1053 return 0;
1054}
1055
1058 static coap_tls_version_t version;
1059 const char *vers = dtls_package_version();
1060
1061 version.version = 0;
1062 if (vers) {
1063 long int p1, p2 = 0, p3 = 0;
1064 char *endptr;
1065
1066 p1 = strtol(vers, &endptr, 10);
1067 if (*endptr == '.') {
1068 p2 = strtol(endptr+1, &endptr, 10);
1069 if (*endptr == '.') {
1070 p3 = strtol(endptr+1, &endptr, 10);
1071 }
1072 }
1073 version.version = (p1 << 16) | (p2 << 8) | p3;
1074 }
1075 version.built_version = version.version;
1077 return &version;
1078}
1079
1080#ifdef DTLS_ECC
1081static const uint8_t b64_6[256] = {
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 /* + / */
1085 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
1086 /* 0 1 2 3 4 5 6 7 8 9 = */
1087 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
1088 /* A B C D E F G H I J K L M N O */
1089 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1090 /* P Q R S T U V W X Y Z */
1091 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
1092 /* a b c d e f g h i j k l m n o */
1093 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
1094 /* p q r s t u v w x y z */
1095 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
1096 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1097 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1098 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1099 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 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};
1105
1106/* caller must free off returned coap_binary_t* */
1107static coap_binary_t *
1108pem_base64_decode(const uint8_t *data, size_t size) {
1109 uint8_t *tbuf = coap_malloc_type(COAP_STRING, size);
1110 size_t nbytesdecoded;
1111 size_t i;
1112 coap_binary_t *decoded;
1113 uint8_t *ptr;
1114 uint8_t *out;
1115 size_t nb64bytes = 0;
1116
1117 for (i = 0; i < size; i++) {
1118 switch (data[i]) {
1119 case ' ':
1120 case '\r':
1121 case '\n':
1122 case '\t':
1123 break;
1124 default:
1125 if (b64_6[data[i]] == 64)
1126 goto end;
1127 tbuf[nb64bytes++] = data[i];
1128 break;
1129 }
1130 }
1131
1132end:
1133 nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
1134 decoded = coap_new_binary(nbytesdecoded + 1);
1135 if (!decoded)
1136 return NULL;
1137
1138 out = decoded->s;
1139 ptr = tbuf;
1140
1141 while (nb64bytes > 4) {
1142 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1143 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1144 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1145 ptr += 4;
1146 nb64bytes -= 4;
1147 }
1148
1149 /* Note: (nb64bytes == 1) is an error */
1150 if (nb64bytes > 1) {
1151 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1152 }
1153 if (nb64bytes > 2) {
1154 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1155 }
1156 if (nb64bytes > 3) {
1157 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1158 }
1159
1160 decoded->length = nbytesdecoded - ((4 - nb64bytes) & 3);
1162 return decoded;
1163}
1164
1165typedef coap_binary_t *(*asn1_callback)(const uint8_t *data, size_t size);
1166
1167static int
1168asn1_verify_privkey(const uint8_t *data, size_t size) {
1169 /* Check if we have the private key (with optional leading 0x00) */
1170 /* skip leading 0x00 */
1171 if (size - 1 == DTLS_EC_KEY_SIZE && *data == '\000') {
1172 --size;
1173 ++data;
1174 }
1175
1176 /* Check if we have the private key */
1177 if (size != DTLS_EC_KEY_SIZE)
1178 return 0;
1179
1180 return 1;
1181}
1182
1183static int
1184asn1_verify_pubkey(const uint8_t *data, size_t size) {
1185 (void)data;
1186
1187 /* We have the public key
1188 (with a leading 0x00 (no unused bits) 0x04 (not compressed() */
1189 if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
1190 return 0;
1191
1192 return 1;
1193}
1194
1195static int
1196asn1_verify_curve(const uint8_t *data, size_t size) {
1197 static uint8_t prime256v1_oid[] =
1198 /* OID 1.2.840.10045.3.1.7 */
1199 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
1200
1201 /* Check that we have the correct EC (only one supported) */
1202 if (size != sizeof(prime256v1_oid) ||
1203 memcmp(data, prime256v1_oid, size) != 0)
1204 return 0;
1205
1206 return 1;
1207}
1208
1209static int
1210asn1_verify_pkcs8_version(const uint8_t *data, size_t size) {
1211 /* Check that we have the version */
1212 if (size != 1 || *data != 0)
1213 return 0;
1214
1215 return 1;
1216}
1217
1218static int
1219asn1_verify_ec_identifier(const uint8_t *data, size_t size) {
1220 static uint8_t ec_public_key_oid[] =
1221 /* OID 1.2.840.10045.2.1 */
1222 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
1223
1224 /* Check that we have the correct ecPublicKey */
1225 if (size != sizeof(ec_public_key_oid) ||
1226 memcmp(data, ec_public_key_oid, size) != 0)
1227 return 0;
1228
1229 return 1;
1230}
1231
1232static int
1233asn1_verify_ec_key(const uint8_t *data, size_t size) {
1234 (void)data;
1235
1236 if (size == 0)
1237 return 0;
1238
1239 return 1;
1240}
1241
1242static int
1243asn1_derive_keys(coap_tiny_context_t *t_context,
1244 const uint8_t *priv_data, size_t priv_len,
1245 const uint8_t *pub_data, size_t pub_len,
1246 int is_pkcs8) {
1247 coap_binary_t *test;
1248
1249 t_context->priv_key = get_asn1_tag(COAP_ASN1_OCTETSTRING, priv_data,
1250 priv_len, asn1_verify_privkey);
1251 if (!t_context->priv_key) {
1252 coap_log_info("EC Private Key (RPK) invalid\n");
1253 return 0;
1254 }
1255 /* skip leading 0x00 */
1256 if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
1257 t_context->priv_key->s[0] == '\000') {
1258 t_context->priv_key->length--;
1259 t_context->priv_key->s++;
1260 }
1261
1262 if (!is_pkcs8) {
1263 /* pkcs8 abstraction tested for valid eliptic curve */
1264 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, priv_data, priv_len,
1265 asn1_verify_curve);
1266 if (!test) {
1267 coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1268 coap_delete_binary(t_context->priv_key);
1269 t_context->priv_key = NULL;
1270 return 0;
1271 }
1272 coap_delete_binary(test);
1273 }
1274
1275 t_context->pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, pub_data, pub_len,
1276 asn1_verify_pubkey);
1277 if (!t_context->pub_key) {
1278 coap_log_info("EC Public Key (RPK) invalid\n");
1279 coap_delete_binary(t_context->priv_key);
1280 t_context->priv_key = NULL;
1281 return 0;
1282 }
1283 /* Drop leading 0x00 and 0x04 */
1284 t_context->pub_key->s += 2;
1285 t_context->pub_key->length -= 2;
1286 dtls_set_handler(t_context->dtls_context, &ec_cb);
1287 return 1;
1288}
1289
1290static coap_binary_t *
1291ec_abstract_pkcs8_asn1(const uint8_t *asn1_ptr, size_t asn1_length) {
1292 coap_binary_t *test;
1293
1294 test = get_asn1_tag(COAP_ASN1_INTEGER, asn1_ptr, asn1_length,
1295 asn1_verify_pkcs8_version);
1296 if (!test)
1297 return 0;
1298
1299 coap_delete_binary(test);
1300
1301 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1302 asn1_verify_ec_identifier);
1303 if (!test)
1304 return 0;
1305 coap_delete_binary(test);
1306
1307 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1308 asn1_verify_curve);
1309 if (!test) {
1310 coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1311 return 0;
1312 }
1313 coap_delete_binary(test);
1314
1315 test = get_asn1_tag(COAP_ASN1_OCTETSTRING, asn1_ptr, asn1_length,
1316 asn1_verify_ec_key);
1317 return test;
1318}
1319
1320static coap_binary_t *
1321pem_decode_mem_asn1(const char *begstr, const uint8_t *str) {
1322 char *bcp = str ? strstr((const char *)str, begstr) : NULL;
1323 char *tcp = bcp ? strstr(bcp, "-----END ") : NULL;
1324
1325 if (bcp && tcp) {
1326 bcp += strlen(begstr);
1327 return pem_base64_decode((const uint8_t *)bcp, tcp - bcp);
1328 }
1329 return NULL;
1330}
1331
1332#endif /* DTLS_ECC */
1333
1334int
1336 const coap_dtls_pki_t *setup_data,
1337 const coap_dtls_role_t role) {
1338#ifdef DTLS_ECC
1339 coap_tiny_context_t *t_context;
1340 coap_binary_t *asn1_priv = NULL;
1341 coap_binary_t *asn1_pub = NULL;
1342 coap_binary_t *asn1_temp;
1343 int is_pkcs8 = 0;
1344 coap_dtls_key_t key;
1345
1346 if (!setup_data->is_rpk_not_cert) {
1347 coap_log_warn("Only RPK, not full PKI is supported\n");
1348 return 0;
1349 }
1350 if (!ctx)
1351 return 0;
1352
1353 t_context = (coap_tiny_context_t *)ctx->dtls_context;
1354 if (!t_context)
1355 return 0;
1356 if (t_context->priv_key) {
1357 coap_delete_binary(t_context->priv_key);
1358 t_context->priv_key = NULL;
1359 }
1360 if (t_context->pub_key) {
1361 coap_delete_binary(t_context->pub_key);
1362 t_context->pub_key = NULL;
1363 }
1364 t_context->setup_data = *setup_data;
1365
1366 /* Map over to the new define format to save code duplication */
1367 coap_dtls_map_key_type_to_define(setup_data, &key);
1368
1369 assert(key.key_type == COAP_PKI_KEY_DEFINE);
1370
1371 /*
1372 * Configure the Private Key
1373 */
1374 if (key.key.define.private_key.u_byte &&
1375 key.key.define.private_key.u_byte[0]) {
1376 switch (key.key.define.private_key_def) {
1377 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1378 /* Need to take PEM memory information and convert to binary */
1379 asn1_priv = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1381 if (!asn1_priv) {
1382 asn1_priv = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1384 if (!asn1_priv) {
1387 &key, role, 0);
1388 }
1389 asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->s, asn1_priv->length);
1390 if (!asn1_temp) {
1391 coap_log_info("*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1392 coap_delete_binary(asn1_priv);
1395 &key, role, 0);
1396 }
1397 coap_delete_binary(asn1_priv);
1398 asn1_priv = asn1_temp;
1399 is_pkcs8 = 1;
1400 }
1401 asn1_pub = pem_decode_mem_asn1("-----BEGIN PUBLIC KEY-----",
1403 if (!asn1_pub) {
1404 asn1_pub = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1406 if (!asn1_pub) {
1407 asn1_pub = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1409 if (!asn1_pub) {
1410 coap_log_info("*** setup_pki: (D)TLS: Public Key (RPK) invalid\n");
1411 coap_delete_binary(asn1_priv);
1414 &key, role, 0);
1415 }
1416 asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->s, asn1_pub->length);
1417 if (!asn1_temp) {
1418 coap_log_info("*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1419 coap_delete_binary(asn1_priv);
1420 coap_delete_binary(asn1_pub);
1423 &key, role, 0);
1424 }
1425 coap_delete_binary(asn1_pub);
1426 asn1_pub = asn1_temp;
1427 is_pkcs8 = 1;
1428 }
1429 }
1430 if (!asn1_derive_keys(t_context, asn1_priv->s, asn1_priv->length,
1431 asn1_pub->s, asn1_pub->length, is_pkcs8)) {
1432 coap_log_info("*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1433 coap_delete_binary(asn1_priv);
1434 coap_delete_binary(asn1_pub);
1435 return 0;
1436 }
1437 coap_delete_binary(asn1_priv);
1438 coap_delete_binary(asn1_pub);
1439 return 1;
1440 break;
1441 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1442 if (key.key.define.private_key_len > 0 &&
1444 const uint8_t *private_key = key.key.define.private_key.u_byte;
1445 size_t private_key_len = key.key.define.private_key_len;
1446
1447 /* Check to see whether this is in pkcs8 format or not */
1448 asn1_temp = ec_abstract_pkcs8_asn1(key.key.define.private_key.u_byte,
1450 if (asn1_temp) {
1451 private_key = asn1_temp->s;
1452 private_key_len = asn1_temp->length;
1453 is_pkcs8 = 1;
1454 }
1455 /* Need to take ASN1 memory information and convert to binary */
1456 if (key.key.define.public_cert.u_byte &&
1458 if (!asn1_derive_keys(t_context,
1459 private_key,
1460 private_key_len,
1463 is_pkcs8)) {
1464 coap_log_info("*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1465 coap_delete_binary(asn1_temp);
1466 return 0;
1467 }
1468 } else {
1469 if (!asn1_derive_keys(t_context,
1470 private_key,
1471 private_key_len,
1472 private_key,
1473 private_key_len,
1474 is_pkcs8)) {
1475 coap_log_info("*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1476 coap_delete_binary(asn1_temp);
1477 return 0;
1478 }
1479 }
1480 coap_delete_binary(asn1_temp);
1481 return 1;
1482 } else {
1485 &key, role, 0);
1486 }
1487 break;
1494 default:
1497 &key, role, 0);
1498 }
1499 } else {
1502 &key, role, 0);
1503 }
1504
1505 /*
1506 * Configure the Public Certificate / Key
1507 */
1508 if (key.key.define.public_cert.u_byte &&
1509 key.key.define.public_cert.u_byte[0]) {
1510 switch (key.key.define.public_cert_def) {
1513 /* done under private key */
1514 break;
1521 default:
1524 &key, role, 0);
1525 }
1526 }
1527
1528 /*
1529 * Configure the CA
1530 */
1531 if (key.key.define.ca.u_byte &&
1532 key.key.define.ca.u_byte[0]) {
1533 switch (key.key.define.ca_def) {
1536 /* Ignore if set */
1537 break;
1544 default:
1547 &key, role, 0);
1548 }
1549 }
1550
1551 if (setup_data->use_cid) {
1552#if (DTLS_MAX_CID_LENGTH == 0)
1553 coap_log_warn("TinyDTLS has no Connection-ID support\n");
1554#endif /* DTLS_MAX_CID_LENGTH == 0 */
1555 }
1556#if (DTLS_MAX_CID_LENGTH > 0)
1557 t_context->use_cid = setup_data->use_cid;
1558#endif /* DTLS_MAX_CID_LENGTH > 0 */
1559 return 1;
1560#else /* ! DTLS_ECC */
1561 (void)ctx;
1562 (void)setup_data;
1563 (void)role;
1564 coap_log_warn("TinyDTLS not compiled with ECC support\n");
1565 return 0;
1566#endif /* ! DTLS_ECC */
1567}
1568
1569int
1571 const char *ca_file COAP_UNUSED,
1572 const char *ca_path COAP_UNUSED
1573 ) {
1574 coap_log_warn("Root CAs PKI not supported\n");
1575 return 0;
1576}
1577
1578int
1580 return 0;
1581}
1582
1583#if COAP_CLIENT_SUPPORT
1584int
1585coap_dtls_context_set_cpsk(coap_context_t *coap_context,
1586 coap_dtls_cpsk_t *setup_data) {
1587 coap_tiny_context_t *t_context;
1588
1589 if (!setup_data)
1590 return 0;
1591
1592 t_context = (coap_tiny_context_t *)coap_context->dtls_context;
1593 if (!t_context)
1594 return 0;
1595
1596 if (setup_data->use_cid) {
1597#if (DTLS_MAX_CID_LENGTH == 0)
1598 coap_log_warn("TinyDTLS has no Connection-ID support\n");
1599#endif /* DTLS_MAX_CID_LENGTH == 0 */
1600 }
1601#if (DTLS_MAX_CID_LENGTH > 0)
1602 t_context->use_cid = setup_data->use_cid;
1603#endif /* DTLS_MAX_CID_LENGTH > 0 */
1604#ifdef DTLS_PSK
1605 if (setup_data->ec_jpake) {
1606 coap_log_warn("TinyDTLS has no EC-JPAKE support\n");
1607 }
1608 return 1;
1609#else /* ! DTLS_PSK */
1610 coap_log_warn("TinyDTLS not compiled with PSK support\n");
1611 return 0;
1612#endif /* ! DTLS_PSK */
1613}
1614#endif /* COAP_CLIENT_SUPPORT */
1615
1616#if COAP_SERVER_SUPPORT
1617int
1618coap_dtls_context_set_spsk(coap_context_t *coap_context COAP_UNUSED,
1619 coap_dtls_spsk_t *setup_data
1620 ) {
1621 if (!setup_data)
1622 return 0;
1623
1624#ifdef DTLS_PSK
1625 if (setup_data->validate_sni_call_back) {
1626 coap_log_warn("CoAP Server with TinyDTLS does not support SNI selection\n");
1627 }
1628
1629 if (setup_data->ec_jpake) {
1630 coap_log_warn("TinyDTLS has no EC-JPAKE support\n");
1631 }
1632 return 1;
1633#else /* ! DTLS_PSK */
1634 coap_log_warn("TinyDTLS not compiled with PSK support\n");
1635 return 0;
1636#endif /* ! DTLS_PSK */
1637}
1638#endif /* COAP_SERVER_SUPPORT */
1639
1640int
1642 return 1;
1643}
1644
1645#if !COAP_DISABLE_TCP
1646#if COAP_CLIENT_SUPPORT
1647void *
1648coap_tls_new_client_session(coap_session_t *session COAP_UNUSED) {
1649 return NULL;
1650}
1651#endif /* COAP_CLIENT_SUPPORT */
1652
1653#if COAP_SERVER_SUPPORT
1654void *
1655coap_tls_new_server_session(coap_session_t *session COAP_UNUSED) {
1656 return NULL;
1657}
1658#endif /* COAP_SERVER_SUPPORT */
1659
1660void
1662}
1663
1664/*
1665 * strm
1666 * return +ve Number of bytes written.
1667 * -1 Error (error in errno).
1668 */
1669ssize_t
1671 const uint8_t *data COAP_UNUSED,
1672 size_t data_len COAP_UNUSED
1673 ) {
1674 return -1;
1675}
1676
1677/*
1678 * strm
1679 * return >=0 Number of bytes read.
1680 * -1 Error (error in errno).
1681 */
1682ssize_t
1684 uint8_t *data COAP_UNUSED,
1685 size_t data_len COAP_UNUSED) {
1686 errno = ENODEV;
1687 return -1;
1688}
1689#endif /* !COAP_DISABLE_TCP */
1690
1691#if COAP_SERVER_SUPPORT
1692coap_digest_ctx_t *
1693coap_digest_setup(void) {
1694 dtls_sha256_ctx *digest_ctx = coap_malloc_type(COAP_STRING, sizeof(dtls_sha256_ctx));
1695
1696 if (digest_ctx) {
1697 dtls_sha256_init(digest_ctx);
1698 }
1699
1700 return digest_ctx;
1701}
1702
1703void
1704coap_digest_free(coap_digest_ctx_t *digest_ctx) {
1705 coap_free_type(COAP_STRING, digest_ctx);
1706}
1707
1708int
1709coap_digest_update(coap_digest_ctx_t *digest_ctx,
1710 const uint8_t *data,
1711 size_t data_len) {
1712 dtls_sha256_update(digest_ctx, data, data_len);
1713
1714 return 1;
1715}
1716
1717int
1718coap_digest_final(coap_digest_ctx_t *digest_ctx,
1719 coap_digest_t *digest_buffer) {
1720 dtls_sha256_final((uint8_t *)digest_buffer, digest_ctx);
1721
1722 coap_digest_free(digest_ctx);
1723 return 1;
1724}
1725#endif /* COAP_SERVER_SUPPORT */
1726
1727#if COAP_WS_SUPPORT
1728int
1730 const coap_bin_const_t *data,
1731 coap_bin_const_t **hash) {
1732 SHA1Context sha1_context;
1734
1735 (void)alg;
1736
1737 SHA1Reset(&sha1_context);
1738 if (SHA1Input(&sha1_context, data->s, data->length) != shaSuccess)
1739 return 0;
1741 if (!dummy)
1742 return 0;
1743 if (SHA1Result(&sha1_context, dummy->s) != shaSuccess) {
1745 return 0;
1746 }
1747 *hash = (coap_bin_const_t *)(dummy);
1748 return 1;
1749}
1750#endif /* COAP_WS_SUPPORT */
1751
1752#if COAP_OSCORE_SUPPORT
1753
1754int
1756 return 1;
1757}
1758
1759/*
1760 * The struct cipher_algs and the function get_cipher_alg() are used to
1761 * determine which cipher type to use for creating the required cipher
1762 * suite object.
1763 */
1764static struct cipher_algs {
1765 cose_alg_t alg;
1766 uint32_t cipher_type;
1767} ciphers[] = {
1769};
1770
1771static uint32_t
1772get_cipher_alg(cose_alg_t alg) {
1773 size_t idx;
1774
1775 for (idx = 0; idx < sizeof(ciphers)/sizeof(struct cipher_algs); idx++) {
1776 if (ciphers[idx].alg == alg)
1777 return ciphers[idx].cipher_type;
1778 }
1779 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
1780 return 0;
1781}
1782
1783/*
1784 * The struct hmac_algs and the function get_hmac_alg() are used to
1785 * determine which hmac type to use for creating the required hmac
1786 * suite object.
1787 */
1788static struct hmac_algs {
1789 cose_hmac_alg_t hmac_alg;
1790 uint32_t hmac_type;
1791} hmacs[] = {
1793};
1794
1795static uint32_t
1796get_hmac_alg(cose_hmac_alg_t hmac_alg) {
1797 size_t idx;
1798
1799 for (idx = 0; idx < sizeof(hmacs)/sizeof(struct hmac_algs); idx++) {
1800 if (hmacs[idx].hmac_alg == hmac_alg)
1801 return hmacs[idx].hmac_type;
1802 }
1803 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
1804 return 0;
1805}
1806
1807int
1809 return get_cipher_alg(alg);
1810}
1811
1812int
1814 cose_hmac_alg_t hmac_alg;
1815
1816 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
1817 return 0;
1818 return get_hmac_alg(hmac_alg);
1819}
1820
1821int
1823 coap_bin_const_t *data,
1824 coap_bin_const_t *aad,
1825 uint8_t *result, size_t *max_result_len) {
1826 int num_bytes;
1827 const coap_crypto_aes_ccm_t *ccm;
1828 dtls_ccm_params_t dtls_params;
1829 coap_bin_const_t laad;
1830
1831 if (data == NULL)
1832 return 0;
1833
1834 assert(params);
1835
1836 if (get_cipher_alg(params->alg) == 0) {
1837 coap_log_debug("coap_crypto_encrypt: algorithm %d not supported\n",
1838 params->alg);
1839 return 0;
1840 }
1841
1842 ccm = &params->params.aes;
1843 if (*max_result_len < (data->length + ccm->tag_len)) {
1844 coap_log_warn("coap_encrypt: result buffer too small\n");
1845 return 0;
1846 }
1847
1848 dtls_params.nonce = ccm->nonce;
1849 dtls_params.tag_length = ccm->tag_len;
1850 dtls_params.l = ccm->l;
1851
1852 if (aad) {
1853 laad = *aad;
1854 } else {
1855 laad.s = NULL;
1856 laad.length = 0;
1857 }
1858
1859 num_bytes = dtls_encrypt_params(&dtls_params,
1860 data->s, data->length,
1861 result,
1862 ccm->key.s, ccm->key.length,
1863 laad.s, laad.length);
1864 if (num_bytes < 0) {
1865 return 0;
1866 }
1867 *max_result_len = num_bytes;
1868 return 1;
1869}
1870
1871int
1873 coap_bin_const_t *data,
1874 coap_bin_const_t *aad,
1875 uint8_t *result, size_t *max_result_len) {
1876 int num_bytes;
1877 const coap_crypto_aes_ccm_t *ccm;
1878 dtls_ccm_params_t dtls_params;
1879 coap_bin_const_t laad;
1880
1881 if (data == NULL)
1882 return 0;
1883
1884 assert(params);
1885
1886 if (get_cipher_alg(params->alg) == 0) {
1887 coap_log_debug("coap_crypto_decrypt: algorithm %d not supported\n",
1888 params->alg);
1889 return 0;
1890 }
1891
1892 ccm = &params->params.aes;
1893
1894 if ((*max_result_len + ccm->tag_len) < data->length) {
1895 coap_log_warn("coap_decrypt: result buffer too small\n");
1896 return 0;
1897 }
1898
1899 dtls_params.nonce = ccm->nonce;
1900 dtls_params.tag_length = ccm->tag_len;
1901 dtls_params.l = ccm->l;
1902
1903 if (aad) {
1904 laad = *aad;
1905 } else {
1906 laad.s = NULL;
1907 laad.length = 0;
1908 }
1909
1910 num_bytes = dtls_decrypt_params(&dtls_params,
1911 data->s, data->length,
1912 result,
1913 ccm->key.s, ccm->key.length,
1914 laad.s, laad.length);
1915 if (num_bytes < 0) {
1916 return 0;
1917 }
1918 *max_result_len = num_bytes;
1919 return 1;
1920}
1921
1922int
1924 coap_bin_const_t *data, coap_bin_const_t **hmac) {
1925 dtls_hmac_context_t hmac_context;
1926 int num_bytes;
1928
1929 if (data == NULL)
1930 return 0;
1931
1932 if (get_hmac_alg(hmac_alg) == 0) {
1933 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
1934 return 0;
1935 }
1936
1937 dummy = coap_new_binary(DTLS_SHA256_DIGEST_LENGTH);
1938 if (dummy == NULL)
1939 return 0;
1940
1941 dtls_hmac_init(&hmac_context, key->s, key->length);
1942 dtls_hmac_update(&hmac_context, data->s, data->length);
1943 num_bytes = dtls_hmac_finalize(&hmac_context, dummy->s);
1944
1945 if (num_bytes != DTLS_SHA256_DIGEST_LENGTH) {
1947 return 0;
1948 }
1949 *hmac = (coap_bin_const_t *)dummy;
1950 return 1;
1951}
1952
1953#endif /* COAP_OSCORE_SUPPORT */
1954
1955#else /* ! COAP_WITH_LIBTINYDTLS */
1956
1957#ifdef __clang__
1958/* Make compilers happy that do not like empty modules. As this function is
1959 * never used, we ignore -Wunused-function at the end of compiling this file
1960 */
1961#pragma GCC diagnostic ignored "-Wunused-function"
1962#endif
1963static inline void
1964dummy(void) {
1965}
1966
1967#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:5079
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:2994
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