libcoap 4.3.3
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 */
156}
157
158void
159coap_dtls_shutdown(void) {
160}
161
162void *
163coap_dtls_get_tls(const coap_session_t *c_session,
164 coap_tls_library_t *tls_lib) {
165 if (tls_lib)
166 *tls_lib = COAP_TLS_LIBRARY_TINYDTLS;
167 if (c_session && c_session->context && c_session->context->dtls_context) {
168 const coap_tiny_context_t *t_context =
169 (const coap_tiny_context_t *)c_session->context->dtls_context;
170
171 return t_context->dtls_context;
172 }
173 return NULL;
174}
175
176void
178 log_t d_level;
179
180 /* DTLS_LOG_ERR is missing, so account for the gap */
181 switch (c_level) {
182 case COAP_LOG_EMERG:
183 d_level = DTLS_LOG_EMERG;
184 break;
185 case COAP_LOG_ALERT:
186 d_level = DTLS_LOG_ALERT;
187 break;
188 case COAP_LOG_CRIT:
189 case COAP_LOG_ERR:
190 d_level = DTLS_LOG_CRIT;
191 break;
192 case COAP_LOG_WARN:
193 d_level = DTLS_LOG_WARN;
194 break;
195 case COAP_LOG_NOTICE:
196 d_level = DTLS_LOG_NOTICE;
197 break;
198 case COAP_LOG_INFO:
199 d_level = DTLS_LOG_INFO;
200 break;
201 case COAP_LOG_DEBUG:
202 case COAP_LOG_OSCORE:
204 default:
205 d_level = DTLS_LOG_DEBUG;
206 break;
207 }
208 dtls_set_log_level(d_level);
209}
210
213 log_t d_level = dtls_get_log_level();
214
215 return dtls_map_logging(d_level);
216}
217
218static void
219get_session_addr(const session_t *s, coap_address_t *a) {
220#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
221 a->addr = s->addr;
222 a->port = s->port;
223#elif defined(WITH_RIOT_SOCK)
224 if (s->addr.family == AF_INET6) {
225 a->size = (socklen_t)sizeof(a->addr.sin6);
226 a->addr.sa.sa_family = s->addr.family;
227 memcpy(&a->addr.sin6.sin6_addr, &s->addr.ipv6,
228 sizeof(a->addr.sin6.sin6_addr));
229 a->addr.sin6.sin6_port = s->addr.port;
230#ifdef SOCK_HAS_IPV4
231 } else if (s->addr.family == AF_INET) {
232 a->addr.sa.sa_family = s->addr.family;
233 a->size = (socklen_t)sizeof(a->addr.sin);
234 memcpy(&a->addr.sin.sin_addr, &s->addr.ipv4, sizeof(a->addr.sin.sin_addr));
235 a->addr.sin.sin_port = s->addr.port;
236#endif /* SOCK_HAS_IPV4 */
237 }
238#else /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
239 if (s->addr.sa.sa_family == AF_INET6) {
240 a->size = (socklen_t)sizeof(a->addr.sin6);
241 a->addr.sin6 = s->addr.sin6;
242 } else if (s->addr.sa.sa_family == AF_INET) {
243 a->size = (socklen_t)sizeof(a->addr.sin);
244 a->addr.sin = s->addr.sin;
245 } else {
246 a->size = (socklen_t)s->size;
247 a->addr.sa = s->addr.sa;
248 }
249#endif /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
250}
251
252static void
253put_session_addr(const coap_address_t *a, session_t *s) {
254#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
255 s->size = (unsigned char)sizeof(s->addr);
256 s->addr = a->addr;
257 s->port = a->port;
258#elif defined(WITH_RIOT_SOCK)
259 if (a->addr.sa.sa_family == AF_INET6) {
260 s->size = (socklen_t)sizeof(s->addr.ipv6);
261 s->addr.family = a->addr.sa.sa_family;
262 memcpy(&s->addr.ipv6, &a->addr.sin6.sin6_addr,
263 sizeof(s->addr.ipv6));
264 s->addr.port = a->addr.sin6.sin6_port;
265#ifdef SOCK_HAS_IPV4
266 } else if (a->addr.sa.sa_family == AF_INET) {
267 s->size = (socklen_t)sizeof(s->addr.ipv4);
268 s->addr.family = a->addr.sa.sa_family;
269 memcpy(&a->addr.ipv4, &s->addr.sin.sin_addr, sizeof(a->addr.ipv4));
270 s->addr.port = a->addr.sin.sin_port;
271#endif /* SOCK_HAS_IPV4 */
272 }
273#else /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
274 if (a->addr.sa.sa_family == AF_INET6) {
275 s->size = (socklen_t)sizeof(s->addr.sin6);
276 s->addr.sin6 = a->addr.sin6;
277 } else if (a->addr.sa.sa_family == AF_INET) {
278 s->size = (socklen_t)sizeof(s->addr.sin);
279 s->addr.sin = a->addr.sin;
280 } else {
281 s->size = (socklen_t)a->size;
282 s->addr.sa = a->addr.sa;
283 }
284#endif /* ! WITH_CONTIKI && ! WITH_LWIP && ! WITH_RIOT_SOCK */
285}
286
287static int
288dtls_send_to_peer(struct dtls_context_t *dtls_context,
289 session_t *dtls_session, uint8 *data, size_t len) {
290 coap_tiny_context_t *t_context =
291 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
292 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
293 coap_session_t *coap_session;
294 coap_address_t remote_addr;
295
296 assert(coap_context);
297 get_session_addr(dtls_session, &remote_addr);
298 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
299 if (!coap_session) {
300 coap_log_warn("dtls_send_to_peer: cannot find local interface\n");
301 return -3;
302 }
303 return (int)coap_session->sock.lfunc[COAP_LAYER_TLS].l_write(coap_session,
304 data, len);
305}
306
307static int
308dtls_application_data(struct dtls_context_t *dtls_context,
309 session_t *dtls_session, uint8 *data, size_t len) {
310 coap_tiny_context_t *t_context =
311 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
312 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
313 coap_session_t *coap_session;
314 coap_address_t remote_addr;
315
316 assert(coap_context);
317 get_session_addr(dtls_session, &remote_addr);
318 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
319 if (!coap_session) {
320 coap_log_debug("dropped message that was received on invalid interface\n");
321 return -1;
322 }
323
324 return coap_handle_dgram(coap_context, coap_session, data, len);
325}
326
327static int coap_event_dtls = 0;
328
329static int
330dtls_event(struct dtls_context_t *dtls_context,
331 session_t *dtls_session,
332 dtls_alert_level_t level,
333 uint16_t code) {
334 (void)dtls_context;
335 (void)dtls_session;
336
337 if (level == DTLS_ALERT_LEVEL_FATAL)
338 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
339
340 /* handle DTLS events */
341 switch (code) {
342 case DTLS_ALERT_CLOSE_NOTIFY: {
343 coap_event_dtls = COAP_EVENT_DTLS_CLOSED;
344 break;
345 }
346 case DTLS_EVENT_CONNECTED: {
347 coap_event_dtls = COAP_EVENT_DTLS_CONNECTED;
348 break;
349 }
350#ifdef DTLS_EVENT_RENEGOTIATE
351 case DTLS_EVENT_RENEGOTIATE: {
352 coap_event_dtls = COAP_EVENT_DTLS_RENEGOTIATE;
353 break;
354 }
355#endif
356 default:
357 ;
358 }
359
360 return 0;
361}
362
363#ifdef DTLS_PSK
364/* This function is the "key store" for tinyDTLS. It is called to
365 * retrieve a key for the given identity within this particular
366 * session. */
367static int
368get_psk_info(struct dtls_context_t *dtls_context,
369 const session_t *dtls_session,
370 dtls_credentials_type_t type,
371 const uint8_t *id, size_t id_len,
372 unsigned char *result, size_t result_length) {
373
374 coap_tiny_context_t *t_context =
375 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
376 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
377 coap_session_t *coap_session;
378 int fatal_error = DTLS_ALERT_INTERNAL_ERROR;
379 coap_address_t remote_addr;
380#if COAP_CLIENT_SUPPORT
381 coap_dtls_cpsk_t *setup_cdata;
382 const coap_bin_const_t *psk_identity;
383 const coap_dtls_cpsk_info_t *cpsk_info;
384#endif /* COAP_CLIENT_SUPPORT */
385 const coap_bin_const_t *psk_key;
386#if COAP_SERVER_SUPPORT
387 coap_dtls_spsk_t *setup_sdata;
388 const coap_bin_const_t *psk_hint;
389#endif /* COAP_SERVER_SUPPORT */
390
391 assert(coap_context);
392 get_session_addr(dtls_session, &remote_addr);
393 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
394 if (!coap_session) {
395 coap_log_debug("cannot get PSK, session not found\n");
396 goto error;
397 }
398
399 switch (type) {
400 case DTLS_PSK_IDENTITY:
401
402#if COAP_CLIENT_SUPPORT
403 if (coap_session->type != COAP_SESSION_TYPE_CLIENT)
404 goto error;
405
406 setup_cdata = &coap_session->cpsk_setup_data;
407
408 coap_bin_const_t temp;
409 temp.s = id;
410 temp.length = id_len;
411 coap_session_refresh_psk_hint(coap_session, &temp);
412
413 coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)id_len,
414 id ? (const char *)id : "");
415
416 if (setup_cdata->validate_ih_call_back) {
417 coap_str_const_t lhint;
418
419 lhint.length = id_len;
420 lhint.s = id;
421 cpsk_info =
422 setup_cdata->validate_ih_call_back(&lhint,
423 coap_session,
424 setup_cdata->ih_call_back_arg);
425 if (cpsk_info) {
426 psk_identity = &cpsk_info->identity;
427 coap_session_refresh_psk_identity(coap_session, &cpsk_info->identity);
428 coap_session_refresh_psk_key(coap_session, &cpsk_info->key);
429 } else {
430 psk_identity = NULL;
431 }
432 } else {
433 psk_identity = coap_get_session_client_psk_identity(coap_session);
434 }
435 if (psk_identity == NULL) {
436 coap_log_warn("no PSK identity given\n");
437 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
438 goto error;
439 }
440 if (psk_identity->length > result_length) {
441 coap_log_warn("psk_identity too large, truncated to %zd bytes\n",
442 result_length);
443 } else {
444 /* Reduce to match */
445 result_length = psk_identity->length;
446 }
447 memcpy(result, psk_identity->s, result_length);
448 return result_length;
449#else /* ! COAP_CLIENT_SUPPORT */
450 return 0;
451#endif /* ! COAP_CLIENT_SUPPORT */
452
453 case DTLS_PSK_KEY:
454#if COAP_CLIENT_SUPPORT
455 if (coap_session->type == COAP_SESSION_TYPE_CLIENT) {
456 psk_key = coap_get_session_client_psk_key(coap_session);
457 if (psk_key == NULL) {
458 coap_log_warn("no PSK key given\n");
459 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
460 goto error;
461 }
462 if (psk_key->length > result_length) {
463 coap_log_warn("psk_key too large, truncated to %zd bytes\n",
464 result_length);
465 } else {
466 /* Reduce to match */
467 result_length = psk_key->length;
468 }
469 memcpy(result, psk_key->s, result_length);
470 return result_length;
471 }
472#endif /* COAP_CLIENT_SUPPORT */
473#if COAP_SERVER_SUPPORT
474 if (coap_session->type != COAP_SESSION_TYPE_CLIENT) {
475 coap_bin_const_t lidentity;
476
477 lidentity.length = id ? id_len : 0;
478 lidentity.s = id ? (const uint8_t *)id : (const uint8_t *)"";
479 setup_sdata = &coap_session->context->spsk_setup_data;
480
481 /* Track the Identity being used */
482 coap_session_refresh_psk_identity(coap_session, &lidentity);
483
484 coap_log_debug("got psk_identity: '%.*s'\n",
485 (int)lidentity.length, lidentity.s);
486
487 if (setup_sdata->validate_id_call_back) {
488 psk_key =
489 setup_sdata->validate_id_call_back(&lidentity,
490 coap_session,
491 setup_sdata->id_call_back_arg);
492 } else {
493 psk_key = coap_get_session_server_psk_key(coap_session);
494 }
495
496 if (psk_key == NULL) {
497 coap_log_warn("no PSK key given\n");
498 return 0;
499 }
500 if (setup_sdata->validate_id_call_back)
501 coap_session_refresh_psk_key(coap_session, psk_key);
502 if (psk_key->length > result_length) {
503 coap_log_warn("psk_key too large, truncated to %zd bytes\n",
504 result_length);
505 } else {
506 /* Reduce to match */
507 result_length = psk_key->length;
508 }
509 memcpy(result, psk_key->s, result_length);
510 return result_length;
511 }
512#endif /* COAP_SERVER_SUPPORT */
513 return 0;
514
515 case DTLS_PSK_HINT:
516#if COAP_SERVER_SUPPORT
517 psk_hint = coap_get_session_server_psk_hint(coap_session);
518 if (psk_hint == NULL)
519 return 0;
520 if (psk_hint->length > result_length) {
521 coap_log_warn("psk_hint too large, truncated to %zd bytes\n",
522 result_length);
523 } else {
524 /* Reduce to match */
525 result_length = psk_hint->length;
526 }
527 memcpy(result, psk_hint->s, result_length);
528 return result_length;
529#else /* COAP_SERVER_SUPPORT */
530 return 0;
531#endif /* COAP_SERVER_SUPPORT */
532
533 default:
534 coap_log_warn("unsupported request type: %d\n", type);
535 }
536
537error:
538 return dtls_alert_fatal_create(fatal_error);
539}
540#endif /* DTLS_PSK */
541
542#ifdef DTLS_ECC
543static int
544get_ecdsa_key(struct dtls_context_t *dtls_context,
545 const session_t *dtls_session COAP_UNUSED,
546 const dtls_ecdsa_key_t **result) {
547 static dtls_ecdsa_key_t ecdsa_key;
548 coap_tiny_context_t *t_context =
549 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
550
551 ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1;
552 ecdsa_key.priv_key = t_context->priv_key->s;
553 ecdsa_key.pub_key_x = t_context->pub_key->s;
554 ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE];
555
556 *result = &ecdsa_key;
557 return 0;
558}
559
560/* first part of Raw public key, the is the start of the Subject Public Key */
561static const unsigned char cert_asn1_header[] = {
562 0x30, 0x59, /* SEQUENCE, length 89 bytes */
563 0x30, 0x13, /* SEQUENCE, length 19 bytes */
564 0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */
565 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
566 0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */
567 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
568 0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */
569 0x04 /* uncompressed, followed by the r and s values of the public key */
570};
571#define DTLS_CE_LENGTH (sizeof(cert_asn1_header) + key_size + key_size)
572
573static int
574verify_ecdsa_key(struct dtls_context_t *dtls_context COAP_UNUSED,
575 const session_t *dtls_session COAP_UNUSED,
576 const uint8_t *other_pub_x,
577 const uint8_t *other_pub_y,
578 size_t key_size) {
579 coap_tiny_context_t *t_context =
580 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
581 if (t_context && t_context->setup_data.validate_cn_call_back) {
582 /* Need to build asn.1 certificate - code taken from tinydtls */
583 uint8 *p;
584 uint8 buf[DTLS_CE_LENGTH];
585 coap_session_t *c_session;
586 coap_address_t remote_addr;
587
588 /* Certificate
589 *
590 * Start message construction at beginning of buffer. */
591 p = buf;
592
593 memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
594 p += sizeof(cert_asn1_header);
595
596 memcpy(p, other_pub_x, key_size);
597 p += key_size;
598
599 memcpy(p, other_pub_y, key_size);
600 p += key_size;
601
602 assert(p <= (buf + sizeof(buf)));
603
604 get_session_addr(dtls_session, &remote_addr);
605 c_session = coap_session_get_by_peer(t_context->coap_context,
606 &remote_addr, dtls_session->ifindex);
607 if (!c_session)
608 return -3;
609 if (!t_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN,
610 buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg)) {
611 return -1;
612 }
613 }
614 return 0;
615}
616static dtls_handler_t ec_cb = {
617 .write = dtls_send_to_peer,
618 .read = dtls_application_data,
619 .event = dtls_event,
620#ifdef DTLS_PSK
621 .get_psk_info = NULL,
622#endif /* DTLS_PSK */
623 .get_ecdsa_key = get_ecdsa_key,
624 .verify_ecdsa_key = verify_ecdsa_key
625};
626#endif /* DTLS_ECC */
627
628static dtls_handler_t psk_cb = {
629 .write = dtls_send_to_peer,
630 .read = dtls_application_data,
631 .event = dtls_event,
632#ifdef DTLS_PSK
633 .get_psk_info = get_psk_info,
634#endif /* DTLS_PSK */
635#ifdef DTLS_ECC
636 .get_ecdsa_key = NULL,
637 .verify_ecdsa_key = NULL
638#endif /* DTLS_ECC */
639};
640
641void *
643 coap_tiny_context_t *t_context = coap_malloc_type(COAP_DTLS_CONTEXT, sizeof(coap_tiny_context_t));
644 struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL;
645 if (!dtls_context)
646 goto error;
647 memset(t_context, 0, sizeof(coap_tiny_context_t));
648 t_context->coap_context = coap_context;
649 t_context->dtls_context = dtls_context;
650 dtls_set_handler(dtls_context, &psk_cb);
651 return t_context;
652error:
653 if (t_context)
655 if (dtls_context)
656 coap_dtls_free_context(dtls_context);
657 return NULL;
658}
659
660void
661coap_dtls_free_context(void *handle) {
662 if (handle) {
663 coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
664#ifdef DTLS_ECC
665 if (t_context->priv_key) {
666 coap_delete_binary(t_context->priv_key);
667 t_context->priv_key = NULL;
668 }
669 if (t_context->pub_key) {
670 coap_delete_binary(t_context->pub_key);
671 t_context->pub_key = NULL;
672 }
673#endif /* DTLS_ECC */
674 if (t_context->dtls_context)
675 dtls_free_context(t_context->dtls_context);
677 }
678}
679
680static session_t *
681coap_dtls_new_session(coap_session_t *session) {
682 session_t *dtls_session = coap_malloc_type(COAP_DTLS_SESSION, sizeof(session_t));
683
684 if (dtls_session) {
685 /* create tinydtls session object from remote address and local
686 * endpoint handle */
687 dtls_session_init(dtls_session);
688 put_session_addr(&session->addr_info.remote, dtls_session);
689 dtls_session->ifindex = session->ifindex;
690 coap_log_debug("***new session %p\n", (void *)dtls_session);
691 }
692
693 return dtls_session;
694}
695
696#if COAP_SERVER_SUPPORT
697void *
699 return coap_dtls_new_session(session);
700}
701#endif /* COAP_SERVER_SUPPORT */
702
703#if COAP_CLIENT_SUPPORT
704void *
706 dtls_peer_t *peer;
707 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
708 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
709 session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL;
710
711 if (!dtls_session)
712 return NULL;
713 peer =
714 dtls_get_peer(dtls_context, dtls_session);
715
716 if (!peer) {
717 /* The peer connection does not yet exist. */
718 /* dtls_connect() returns a value greater than zero if a new
719 * connection attempt is made, 0 for session reuse. */
720 if (dtls_connect(dtls_context, dtls_session) >= 0) {
721 peer =
722 dtls_get_peer(dtls_context, dtls_session);
723 }
724 }
725
726 if (!peer) {
727 /* delete existing session because the peer object has been invalidated */
728 coap_free_type(COAP_DTLS_SESSION, dtls_session);
729 dtls_session = NULL;
730 }
731
732 return dtls_session;
733}
734#endif /* COAP_CLIENT_SUPPORT */
735
736void
738 (void)session;
739}
740
741void
743 coap_tiny_context_t *t_context =
744 (coap_tiny_context_t *)coap_session->context->dtls_context;
745 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
746
747 if (dtls_context == NULL)
748 return;
749 if (coap_session->tls && dtls_context) {
750 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->tls);
751 if (peer)
752 dtls_reset_peer(dtls_context, peer);
753 else
754 dtls_close(dtls_context, (session_t *)coap_session->tls);
755 coap_log_debug("***removed session %p\n", coap_session->tls);
756 coap_free_type(COAP_DTLS_SESSION, coap_session->tls);
757 coap_session->tls = NULL;
758 coap_handle_event(coap_session->context, COAP_EVENT_DTLS_CLOSED, coap_session);
759 }
760}
761
762ssize_t
764 const uint8_t *data,
765 size_t data_len) {
766 int res;
767 uint8_t *data_rw;
768 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
769 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
770
771 assert(dtls_context);
772
773 coap_event_dtls = -1;
774 /* Need to do this to not get a compiler warning about const parameters */
775 memcpy(&data_rw, &data, sizeof(data_rw));
776 res = dtls_write(dtls_context,
777 (session_t *)session->tls, data_rw, data_len);
778
779 if (res < 0)
780 coap_log_warn("coap_dtls_send: cannot send PDU\n");
781
782 if (coap_event_dtls >= 0) {
783 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
784 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
785 coap_handle_event(session->context, coap_event_dtls, session);
786 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
787 coap_session_connected(session);
788 else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
790 }
791
792 if (res > 0) {
793 if (res == (ssize_t)data_len)
794 coap_log_debug("* %s: dtls: sent %4d bytes\n",
795 coap_session_str(session), res);
796 else
797 coap_log_debug("* %s: dtls: sent %4d of %4zd bytes\n",
798 coap_session_str(session), res, data_len);
799 }
800 return res;
801}
802
803int
805 return 1;
806}
807
809coap_dtls_get_context_timeout(void *tiny_context) {
810 clock_time_t next = 0;
811 coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
812 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
813 if (tiny_context)
814 dtls_check_retransmit(dtls_context, &next);
815 if (next > 0)
816 return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND +
817 coap_tick_0;
818 return 0;
819}
820
823 (void)session;
824 (void)now;
825 return 0;
826}
827
828/*
829 * return 1 timed out
830 * 0 still timing out
831 */
832int
834 (void)session;
835 return 0;
836}
837
838int
840 const uint8_t *data,
841 size_t data_len
842 ) {
843 session_t *dtls_session = (session_t *)session->tls;
844 int err;
845 uint8_t *data_rw;
846 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
847 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
848
849 assert(dtls_context);
850 coap_event_dtls = -1;
851 /* Need to do this to not get a compiler warning about const parameters */
852 memcpy(&data_rw, &data, sizeof(data_rw));
853 err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len);
854
855 if (err) {
856 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
857 }
858
859 if (coap_event_dtls >= 0) {
860 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
861 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
862 coap_handle_event(session->context, coap_event_dtls, session);
863 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
864 coap_session_connected(session);
865 else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
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 (void)alg;
1492 (void)data;
1493 (void)hash;
1494 return 0;
1495}
1496#endif /* COAP_WS_SUPPORT */
1497
1498#if COAP_OSCORE_SUPPORT
1499
1500int
1502 return 1;
1503}
1504
1505/*
1506 * The struct cipher_algs and the function get_cipher_alg() are used to
1507 * determine which cipher type to use for creating the required cipher
1508 * suite object.
1509 */
1510static struct cipher_algs {
1511 cose_alg_t alg;
1512 u_int cipher_type;
1513} ciphers[] = {
1515};
1516
1517static u_int
1518get_cipher_alg(cose_alg_t alg) {
1519 size_t idx;
1520
1521 for (idx = 0; idx < sizeof(ciphers)/sizeof(struct cipher_algs); idx++) {
1522 if (ciphers[idx].alg == alg)
1523 return ciphers[idx].cipher_type;
1524 }
1525 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
1526 return 0;
1527}
1528
1529/*
1530 * The struct hmac_algs and the function get_hmac_alg() are used to
1531 * determine which hmac type to use for creating the required hmac
1532 * suite object.
1533 */
1534static struct hmac_algs {
1535 cose_hmac_alg_t hmac_alg;
1536 u_int hmac_type;
1537} hmacs[] = {
1539};
1540
1541static u_int
1542get_hmac_alg(cose_hmac_alg_t hmac_alg) {
1543 size_t idx;
1544
1545 for (idx = 0; idx < sizeof(hmacs)/sizeof(struct hmac_algs); idx++) {
1546 if (hmacs[idx].hmac_alg == hmac_alg)
1547 return hmacs[idx].hmac_type;
1548 }
1549 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
1550 return 0;
1551}
1552
1553int
1555 return get_cipher_alg(alg);
1556}
1557
1558int
1560 cose_hmac_alg_t hmac_alg;
1561
1562 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
1563 return 0;
1564 return get_hmac_alg(hmac_alg);
1565}
1566
1567int
1569 coap_bin_const_t *data,
1570 coap_bin_const_t *aad,
1571 uint8_t *result, size_t *max_result_len) {
1572 int num_bytes;
1573 const coap_crypto_aes_ccm_t *ccm;
1574 dtls_ccm_params_t dtls_params;
1575 coap_bin_const_t laad;
1576
1577 if (data == NULL)
1578 return 0;
1579
1580 assert(params);
1581
1582 if (get_cipher_alg(params->alg) == 0) {
1583 coap_log_debug("coap_crypto_encrypt: algorithm %d not supported\n",
1584 params->alg);
1585 return 0;
1586 }
1587
1588 ccm = &params->params.aes;
1589 if (*max_result_len < (data->length + ccm->tag_len)) {
1590 coap_log_warn("coap_encrypt: result buffer too small\n");
1591 return 0;
1592 }
1593
1594 dtls_params.nonce = ccm->nonce;
1595 dtls_params.tag_length = ccm->tag_len;
1596 dtls_params.l = ccm->l;
1597
1598 if (aad) {
1599 laad = *aad;
1600 } else {
1601 laad.s = NULL;
1602 laad.length = 0;
1603 }
1604
1605 num_bytes = dtls_encrypt_params(&dtls_params,
1606 data->s, data->length,
1607 result,
1608 ccm->key.s, ccm->key.length,
1609 laad.s, laad.length);
1610 if (num_bytes < 0) {
1611 return 0;
1612 }
1613 *max_result_len = num_bytes;
1614 return 1;
1615}
1616
1617int
1619 coap_bin_const_t *data,
1620 coap_bin_const_t *aad,
1621 uint8_t *result, size_t *max_result_len) {
1622 int num_bytes;
1623 const coap_crypto_aes_ccm_t *ccm;
1624 dtls_ccm_params_t dtls_params;
1625 coap_bin_const_t laad;
1626
1627 if (data == NULL)
1628 return 0;
1629
1630 assert(params);
1631
1632 if (get_cipher_alg(params->alg) == 0) {
1633 coap_log_debug("coap_crypto_decrypt: algorithm %d not supported\n",
1634 params->alg);
1635 return 0;
1636 }
1637
1638 ccm = &params->params.aes;
1639
1640 if ((*max_result_len + ccm->tag_len) < data->length) {
1641 coap_log_warn("coap_decrypt: result buffer too small\n");
1642 return 0;
1643 }
1644
1645 dtls_params.nonce = ccm->nonce;
1646 dtls_params.tag_length = ccm->tag_len;
1647 dtls_params.l = ccm->l;
1648
1649 if (aad) {
1650 laad = *aad;
1651 } else {
1652 laad.s = NULL;
1653 laad.length = 0;
1654 }
1655
1656 num_bytes = dtls_decrypt_params(&dtls_params,
1657 data->s, data->length,
1658 result,
1659 ccm->key.s, ccm->key.length,
1660 laad.s, laad.length);
1661 if (num_bytes < 0) {
1662 return 0;
1663 }
1664 *max_result_len = num_bytes;
1665 return 1;
1666}
1667
1668int
1670 coap_bin_const_t *data, coap_bin_const_t **hmac) {
1671 dtls_hmac_context_t hmac_context;
1672 int num_bytes;
1674
1675 if (data == NULL)
1676 return 0;
1677
1678 if (get_hmac_alg(hmac_alg) == 0) {
1679 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
1680 return 0;
1681 }
1682
1683 dummy = coap_new_binary(DTLS_SHA256_DIGEST_LENGTH);
1684 if (dummy == NULL)
1685 return 0;
1686
1687 dtls_hmac_init(&hmac_context, key->s, key->length);
1688 dtls_hmac_update(&hmac_context, data->s, data->length);
1689 num_bytes = dtls_hmac_finalize(&hmac_context, dummy->s);
1690
1691 if (num_bytes != DTLS_SHA256_DIGEST_LENGTH) {
1693 return 0;
1694 }
1695 *hmac = (coap_bin_const_t *)dummy;
1696 return 1;
1697}
1698
1699#endif /* COAP_OSCORE_SUPPORT */
1700
1701#else /* !COAP_WITH_LIBTINYDTLS */
1702
1703#ifdef __clang__
1704/* Make compilers happy that do not like empty modules. As this function is
1705 * never used, we ignore -Wunused-function at the end of compiling this file
1706 */
1707#pragma GCC diagnostic ignored "-Wunused-function"
1708#endif
1709static inline void
1710dummy(void) {
1711}
1712
1713#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:192
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:264
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition: coap_notls.c:187
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:206
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:224
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:175
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:252
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:171
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:201
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition: coap_notls.c:149
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:167
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition: coap_notls.c:144
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:243
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:182
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:139
#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:134
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