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