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