libcoap 4.3.4-develop-c081bb6
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
18#include "coap3/coap_internal.h"
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} coap_tiny_context_t;
51
52#if ! defined(DTLS_PSK) && ! defined(DTLS_ECC)
53#error Neither DTLS_PSK or DTLS_ECC defined
54#endif /* ! DTLS_PSK && ! DTLS_ECC */
55
56static dtls_tick_t dtls_tick_0 = 0;
57static coap_tick_t coap_tick_0 = 0;
58
59int
61 return 1;
62}
63
64/*
65 * return 0 failed
66 * 1 passed
67 */
68int
70#ifdef DTLS_PSK
71 return 1;
72#else /* ! DTLS_PSK */
73 return 0;
74#endif /* ! DTLS_PSK */
75}
76
77/*
78 * return 0 failed
79 * 1 passed
80 */
81int
83 return 0;
84}
85
86/*
87 * return 0 failed
88 * 1 passed
89 */
90int
92 return 0;
93}
94
95/*
96 * return 0 failed
97 * 1 passed
98 */
99int
101#ifdef DTLS_ECC
102 return 1;
103#else /* ! DTLS_ECC */
104 return 0;
105#endif /* ! DTLS_ECC */
106}
107
108static coap_log_t
109dtls_map_logging(log_t d_level) {
110 /* DTLS_LOG_ERR is missing, so account for the gap */
111 switch (d_level) {
112 case DTLS_LOG_EMERG:
113 return COAP_LOG_EMERG;
114 break;
115 case DTLS_LOG_ALERT:
116 return COAP_LOG_ALERT;
117 break;
118 case DTLS_LOG_CRIT:
119 return COAP_LOG_CRIT;
120 break;
121 case DTLS_LOG_WARN:
122 return COAP_LOG_WARN;
123 break;
124 case DTLS_LOG_NOTICE:
125 return COAP_LOG_NOTICE;
126 break;
127 case DTLS_LOG_INFO:
128 return COAP_LOG_INFO;
129 break;
130 case DTLS_LOG_DEBUG:
131 default:
132 return COAP_LOG_DEBUG;
133 break;
134 }
135 return COAP_LOG_DEBUG;
136}
137#ifdef HAVE_DTLS_SET_LOG_HANDLER
138/* Valid after TinyDTLS submodule has been updated */
139static void
140dtls_logging(log_t d_level, const char *message) {
141 coap_log_t c_level = dtls_map_logging(d_level);
142
143 coap_dtls_log(c_level, "%s", message);
144}
145#endif /* HAVE_DTLS_SET_LOG_HANDLER */
146
147void
148coap_dtls_startup(void) {
149 dtls_init();
150 dtls_ticks(&dtls_tick_0);
151 coap_ticks(&coap_tick_0);
152#ifdef HAVE_DTLS_SET_LOG_HANDLER
153 /* Valid after TinyDTLS submodule has been updated */
154 dtls_set_log_handler(dtls_logging);
155#endif /* HAVE_DTLS_SET_LOG_HANDLER */
157}
158
159void
160coap_dtls_shutdown(void) {
162}
163
164void *
165coap_dtls_get_tls(const coap_session_t *c_session,
166 coap_tls_library_t *tls_lib) {
167 if (tls_lib)
168 *tls_lib = COAP_TLS_LIBRARY_TINYDTLS;
169 if (c_session && c_session->context && c_session->context->dtls_context) {
170 const coap_tiny_context_t *t_context =
171 (const coap_tiny_context_t *)c_session->context->dtls_context;
172
173 return t_context->dtls_context;
174 }
175 return NULL;
176}
177
178void
180 log_t d_level;
181
182 /* DTLS_LOG_ERR is missing, so account for the gap */
183 switch (c_level) {
184 case COAP_LOG_EMERG:
185 d_level = DTLS_LOG_EMERG;
186 break;
187 case COAP_LOG_ALERT:
188 d_level = DTLS_LOG_ALERT;
189 break;
190 case COAP_LOG_CRIT:
191 case COAP_LOG_ERR:
192 d_level = DTLS_LOG_CRIT;
193 break;
194 case COAP_LOG_WARN:
195 d_level = DTLS_LOG_WARN;
196 break;
197 case COAP_LOG_NOTICE:
198 d_level = DTLS_LOG_NOTICE;
199 break;
200 case COAP_LOG_INFO:
201 d_level = DTLS_LOG_INFO;
202 break;
203 case COAP_LOG_DEBUG:
204 case COAP_LOG_OSCORE:
206 default:
207 d_level = DTLS_LOG_DEBUG;
208 break;
209 }
210 dtls_set_log_level(d_level);
211}
212
215 log_t d_level = dtls_get_log_level();
216
217 return dtls_map_logging(d_level);
218}
219
220static void
221get_session_addr(const session_t *s, coap_address_t *a) {
222#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
223 a->addr = s->addr;
224 a->port = s->port;
225#elif defined(WITH_RIOT_SOCK)
226 if (s->addr.family == AF_INET6) {
227 a->riot.family = s->addr.family;
228 memcpy(&a->riot.addr.ipv6, &s->addr.ipv6,
229 sizeof(a->riot.addr.ipv6));
230 a->riot.port = ntohs(s->addr.port);
231 a->riot.netif = 0;
232#ifdef SOCK_HAS_IPV4
233 } else if (s->addr.family == AF_INET) {
234 a->riot.family = s->addr.family;
235 memcpy(&a->riot.addr.ipv4, &s->addr.ipv4, sizeof(a->riot.addr.ipv4));
236 a->riot.port = ntohs(s->addr.port);
237 a->riot.netif = 0;
238#endif /* SOCK_HAS_IPV4 */
239 }
240#else /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
241 if (s->addr.sa.sa_family == AF_INET6) {
242 a->size = (socklen_t)sizeof(a->addr.sin6);
243 a->addr.sin6 = s->addr.sin6;
244 } else if (s->addr.sa.sa_family == AF_INET) {
245 a->size = (socklen_t)sizeof(a->addr.sin);
246 a->addr.sin = s->addr.sin;
247 } else {
248 a->size = (socklen_t)s->size;
249 a->addr.sa = s->addr.sa;
250 }
251#endif /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
252}
253
254static void
255put_session_addr(const coap_address_t *a, session_t *s) {
256#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
257 s->size = (unsigned char)sizeof(s->addr);
258 s->addr = a->addr;
259 s->port = a->port;
260#elif defined(WITH_RIOT_SOCK)
261 if (a->riot.family == AF_INET6) {
262 s->size = sizeof(s->addr.ipv6);
263 s->addr.family = a->riot.family;
264 memcpy(&s->addr.ipv6, &a->riot.addr.ipv6,
265 sizeof(s->addr.ipv6));
266 s->addr.port = htons(a->riot.port);
267#ifdef SOCK_HAS_IPV4
268 } else if (a->r.family == AF_INET) {
269 s->size = sizeof(s->addr.ipv4);
270 s->addr.family = a->r.family;
271 memcpy(&a->addr.ipv4, &s->r.addr.ipv4, sizeof(a->addr.ipv4));
272 s->addr.port = htons(a->r.port);
273#endif /* SOCK_HAS_IPV4 */
274 }
275#else /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
276 if (a->addr.sa.sa_family == AF_INET6) {
277 s->size = (socklen_t)sizeof(s->addr.sin6);
278 s->addr.sin6 = a->addr.sin6;
279 } else if (a->addr.sa.sa_family == AF_INET) {
280 s->size = (socklen_t)sizeof(s->addr.sin);
281 s->addr.sin = a->addr.sin;
282 } else {
283 s->size = (socklen_t)a->size;
284 s->addr.sa = a->addr.sa;
285 }
286#endif /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
287}
288
289static int
290dtls_send_to_peer(struct dtls_context_t *dtls_context,
291 session_t *dtls_session, uint8 *data, size_t len) {
292 coap_tiny_context_t *t_context =
293 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
294 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
295 coap_session_t *coap_session;
296 coap_address_t remote_addr;
297
298 assert(coap_context);
299 get_session_addr(dtls_session, &remote_addr);
300 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
301 if (!coap_session) {
302 coap_log_warn("dtls_send_to_peer: cannot find local interface\n");
303 return -3;
304 }
305 return (int)coap_session->sock.lfunc[COAP_LAYER_TLS].l_write(coap_session,
306 data, len);
307}
308
309static int
310dtls_application_data(struct dtls_context_t *dtls_context,
311 session_t *dtls_session, uint8 *data, size_t len) {
312 coap_tiny_context_t *t_context =
313 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
314 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
315 coap_session_t *coap_session;
316 coap_address_t remote_addr;
317
318 assert(coap_context);
319 get_session_addr(dtls_session, &remote_addr);
320 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
321 if (!coap_session) {
322 coap_log_debug("dropped message that was received on invalid interface\n");
323 return -1;
324 }
325
326 coap_log_debug("* %s: dtls: recv %4d bytes\n",
327 coap_session_str(coap_session), (int)len);
328 return coap_handle_dgram(coap_context, coap_session, data, len);
329}
330
331static int coap_event_dtls = 0;
332
333static int
334dtls_event(struct dtls_context_t *dtls_context,
335 session_t *dtls_session,
336 dtls_alert_level_t level,
337 unsigned short code) {
338 (void)dtls_context;
339 (void)dtls_session;
340
341 if (level == DTLS_ALERT_LEVEL_FATAL)
342 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
343
344 /* handle DTLS events */
345 switch (code) {
346 case DTLS_ALERT_CLOSE_NOTIFY: {
347 coap_event_dtls = COAP_EVENT_DTLS_CLOSED;
348 break;
349 }
350 case DTLS_EVENT_CONNECTED: {
351 coap_event_dtls = COAP_EVENT_DTLS_CONNECTED;
352 break;
353 }
354#ifdef DTLS_EVENT_RENEGOTIATE
355 case DTLS_EVENT_RENEGOTIATE: {
356 coap_event_dtls = COAP_EVENT_DTLS_RENEGOTIATE;
357 break;
358 }
359#endif
360 default:
361 ;
362 }
363
364 return 0;
365}
366
367#ifdef DTLS_PSK
368/* This function is the "key store" for tinyDTLS. It is called to
369 * retrieve a key for the given identity within this particular
370 * session. */
371static int
372get_psk_info(struct dtls_context_t *dtls_context,
373 const session_t *dtls_session,
374 dtls_credentials_type_t type,
375 const uint8_t *id, size_t id_len,
376 unsigned char *result, size_t result_length) {
377
378 coap_tiny_context_t *t_context =
379 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
380 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
381 coap_session_t *coap_session;
382 int fatal_error = DTLS_ALERT_INTERNAL_ERROR;
383 coap_address_t remote_addr;
384#if COAP_CLIENT_SUPPORT
385 coap_dtls_cpsk_t *setup_cdata;
386 const coap_bin_const_t *psk_identity;
387 const coap_dtls_cpsk_info_t *cpsk_info;
388#endif /* COAP_CLIENT_SUPPORT */
389 const coap_bin_const_t *psk_key;
390#if COAP_SERVER_SUPPORT
391 coap_dtls_spsk_t *setup_sdata;
392 const coap_bin_const_t *psk_hint;
393#endif /* COAP_SERVER_SUPPORT */
394
395 assert(coap_context);
396 get_session_addr(dtls_session, &remote_addr);
397 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
398 if (!coap_session) {
399 coap_log_debug("cannot get PSK, session not found\n");
400 goto error;
401 }
402
403 switch (type) {
404 case DTLS_PSK_IDENTITY:
405
406#if COAP_CLIENT_SUPPORT
407 if (coap_session->type != COAP_SESSION_TYPE_CLIENT)
408 goto error;
409
410 setup_cdata = &coap_session->cpsk_setup_data;
411
412 coap_bin_const_t temp;
413 temp.s = id;
414 temp.length = id_len;
415 coap_session_refresh_psk_hint(coap_session, &temp);
416
417 coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)id_len,
418 id ? (const char *)id : "");
419
420 if (setup_cdata->validate_ih_call_back) {
421 coap_str_const_t lhint;
422
423 lhint.length = id_len;
424 lhint.s = id;
425 cpsk_info =
426 setup_cdata->validate_ih_call_back(&lhint,
427 coap_session,
428 setup_cdata->ih_call_back_arg);
429 if (cpsk_info) {
430 psk_identity = &cpsk_info->identity;
431 coap_session_refresh_psk_identity(coap_session, &cpsk_info->identity);
432 coap_session_refresh_psk_key(coap_session, &cpsk_info->key);
433 } else {
434 psk_identity = NULL;
435 }
436 } else {
437 psk_identity = coap_get_session_client_psk_identity(coap_session);
438 }
439 if (psk_identity == NULL) {
440 coap_log_warn("no PSK identity given\n");
441 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
442 goto error;
443 }
444 if (psk_identity->length > result_length) {
445 coap_log_warn("psk_identity too large, truncated to %zd bytes\n",
446 result_length);
447 } else {
448 /* Reduce to match */
449 result_length = psk_identity->length;
450 }
451 memcpy(result, psk_identity->s, result_length);
452 return result_length;
453#else /* ! COAP_CLIENT_SUPPORT */
454 return 0;
455#endif /* ! COAP_CLIENT_SUPPORT */
456
457 case DTLS_PSK_KEY:
458#if COAP_CLIENT_SUPPORT
459 if (coap_session->type == COAP_SESSION_TYPE_CLIENT) {
460 psk_key = coap_get_session_client_psk_key(coap_session);
461 if (psk_key == NULL) {
462 coap_log_warn("no PSK key given\n");
463 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
464 goto error;
465 }
466 if (psk_key->length > result_length) {
467 coap_log_warn("psk_key too large, truncated to %zd bytes\n",
468 result_length);
469 } else {
470 /* Reduce to match */
471 result_length = psk_key->length;
472 }
473 memcpy(result, psk_key->s, result_length);
474 return result_length;
475 }
476#endif /* COAP_CLIENT_SUPPORT */
477#if COAP_SERVER_SUPPORT
478 if (coap_session->type != COAP_SESSION_TYPE_CLIENT) {
479 coap_bin_const_t lidentity;
480
481 lidentity.length = id ? id_len : 0;
482 lidentity.s = id ? (const uint8_t *)id : (const uint8_t *)"";
483 setup_sdata = &coap_session->context->spsk_setup_data;
484
485 /* Track the Identity being used */
486 coap_session_refresh_psk_identity(coap_session, &lidentity);
487
488 coap_log_debug("got psk_identity: '%.*s'\n",
489 (int)lidentity.length, lidentity.s);
490
491 if (setup_sdata->validate_id_call_back) {
492 psk_key =
493 setup_sdata->validate_id_call_back(&lidentity,
494 coap_session,
495 setup_sdata->id_call_back_arg);
496 } else {
497 psk_key = coap_get_session_server_psk_key(coap_session);
498 }
499
500 if (psk_key == NULL) {
501 coap_log_warn("no PSK key given\n");
502 return 0;
503 }
504 if (setup_sdata->validate_id_call_back)
505 coap_session_refresh_psk_key(coap_session, psk_key);
506 if (psk_key->length > result_length) {
507 coap_log_warn("psk_key too large, truncated to %zd bytes\n",
508 result_length);
509 } else {
510 /* Reduce to match */
511 result_length = psk_key->length;
512 }
513 memcpy(result, psk_key->s, result_length);
514 return result_length;
515 }
516#endif /* COAP_SERVER_SUPPORT */
517 return 0;
518
519 case DTLS_PSK_HINT:
520#if COAP_SERVER_SUPPORT
521 psk_hint = coap_get_session_server_psk_hint(coap_session);
522 if (psk_hint == NULL)
523 return 0;
524 if (psk_hint->length > result_length) {
525 coap_log_warn("psk_hint too large, truncated to %zd bytes\n",
526 result_length);
527 } else {
528 /* Reduce to match */
529 result_length = psk_hint->length;
530 }
531 memcpy(result, psk_hint->s, result_length);
532 return result_length;
533#else /* COAP_SERVER_SUPPORT */
534 return 0;
535#endif /* COAP_SERVER_SUPPORT */
536
537 default:
538 coap_log_warn("unsupported request type: %d\n", type);
539 }
540
541error:
542 return dtls_alert_fatal_create(fatal_error);
543}
544#endif /* DTLS_PSK */
545
546#ifdef DTLS_ECC
547static int
548get_ecdsa_key(struct dtls_context_t *dtls_context,
549 const session_t *dtls_session COAP_UNUSED,
550 const dtls_ecdsa_key_t **result) {
551 static dtls_ecdsa_key_t ecdsa_key;
552 coap_tiny_context_t *t_context =
553 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
554
555 ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1;
556 ecdsa_key.priv_key = t_context->priv_key->s;
557 ecdsa_key.pub_key_x = t_context->pub_key->s;
558 ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE];
559
560 *result = &ecdsa_key;
561 return 0;
562}
563
564/* first part of Raw public key, the is the start of the Subject Public Key */
565static const unsigned char cert_asn1_header[] = {
566 0x30, 0x59, /* SEQUENCE, length 89 bytes */
567 0x30, 0x13, /* SEQUENCE, length 19 bytes */
568 0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */
569 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
570 0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */
571 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
572 0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */
573 0x04 /* uncompressed, followed by the r and s values of the public key */
574};
575#define DTLS_CE_LENGTH (sizeof(cert_asn1_header) + key_size + key_size)
576
577static int
578verify_ecdsa_key(struct dtls_context_t *dtls_context COAP_UNUSED,
579 const session_t *dtls_session COAP_UNUSED,
580 const uint8_t *other_pub_x,
581 const uint8_t *other_pub_y,
582 size_t key_size) {
583 coap_tiny_context_t *t_context =
584 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
585 if (t_context && t_context->setup_data.validate_cn_call_back) {
586 /* Need to build asn.1 certificate - code taken from tinydtls */
587 uint8 *p;
588 uint8 buf[DTLS_CE_LENGTH];
589 coap_session_t *c_session;
590 coap_address_t remote_addr;
591
592 /* Certificate
593 *
594 * Start message construction at beginning of buffer. */
595 p = buf;
596
597 memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
598 p += sizeof(cert_asn1_header);
599
600 memcpy(p, other_pub_x, key_size);
601 p += key_size;
602
603 memcpy(p, other_pub_y, key_size);
604 p += key_size;
605
606 assert(p <= (buf + sizeof(buf)));
607
608 get_session_addr(dtls_session, &remote_addr);
609 c_session = coap_session_get_by_peer(t_context->coap_context,
610 &remote_addr, dtls_session->ifindex);
611 if (!c_session)
612 return -3;
613 if (!t_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN,
614 buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg)) {
615 return -1;
616 }
617 }
618 return 0;
619}
620static dtls_handler_t ec_cb = {
621 .write = dtls_send_to_peer,
622 .read = dtls_application_data,
623 .event = dtls_event,
624#ifdef DTLS_PSK
625 .get_psk_info = NULL,
626#endif /* DTLS_PSK */
627 .get_ecdsa_key = get_ecdsa_key,
628 .verify_ecdsa_key = verify_ecdsa_key
629};
630#endif /* DTLS_ECC */
631
632static dtls_handler_t psk_cb = {
633 .write = dtls_send_to_peer,
634 .read = dtls_application_data,
635 .event = dtls_event,
636#ifdef DTLS_PSK
637 .get_psk_info = get_psk_info,
638#endif /* DTLS_PSK */
639#ifdef DTLS_ECC
640 .get_ecdsa_key = NULL,
641 .verify_ecdsa_key = NULL
642#endif /* DTLS_ECC */
643};
644
645void *
647 coap_tiny_context_t *t_context = coap_malloc_type(COAP_DTLS_CONTEXT, sizeof(coap_tiny_context_t));
648 struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL;
649 if (!dtls_context)
650 goto error;
651 memset(t_context, 0, sizeof(coap_tiny_context_t));
652 t_context->coap_context = coap_context;
653 t_context->dtls_context = dtls_context;
654 dtls_set_handler(dtls_context, &psk_cb);
655 return t_context;
656error:
657 if (t_context)
659 if (dtls_context)
660 coap_dtls_free_context(dtls_context);
661 return NULL;
662}
663
664void
665coap_dtls_free_context(void *handle) {
666 if (handle) {
667 coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
668#ifdef DTLS_ECC
669 if (t_context->priv_key) {
670 coap_delete_binary(t_context->priv_key);
671 t_context->priv_key = NULL;
672 }
673 if (t_context->pub_key) {
674 coap_delete_binary(t_context->pub_key);
675 t_context->pub_key = NULL;
676 }
677#endif /* DTLS_ECC */
678 if (t_context->dtls_context)
679 dtls_free_context(t_context->dtls_context);
681 }
682}
683
684static session_t *
685coap_dtls_new_session(coap_session_t *session) {
686 session_t *dtls_session = coap_malloc_type(COAP_DTLS_SESSION, sizeof(session_t));
687
688 if (dtls_session) {
689 /* create tinydtls session object from remote address and local
690 * endpoint handle */
691 dtls_session_init(dtls_session);
692 put_session_addr(&session->addr_info.remote, dtls_session);
693 dtls_session->ifindex = session->ifindex;
694 coap_log_debug("***new session %p\n", (void *)dtls_session);
695 }
696
697 return dtls_session;
698}
699
700#if COAP_SERVER_SUPPORT
701void *
703 return coap_dtls_new_session(session);
704}
705#endif /* COAP_SERVER_SUPPORT */
706
707#if COAP_CLIENT_SUPPORT
708void *
710 dtls_peer_t *peer;
711 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
712 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
713 session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL;
714
715 if (!dtls_session)
716 return NULL;
717 peer =
718 dtls_get_peer(dtls_context, dtls_session);
719
720 if (!peer) {
721 /* The peer connection does not yet exist. */
722 /* dtls_connect() returns a value greater than zero if a new
723 * connection attempt is made, 0 for session reuse. */
724 if (dtls_connect(dtls_context, dtls_session) >= 0) {
725 peer =
726 dtls_get_peer(dtls_context, dtls_session);
727 }
728 }
729
730 if (!peer) {
731 /* delete existing session because the peer object has been invalidated */
732 coap_free_type(COAP_DTLS_SESSION, dtls_session);
733 dtls_session = NULL;
734 }
735
736 return dtls_session;
737}
738#endif /* COAP_CLIENT_SUPPORT */
739
740void
742 (void)session;
743}
744
745void
747 coap_tiny_context_t *t_context =
748 (coap_tiny_context_t *)coap_session->context->dtls_context;
749 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
750
751 if (dtls_context == NULL)
752 return;
753 if (coap_session->tls && dtls_context) {
754 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->tls);
755 if (peer)
756 dtls_reset_peer(dtls_context, peer);
757 else
758 dtls_close(dtls_context, (session_t *)coap_session->tls);
759 coap_log_debug("***removed session %p\n", coap_session->tls);
760 coap_free_type(COAP_DTLS_SESSION, coap_session->tls);
761 coap_session->tls = NULL;
762 coap_handle_event(coap_session->context, COAP_EVENT_DTLS_CLOSED, coap_session);
763 }
764}
765
766ssize_t
768 const uint8_t *data,
769 size_t data_len) {
770 int res;
771 uint8_t *data_rw;
772 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
773 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
774
775 assert(dtls_context);
776
777 coap_event_dtls = -1;
778 coap_log_debug("* %s: dtls: sent %4d bytes\n",
779 coap_session_str(session), (int)data_len);
780 /* Need to do this to not get a compiler warning about const parameters */
781 memcpy(&data_rw, &data, sizeof(data_rw));
782 res = dtls_write(dtls_context,
783 (session_t *)session->tls, data_rw, data_len);
784
785 if (res < 0)
786 coap_log_warn("coap_dtls_send: cannot send PDU\n");
787
788 if (coap_event_dtls >= 0) {
789 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
790 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
791 coap_handle_event(session->context, coap_event_dtls, session);
792 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
793 coap_session_connected(session);
794 else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
796 }
797
798 return res;
799}
800
801int
803 return 1;
804}
805
807coap_dtls_get_context_timeout(void *tiny_context) {
808 clock_time_t next = 0;
809 coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
810 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
811 if (tiny_context)
812 dtls_check_retransmit(dtls_context, &next);
813 if (next > 0)
814 return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND +
815 coap_tick_0;
816 return 0;
817}
818
821 (void)session;
822 (void)now;
823 return 0;
824}
825
826/*
827 * return 1 timed out
828 * 0 still timing out
829 */
830int
832 (void)session;
833 return 0;
834}
835
836int
838 const uint8_t *data,
839 size_t data_len
840 ) {
841 session_t *dtls_session = (session_t *)session->tls;
842 int err;
843 uint8_t *data_rw;
844 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
845 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
846
847 assert(dtls_context);
848 coap_event_dtls = -1;
849 /* Need to do this to not get a compiler warning about const parameters */
850 memcpy(&data_rw, &data, sizeof(data_rw));
851 err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len);
852
853 if (err) {
854 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
855 }
856
857 if (coap_event_dtls >= 0) {
858 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
859 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
860 coap_handle_event(session->context, coap_event_dtls, session);
861 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
862 coap_session_connected(session);
863 else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) {
865 err = -1;
866 }
867 }
868
869 return err;
870}
871
872#if COAP_SERVER_SUPPORT
873int
875 const uint8_t *data,
876 size_t data_len
877 ) {
878 session_t dtls_session;
879 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
880 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
881 uint8_t *data_rw;
882
883 assert(dtls_context);
884 dtls_session_init(&dtls_session);
885 put_session_addr(&session->addr_info.remote, &dtls_session);
886 dtls_session.ifindex = session->ifindex;
887 /* Need to do this to not get a compiler warning about const parameters */
888 memcpy(&data_rw, &data, sizeof(data_rw));
889 int res = dtls_handle_message(dtls_context, &dtls_session,
890 data_rw, (int)data_len);
891 if (res >= 0) {
892 if (dtls_get_peer(dtls_context, &dtls_session))
893 res = 1;
894 else
895 res = 0;
896 }
897 return res;
898}
899#endif /* COAP_SERVER_SUPPORT */
900
901unsigned int
903 (void)session;
904 return 13 + 8 + 8;
905}
906
907int
909 return 0;
910}
911
914 static coap_tls_version_t version;
915 const char *vers = dtls_package_version();
916
917 version.version = 0;
918 if (vers) {
919 long int p1, p2 = 0, p3 = 0;
920 char *endptr;
921
922 p1 = strtol(vers, &endptr, 10);
923 if (*endptr == '.') {
924 p2 = strtol(endptr+1, &endptr, 10);
925 if (*endptr == '.') {
926 p3 = strtol(endptr+1, &endptr, 10);
927 }
928 }
929 version.version = (p1 << 16) | (p2 << 8) | p3;
930 }
931 version.built_version = version.version;
933 return &version;
934}
935
936#ifdef DTLS_ECC
937static const uint8_t b64_6[256] = {
938 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
939 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
940 /* + / */
941 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
942 /* 0 1 2 3 4 5 6 7 8 9 = */
943 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
944 /* A B C D E F G H I J K L M N O */
945 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
946 /* P Q R S T U V W X Y Z */
947 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
948 /* a b c d e f g h i j k l m n o */
949 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
950 /* p q r s t u v w x y z */
951 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
952 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
953 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
954 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
955 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
956 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
957 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
958 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
959 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
960};
961
962/* caller must free off returned coap_binary_t* */
963static coap_binary_t *
964pem_base64_decode(const uint8_t *data, size_t size) {
965 uint8_t *tbuf = coap_malloc_type(COAP_STRING, size);
966 size_t nbytesdecoded;
967 size_t i;
968 coap_binary_t *decoded;
969 uint8_t *ptr;
970 uint8_t *out;
971 size_t nb64bytes = 0;
972
973 for (i = 0; i < size; i++) {
974 switch (data[i]) {
975 case ' ':
976 case '\r':
977 case '\n':
978 case '\t':
979 break;
980 default:
981 if (b64_6[data[i]] == 64)
982 goto end;
983 tbuf[nb64bytes++] = data[i];
984 break;
985 }
986 }
987
988end:
989 nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
990 decoded = coap_new_binary(nbytesdecoded + 1);
991 if (!decoded)
992 return NULL;
993
994 out = decoded->s;
995 ptr = tbuf;
996
997 while (nb64bytes > 4) {
998 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
999 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1000 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1001 ptr += 4;
1002 nb64bytes -= 4;
1003 }
1004
1005 /* Note: (nb64bytes == 1) is an error */
1006 if (nb64bytes > 1) {
1007 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1008 }
1009 if (nb64bytes > 2) {
1010 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1011 }
1012 if (nb64bytes > 3) {
1013 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1014 }
1015
1016 decoded->length = nbytesdecoded - ((4 - nb64bytes) & 3);
1018 return decoded;
1019}
1020
1021typedef coap_binary_t *(*asn1_callback)(const uint8_t *data, size_t size);
1022
1023static int
1024asn1_verify_privkey(const uint8_t *data, size_t size) {
1025 /* Check if we have the private key (with optional leading 0x00) */
1026 /* skip leading 0x00 */
1027 if (size - 1 == DTLS_EC_KEY_SIZE && *data == '\000') {
1028 --size;
1029 ++data;
1030 }
1031
1032 /* Check if we have the private key */
1033 if (size != DTLS_EC_KEY_SIZE)
1034 return 0;
1035
1036 return 1;
1037}
1038
1039static int
1040asn1_verify_pubkey(const uint8_t *data, size_t size) {
1041 (void)data;
1042
1043 /* We have the public key
1044 (with a leading 0x00 (no unused bits) 0x04 (not compressed() */
1045 if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
1046 return 0;
1047
1048 return 1;
1049}
1050
1051static int
1052asn1_verify_curve(const uint8_t *data, size_t size) {
1053 static uint8_t prime256v1_oid[] =
1054 /* OID 1.2.840.10045.3.1.7 */
1055 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
1056
1057 /* Check that we have the correct EC (only one supported) */
1058 if (size != sizeof(prime256v1_oid) ||
1059 memcmp(data, prime256v1_oid, size) != 0)
1060 return 0;
1061
1062 return 1;
1063}
1064
1065static int
1066asn1_verify_pkcs8_version(const uint8_t *data, size_t size) {
1067 /* Check that we have the version */
1068 if (size != 1 || *data != 0)
1069 return 0;
1070
1071 return 1;
1072}
1073
1074static int
1075asn1_verify_ec_identifier(const uint8_t *data, size_t size) {
1076 static uint8_t ec_public_key_oid[] =
1077 /* OID 1.2.840.10045.2.1 */
1078 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
1079
1080 /* Check that we have the correct ecPublicKey */
1081 if (size != sizeof(ec_public_key_oid) ||
1082 memcmp(data, ec_public_key_oid, size) != 0)
1083 return 0;
1084
1085 return 1;
1086}
1087
1088static int
1089asn1_verify_ec_key(const uint8_t *data, size_t size) {
1090 (void)data;
1091
1092 if (size == 0)
1093 return 0;
1094
1095 return 1;
1096}
1097
1098static int
1099asn1_derive_keys(coap_tiny_context_t *t_context,
1100 const uint8_t *priv_data, size_t priv_len,
1101 const uint8_t *pub_data, size_t pub_len,
1102 int is_pkcs8) {
1103 coap_binary_t *test;
1104
1105 t_context->priv_key = get_asn1_tag(COAP_ASN1_OCTETSTRING, priv_data,
1106 priv_len, asn1_verify_privkey);
1107 if (!t_context->priv_key) {
1108 coap_log_info("EC Private Key (RPK) invalid\n");
1109 return 0;
1110 }
1111 /* skip leading 0x00 */
1112 if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
1113 t_context->priv_key->s[0] == '\000') {
1114 t_context->priv_key->length--;
1115 t_context->priv_key->s++;
1116 }
1117
1118 if (!is_pkcs8) {
1119 /* pkcs8 abstraction tested for valid eliptic curve */
1120 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, priv_data, priv_len,
1121 asn1_verify_curve);
1122 if (!test) {
1123 coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1124 coap_delete_binary(t_context->priv_key);
1125 t_context->priv_key = NULL;
1126 return 0;
1127 }
1128 coap_delete_binary(test);
1129 }
1130
1131 t_context->pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, pub_data, pub_len,
1132 asn1_verify_pubkey);
1133 if (!t_context->pub_key) {
1134 coap_log_info("EC Public Key (RPK) invalid\n");
1135 coap_delete_binary(t_context->priv_key);
1136 t_context->priv_key = NULL;
1137 return 0;
1138 }
1139 /* Drop leading 0x00 and 0x04 */
1140 t_context->pub_key->s += 2;
1141 t_context->pub_key->length -= 2;
1142 dtls_set_handler(t_context->dtls_context, &ec_cb);
1143 return 1;
1144}
1145
1146static coap_binary_t *
1147ec_abstract_pkcs8_asn1(const uint8_t *asn1_ptr, size_t asn1_length) {
1148 coap_binary_t *test;
1149
1150 test = get_asn1_tag(COAP_ASN1_INTEGER, asn1_ptr, asn1_length,
1151 asn1_verify_pkcs8_version);
1152 if (!test)
1153 return 0;
1154
1155 coap_delete_binary(test);
1156
1157 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1158 asn1_verify_ec_identifier);
1159 if (!test)
1160 return 0;
1161 coap_delete_binary(test);
1162
1163 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1164 asn1_verify_curve);
1165 if (!test) {
1166 coap_log_info("EC Private Key (RPK) invalid elliptic curve\n");
1167 return 0;
1168 }
1169 coap_delete_binary(test);
1170
1171 test = get_asn1_tag(COAP_ASN1_OCTETSTRING, asn1_ptr, asn1_length,
1172 asn1_verify_ec_key);
1173 return test;
1174}
1175
1176static coap_binary_t *
1177pem_decode_mem_asn1(const char *begstr, const uint8_t *str) {
1178 char *bcp = str ? strstr((const char *)str, begstr) : NULL;
1179 char *tcp = bcp ? strstr(bcp, "-----END ") : NULL;
1180
1181 if (bcp && tcp) {
1182 bcp += strlen(begstr);
1183 return pem_base64_decode((const uint8_t *)bcp, tcp - bcp);
1184 }
1185 return NULL;
1186}
1187
1188#endif /* DTLS_ECC */
1189
1190int
1192 const coap_dtls_pki_t *setup_data,
1193 const coap_dtls_role_t role COAP_UNUSED) {
1194#ifdef DTLS_ECC
1195 coap_tiny_context_t *t_context;
1196 coap_binary_t *asn1_priv;
1197 coap_binary_t *asn1_pub;
1198 coap_binary_t *asn1_temp;
1199 int is_pkcs8 = 0;
1200
1201 if (!setup_data)
1202 return 0;
1203 if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION)
1204 return 0;
1205 if (!setup_data->is_rpk_not_cert) {
1206 coap_log_warn("Only RPK, not full PKI is supported\n");
1207 return 0;
1208 }
1209 if (!ctx)
1210 return 0;
1211 t_context = (coap_tiny_context_t *)ctx->dtls_context;
1212 if (!t_context)
1213 return 0;
1214 if (t_context->priv_key) {
1215 coap_delete_binary(t_context->priv_key);
1216 t_context->priv_key = NULL;
1217 }
1218 if (t_context->pub_key) {
1219 coap_delete_binary(t_context->pub_key);
1220 t_context->pub_key = NULL;
1221 }
1222 t_context->setup_data = *setup_data;
1223
1224 /* All should be RPK only now */
1225 switch (setup_data->pki_key.key_type) {
1226 case COAP_PKI_KEY_PEM:
1227 coap_log_warn("RPK keys cannot be in COAP_PKI_KEY_PEM format\n");
1228 break;
1230 if (setup_data->pki_key.key.pem_buf.public_cert &&
1231 setup_data->pki_key.key.pem_buf.public_cert[0] &&
1232 setup_data->pki_key.key.pem_buf.private_key &&
1233 setup_data->pki_key.key.pem_buf.private_key[0]) {
1234 /* Need to take PEM memory information and convert to binary */
1235 asn1_priv = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1236 setup_data->pki_key.key.pem_buf.private_key);
1237 if (!asn1_priv) {
1238 asn1_priv = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1239 setup_data->pki_key.key.pem_buf.private_key);
1240 if (!asn1_priv) {
1241 coap_log_info("Private Key (RPK) invalid\n");
1242 return 0;
1243 }
1244 asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->s, asn1_priv->length);
1245 if (!asn1_temp) {
1246 coap_log_info("PKCS#8 Private Key (RPK) invalid\n");
1247 coap_delete_binary(asn1_priv);
1248 return 0;
1249 }
1250 coap_delete_binary(asn1_priv);
1251 asn1_priv = asn1_temp;
1252 is_pkcs8 = 1;
1253 }
1254 asn1_pub = pem_decode_mem_asn1(
1255 "-----BEGIN PUBLIC KEY-----",
1256 setup_data->pki_key.key.pem_buf.public_cert);
1257 if (!asn1_pub) {
1258 asn1_pub = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1259 setup_data->pki_key.key.pem_buf.private_key);
1260 if (!asn1_pub) {
1261 asn1_pub = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1262 setup_data->pki_key.key.pem_buf.private_key);
1263 if (!asn1_pub) {
1264 coap_log_info("Public Key (RPK) invalid\n");
1265 coap_delete_binary(asn1_priv);
1266 return 0;
1267 }
1268 asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->s, asn1_pub->length);
1269 if (!asn1_temp) {
1270 coap_log_info("PKCS#8 Private Key (RPK) invalid\n");
1271 coap_delete_binary(asn1_priv);
1272 coap_delete_binary(asn1_pub);
1273 return 0;
1274 }
1275 coap_delete_binary(asn1_pub);
1276 asn1_pub = asn1_temp;
1277 is_pkcs8 = 1;
1278 }
1279 }
1280 if (!asn1_derive_keys(t_context, asn1_priv->s, asn1_priv->length,
1281 asn1_pub->s, asn1_pub->length, is_pkcs8)) {
1282 coap_log_info("Unable to derive Public/Private Keys\n");
1283 coap_delete_binary(asn1_priv);
1284 coap_delete_binary(asn1_pub);
1285 return 0;
1286 }
1287 coap_delete_binary(asn1_priv);
1288 coap_delete_binary(asn1_pub);
1289 return 1;
1290 }
1291 break;
1292 case COAP_PKI_KEY_ASN1:
1293 if (setup_data->pki_key.key.asn1.private_key &&
1294 setup_data->pki_key.key.asn1.private_key_len &&
1296 const uint8_t *private_key = setup_data->pki_key.key.asn1.private_key;
1297 size_t private_key_len = setup_data->pki_key.key.asn1.private_key_len;
1298
1299 /* Check to see whether this is in pkcs8 format or not */
1300 asn1_temp = ec_abstract_pkcs8_asn1(
1301 setup_data->pki_key.key.asn1.private_key,
1302 setup_data->pki_key.key.asn1.private_key_len);
1303 if (asn1_temp) {
1304 private_key = asn1_temp->s;
1305 private_key_len = asn1_temp->length;
1306 is_pkcs8 = 1;
1307 }
1308 /* Need to take ASN1 memory information and convert to binary */
1309 if (setup_data->pki_key.key.asn1.public_cert &&
1310 setup_data->pki_key.key.asn1.public_cert_len) {
1311 if (!asn1_derive_keys(t_context,
1312 private_key,
1313 private_key_len,
1314 setup_data->pki_key.key.asn1.public_cert,
1315 setup_data->pki_key.key.asn1.public_cert_len,
1316 is_pkcs8)) {
1317 coap_log_info("Unable to derive Public/Private Keys\n");
1318 if (asn1_temp)
1319 coap_delete_binary(asn1_temp);
1320 return 0;
1321 }
1322 } else {
1323 if (!asn1_derive_keys(t_context,
1324 private_key,
1325 private_key_len,
1326 private_key,
1327 private_key_len,
1328 is_pkcs8)) {
1329 coap_log_info("Unable to derive Public/Private Keys\n");
1330 if (asn1_temp)
1331 coap_delete_binary(asn1_temp);
1332 return 0;
1333 }
1334 }
1335 return 1;
1336 }
1337 break;
1339 coap_log_warn("RPK keys cannot be in COAP_PKI_KEY_PCKS11 format\n");
1340 break;
1341 default:
1342 break;
1343 }
1344#else /* ! DTLS_ECC */
1345 (void)ctx;
1346 (void)setup_data;
1347#endif /* ! DTLS_ECC */
1348 coap_log_warn("TinyDTLS not compiled with ECC support\n");
1349 return 0;
1350}
1351
1352int
1354 const char *ca_file COAP_UNUSED,
1355 const char *ca_path COAP_UNUSED
1356 ) {
1357 coap_log_warn("Root CAs PKI not supported\n");
1358 return 0;
1359}
1360
1361#if COAP_CLIENT_SUPPORT
1362int
1364 coap_dtls_cpsk_t *setup_data
1365 ) {
1366 if (!setup_data)
1367 return 0;
1368
1369#ifdef DTLS_PSK
1370 return 1;
1371#else /* ! DTLS_PSK */
1372 coap_log_warn("TinyDTLS not compiled with PSK support\n");
1373 return 0;
1374#endif /* ! DTLS_PSK */
1375}
1376#endif /* COAP_CLIENT_SUPPORT */
1377
1378#if COAP_SERVER_SUPPORT
1379int
1381 coap_dtls_spsk_t *setup_data
1382 ) {
1383 if (!setup_data)
1384 return 0;
1385
1386#ifdef DTLS_PSK
1387 if (setup_data->validate_sni_call_back) {
1388 coap_log_warn("CoAP Server with TinyDTLS does not support SNI selection\n");
1389 }
1390
1391 return 1;
1392#else /* ! DTLS_PSK */
1393 coap_log_warn("TinyDTLS not compiled with PSK support\n");
1394 return 0;
1395#endif /* ! DTLS_PSK */
1396}
1397#endif /* COAP_SERVER_SUPPORT */
1398
1399int
1401 return 1;
1402}
1403
1404#if !COAP_DISABLE_TCP
1405#if COAP_CLIENT_SUPPORT
1406void *
1408 return NULL;
1409}
1410#endif /* COAP_CLIENT_SUPPORT */
1411
1412#if COAP_SERVER_SUPPORT
1413void *
1415 return NULL;
1416}
1417#endif /* COAP_SERVER_SUPPORT */
1418
1419void
1421}
1422
1423/*
1424 * strm
1425 * return +ve Number of bytes written.
1426 * -1 Error (error in errno).
1427 */
1428ssize_t
1430 const uint8_t *data COAP_UNUSED,
1431 size_t data_len COAP_UNUSED
1432 ) {
1433 return -1;
1434}
1435
1436/*
1437 * strm
1438 * return >=0 Number of bytes read.
1439 * -1 Error (error in errno).
1440 */
1441ssize_t
1443 uint8_t *data COAP_UNUSED,
1444 size_t data_len COAP_UNUSED) {
1445 errno = ENODEV;
1446 return -1;
1447}
1448#endif /* !COAP_DISABLE_TCP */
1449
1450#if COAP_SERVER_SUPPORT
1452coap_digest_setup(void) {
1453 dtls_sha256_ctx *digest_ctx = coap_malloc_type(COAP_STRING, sizeof(dtls_sha256_ctx));
1454
1455 if (digest_ctx) {
1456 dtls_sha256_init(digest_ctx);
1457 }
1458
1459 return digest_ctx;
1460}
1461
1462void
1464 coap_free_type(COAP_STRING, digest_ctx);
1465}
1466
1467int
1469 const uint8_t *data,
1470 size_t data_len) {
1471 dtls_sha256_update(digest_ctx, data, data_len);
1472
1473 return 1;
1474}
1475
1476int
1478 coap_digest_t *digest_buffer) {
1479 dtls_sha256_final((uint8_t *)digest_buffer, digest_ctx);
1480
1481 coap_digest_free(digest_ctx);
1482 return 1;
1483}
1484#endif /* COAP_SERVER_SUPPORT */
1485
1486#if COAP_WS_SUPPORT
1487int
1489 const coap_bin_const_t *data,
1490 coap_bin_const_t **hash) {
1491 SHA1Context sha1_context;
1492 coap_binary_t *dummy = NULL;
1493
1494 (void)alg;
1495
1496 SHA1Reset(&sha1_context);
1497 if (SHA1Input(&sha1_context, data->s, data->length) != shaSuccess)
1498 return 0;
1500 if (!dummy)
1501 return 0;
1502 if (SHA1Result(&sha1_context, dummy->s) != shaSuccess) {
1504 return 0;
1505 }
1506 *hash = (coap_bin_const_t *)(dummy);
1507 return 1;
1508}
1509#endif /* COAP_WS_SUPPORT */
1510
1511#if COAP_OSCORE_SUPPORT
1512
1513int
1515 return 1;
1516}
1517
1518/*
1519 * The struct cipher_algs and the function get_cipher_alg() are used to
1520 * determine which cipher type to use for creating the required cipher
1521 * suite object.
1522 */
1523static struct cipher_algs {
1524 cose_alg_t alg;
1525 u_int cipher_type;
1526} ciphers[] = {
1528};
1529
1530static u_int
1531get_cipher_alg(cose_alg_t alg) {
1532 size_t idx;
1533
1534 for (idx = 0; idx < sizeof(ciphers)/sizeof(struct cipher_algs); idx++) {
1535 if (ciphers[idx].alg == alg)
1536 return ciphers[idx].cipher_type;
1537 }
1538 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
1539 return 0;
1540}
1541
1542/*
1543 * The struct hmac_algs and the function get_hmac_alg() are used to
1544 * determine which hmac type to use for creating the required hmac
1545 * suite object.
1546 */
1547static struct hmac_algs {
1548 cose_hmac_alg_t hmac_alg;
1549 u_int hmac_type;
1550} hmacs[] = {
1552};
1553
1554static u_int
1555get_hmac_alg(cose_hmac_alg_t hmac_alg) {
1556 size_t idx;
1557
1558 for (idx = 0; idx < sizeof(hmacs)/sizeof(struct hmac_algs); idx++) {
1559 if (hmacs[idx].hmac_alg == hmac_alg)
1560 return hmacs[idx].hmac_type;
1561 }
1562 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
1563 return 0;
1564}
1565
1566int
1568 return get_cipher_alg(alg);
1569}
1570
1571int
1573 cose_hmac_alg_t hmac_alg;
1574
1575 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
1576 return 0;
1577 return get_hmac_alg(hmac_alg);
1578}
1579
1580int
1582 coap_bin_const_t *data,
1583 coap_bin_const_t *aad,
1584 uint8_t *result, size_t *max_result_len) {
1585 int num_bytes;
1586 const coap_crypto_aes_ccm_t *ccm;
1587 dtls_ccm_params_t dtls_params;
1588 coap_bin_const_t laad;
1589
1590 if (data == NULL)
1591 return 0;
1592
1593 assert(params);
1594
1595 if (get_cipher_alg(params->alg) == 0) {
1596 coap_log_debug("coap_crypto_encrypt: algorithm %d not supported\n",
1597 params->alg);
1598 return 0;
1599 }
1600
1601 ccm = &params->params.aes;
1602 if (*max_result_len < (data->length + ccm->tag_len)) {
1603 coap_log_warn("coap_encrypt: result buffer too small\n");
1604 return 0;
1605 }
1606
1607 dtls_params.nonce = ccm->nonce;
1608 dtls_params.tag_length = ccm->tag_len;
1609 dtls_params.l = ccm->l;
1610
1611 if (aad) {
1612 laad = *aad;
1613 } else {
1614 laad.s = NULL;
1615 laad.length = 0;
1616 }
1617
1618 num_bytes = dtls_encrypt_params(&dtls_params,
1619 data->s, data->length,
1620 result,
1621 ccm->key.s, ccm->key.length,
1622 laad.s, laad.length);
1623 if (num_bytes < 0) {
1624 return 0;
1625 }
1626 *max_result_len = num_bytes;
1627 return 1;
1628}
1629
1630int
1632 coap_bin_const_t *data,
1633 coap_bin_const_t *aad,
1634 uint8_t *result, size_t *max_result_len) {
1635 int num_bytes;
1636 const coap_crypto_aes_ccm_t *ccm;
1637 dtls_ccm_params_t dtls_params;
1638 coap_bin_const_t laad;
1639
1640 if (data == NULL)
1641 return 0;
1642
1643 assert(params);
1644
1645 if (get_cipher_alg(params->alg) == 0) {
1646 coap_log_debug("coap_crypto_decrypt: algorithm %d not supported\n",
1647 params->alg);
1648 return 0;
1649 }
1650
1651 ccm = &params->params.aes;
1652
1653 if ((*max_result_len + ccm->tag_len) < data->length) {
1654 coap_log_warn("coap_decrypt: result buffer too small\n");
1655 return 0;
1656 }
1657
1658 dtls_params.nonce = ccm->nonce;
1659 dtls_params.tag_length = ccm->tag_len;
1660 dtls_params.l = ccm->l;
1661
1662 if (aad) {
1663 laad = *aad;
1664 } else {
1665 laad.s = NULL;
1666 laad.length = 0;
1667 }
1668
1669 num_bytes = dtls_decrypt_params(&dtls_params,
1670 data->s, data->length,
1671 result,
1672 ccm->key.s, ccm->key.length,
1673 laad.s, laad.length);
1674 if (num_bytes < 0) {
1675 return 0;
1676 }
1677 *max_result_len = num_bytes;
1678 return 1;
1679}
1680
1681int
1683 coap_bin_const_t *data, coap_bin_const_t **hmac) {
1684 dtls_hmac_context_t hmac_context;
1685 int num_bytes;
1687
1688 if (data == NULL)
1689 return 0;
1690
1691 if (get_hmac_alg(hmac_alg) == 0) {
1692 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
1693 return 0;
1694 }
1695
1696 dummy = coap_new_binary(DTLS_SHA256_DIGEST_LENGTH);
1697 if (dummy == NULL)
1698 return 0;
1699
1700 dtls_hmac_init(&hmac_context, key->s, key->length);
1701 dtls_hmac_update(&hmac_context, data->s, data->length);
1702 num_bytes = dtls_hmac_finalize(&hmac_context, dummy->s);
1703
1704 if (num_bytes != DTLS_SHA256_DIGEST_LENGTH) {
1706 return 0;
1707 }
1708 *hmac = (coap_bin_const_t *)dummy;
1709 return 1;
1710}
1711
1712#endif /* COAP_OSCORE_SUPPORT */
1713
1714#else /* !COAP_WITH_LIBTINYDTLS */
1715
1716#ifdef __clang__
1717/* Make compilers happy that do not like empty modules. As this function is
1718 * never used, we ignore -Wunused-function at the end of compiling this file
1719 */
1720#pragma GCC diagnostic ignored "-Wunused-function"
1721#endif
1722static inline void
1723dummy(void) {
1724}
1725
1726#endif /* COAP_WITH_LIBTINYDTLS */
Pulls together all the internal only header files.
@ COAP_NACK_TLS_FAILED
Definition: coap_io.h:73
@ COAP_LAYER_TLS
@ COAP_DTLS_SESSION
Definition: coap_mem.h:49
@ COAP_DTLS_CONTEXT
Definition: coap_mem.h:59
@ COAP_STRING
Definition: coap_mem.h:38
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:77
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition: coap_notls.c:193
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:265
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition: coap_notls.c:188
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:207
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition: coap_notls.c:122
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:225
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition: coap_notls.c:111
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:176
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:253
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:172
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:85
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:202
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition: coap_notls.c:150
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:168
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition: coap_notls.c:145
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:244
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_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:2285
int coap_handle_event(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:4073
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 *session)
Get the current client's PSK identity.
Definition: coap_net.c:286
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition: coap_notls.c:118
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_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition: coap_notls.c:183
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:130
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.
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_tls_version_t * coap_get_tls_library_version(void)
Determine the type and version of the underlying (D)TLS library.
Definition: coap_notls.c:69
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition: coap_notls.c:37
coap_dtls_role_t
Definition: coap_dtls.h:44
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition: coap_notls.c:28
#define COAP_DTLS_PKI_SETUP_VERSION
Latest PKI setup version.
Definition: coap_dtls.h:282
#define COAP_DTLS_RPK_CERT_CN
Definition: coap_dtls.h:49
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_notls.c:23
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition: coap_notls.c:46
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition: coap_notls.c:64
coap_tls_library_t
Definition: coap_dtls.h:93
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition: coap_notls.c:55
@ COAP_PKI_KEY_PKCS11
The PKI key type is PKCS11 (DER)
Definition: coap_dtls.h:194
@ COAP_PKI_KEY_PEM_BUF
The PKI key type is PEM buffer.
Definition: coap_dtls.h:193
@ COAP_PKI_KEY_PEM
The PKI key type is PEM file.
Definition: coap_dtls.h:191
@ COAP_PKI_KEY_ASN1
The PKI key type is ASN.1 (DER) buffer.
Definition: coap_dtls.h:192
@ COAP_ASN1_PKEY_EC
EC type.
Definition: coap_dtls.h:180
@ COAP_TLS_LIBRARY_TINYDTLS
Using TinyDTLS library.
Definition: coap_dtls.h:95
@ 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_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:140
#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:135
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_oscore_is_supported(void)
Check whether OSCORE is available.
Definition: coap_oscore.c:2113
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:766
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).
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.
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:855
@ 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
#define COAP_UNUSED
Definition: libcoap.h:68
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.
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:350
coap_bin_const_t key
Definition: coap_dtls.h:352
coap_bin_const_t identity
Definition: coap_dtls.h:351
The structure used for defining the Client PSK setup data to be used.
Definition: coap_dtls.h:381
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition: coap_dtls.h:402
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition: coap_dtls.h:401
union coap_dtls_key_t::@3 key
coap_pki_key_pem_buf_t pem_buf
for PEM memory keys
Definition: coap_dtls.h:259
coap_pki_key_t key_type
key format type
Definition: coap_dtls.h:256
coap_pki_key_asn1_t asn1
for ASN.1 (DER) memory keys
Definition: coap_dtls.h:260
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:287
uint8_t version
Definition: coap_dtls.h:288
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition: coap_dtls.h:305
coap_dtls_key_t pki_key
PKI key definition.
Definition: coap_dtls.h:344
The structure used for defining the Server PSK setup data to be used.
Definition: coap_dtls.h:468
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition: coap_dtls.h:495
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition: coap_dtls.h:487
void * id_call_back_arg
Passed in to the Identity callback function.
Definition: coap_dtls.h:488
coap_layer_write_t l_write
const uint8_t * private_key
ASN1 (DER) Private Key.
Definition: coap_dtls.h:233
coap_asn1_privatekey_type_t private_key_type
Private Key Type.
Definition: coap_dtls.h:237
size_t public_cert_len
ASN1 Public Cert length.
Definition: coap_dtls.h:235
size_t private_key_len
ASN1 Private Key length.
Definition: coap_dtls.h:236
const uint8_t * public_cert
ASN1 (DER) Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:232
const uint8_t * private_key
PEM buffer Private Key If RPK and 'EC PRIVATE KEY' this can be used for both the public_cert and priv...
Definition: coap_dtls.h:219
const uint8_t * public_cert
PEM buffer Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:218
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
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:106
uint64_t built_version
(D)TLS Built against Library Version
Definition: coap_dtls.h:109
coap_tls_library_t type
Library type.
Definition: coap_dtls.h:108
uint64_t version
(D)TLS runtime Library Version
Definition: coap_dtls.h:107