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