libcoap 4.3.1
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-2022 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 HAVE_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#include <tinydtls/tinydtls.h>
31#include <tinydtls/dtls.h>
32#include <tinydtls/dtls_debug.h>
33
34typedef struct coap_tiny_context_t {
35 struct dtls_context_t *dtls_context;
36 coap_context_t *coap_context;
37#ifdef DTLS_ECC
38 coap_dtls_pki_t setup_data;
39 coap_binary_t *priv_key;
40 coap_binary_t *pub_key;
41#endif /* DTLS_ECC */
42} coap_tiny_context_t;
43
44static dtls_tick_t dtls_tick_0 = 0;
45static coap_tick_t coap_tick_0 = 0;
46
47int
49 return 1;
50}
51
52void coap_dtls_startup(void) {
53 dtls_init();
54 dtls_ticks(&dtls_tick_0);
55 coap_ticks(&coap_tick_0);
56}
57
58void coap_dtls_shutdown(void) {
59}
60
61void *
62coap_dtls_get_tls(const coap_session_t *c_session,
63 coap_tls_library_t *tls_lib) {
64 if (tls_lib)
66 if (c_session && c_session->context && c_session->context->dtls_context) {
67 const coap_tiny_context_t *t_context =
68 (const coap_tiny_context_t *)c_session->context->dtls_context;
69
70 return t_context->dtls_context;
71 }
72 return NULL;
73}
74
75void
76coap_dtls_set_log_level(int level) {
77 dtls_set_log_level(level);
78}
79
80int
82 return dtls_get_log_level();
83}
84
85static void get_session_addr(const session_t *s, coap_address_t *a) {
86#ifdef WITH_CONTIKI
87 a->addr = s->addr;
88 a->port = s->port;
89#else
90 if (s->addr.sa.sa_family == AF_INET6) {
91 a->size = (socklen_t)sizeof(a->addr.sin6);
92 a->addr.sin6 = s->addr.sin6;
93 } else if (s->addr.sa.sa_family == AF_INET) {
94 a->size = (socklen_t)sizeof(a->addr.sin);
95 a->addr.sin = s->addr.sin;
96 } else {
97 a->size = (socklen_t)s->size;
98 a->addr.sa = s->addr.sa;
99 }
100#endif
101}
102
103static void put_session_addr(const coap_address_t *a, session_t *s) {
104#ifdef WITH_CONTIKI
105 s->size = (unsigned char)sizeof(s->addr);
106 s->addr = a->addr;
107 s->port = a->port;
108#else
109 if (a->addr.sa.sa_family == AF_INET6) {
110 s->size = (socklen_t)sizeof(s->addr.sin6);
111 s->addr.sin6 = a->addr.sin6;
112 } else if (a->addr.sa.sa_family == AF_INET) {
113 s->size = (socklen_t)sizeof(s->addr.sin);
114 s->addr.sin = a->addr.sin;
115 } else {
116 s->size = (socklen_t)a->size;
117 s->addr.sa = a->addr.sa;
118 }
119#endif
120}
121
122static int
123dtls_send_to_peer(struct dtls_context_t *dtls_context,
124 session_t *dtls_session, uint8 *data, size_t len) {
125 coap_tiny_context_t *t_context =
126 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
127 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
128 coap_session_t *coap_session;
129 coap_address_t remote_addr;
130
131 assert(coap_context);
132 get_session_addr(dtls_session, &remote_addr);
133 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
134 if (!coap_session) {
135 coap_log(LOG_WARNING, "dtls_send_to_peer: cannot find local interface\n");
136 return -3;
137 }
138 return (int)coap_session_send(coap_session, data, len);
139}
140
141static int
142dtls_application_data(struct dtls_context_t *dtls_context,
143 session_t *dtls_session, uint8 *data, size_t len) {
144 coap_tiny_context_t *t_context =
145 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
146 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
147 coap_session_t *coap_session;
148 coap_address_t remote_addr;
149
150 assert(coap_context);
151 get_session_addr(dtls_session, &remote_addr);
152 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
153 if (!coap_session) {
155 "dropped message that was received on invalid interface\n");
156 return -1;
157 }
158
159 return coap_handle_dgram(coap_context, coap_session, data, len);
160}
161
162static int coap_event_dtls = 0;
163
164static int
165dtls_event(struct dtls_context_t *dtls_context,
166 session_t *dtls_session,
167 dtls_alert_level_t level,
168 uint16_t code) {
169 (void)dtls_context;
170 (void)dtls_session;
171
172 if (level == DTLS_ALERT_LEVEL_FATAL)
173 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
174
175 /* handle DTLS events */
176 switch (code) {
177 case DTLS_ALERT_CLOSE_NOTIFY:
178 {
179 coap_event_dtls = COAP_EVENT_DTLS_CLOSED;
180 break;
181 }
182 case DTLS_EVENT_CONNECTED:
183 {
184 coap_event_dtls = COAP_EVENT_DTLS_CONNECTED;
185 break;
186 }
187 case DTLS_EVENT_RENEGOTIATE:
188 {
189 coap_event_dtls = COAP_EVENT_DTLS_RENEGOTIATE;
190 break;
191 }
192 default:
193 ;
194 }
195
196 return 0;
197}
198
199/* This function is the "key store" for tinyDTLS. It is called to
200 * retrieve a key for the given identity within this particular
201 * session. */
202static int
203get_psk_info(struct dtls_context_t *dtls_context,
204 const session_t *dtls_session,
205 dtls_credentials_type_t type,
206 const uint8_t *id, size_t id_len,
207 unsigned char *result, size_t result_length) {
208
209 coap_tiny_context_t *t_context =
210 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
211 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
212 coap_session_t *coap_session;
213 int fatal_error = DTLS_ALERT_INTERNAL_ERROR;
214 coap_address_t remote_addr;
215#if COAP_CLIENT_SUPPORT
216 coap_dtls_cpsk_t *setup_cdata;
217 const coap_bin_const_t *psk_identity;
218 const coap_dtls_cpsk_info_t *cpsk_info;
219#endif /* COAP_CLIENT_SUPPORT */
220 const coap_bin_const_t *psk_key;
221#if COAP_SERVER_SUPPORT
222 coap_dtls_spsk_t *setup_sdata;
223 const coap_bin_const_t *psk_hint;
224#endif /* COAP_SERVER_SUPPORT */
225
226 assert(coap_context);
227 get_session_addr(dtls_session, &remote_addr);
228 coap_session = coap_session_get_by_peer(coap_context, &remote_addr, dtls_session->ifindex);
229 if (!coap_session) {
230 coap_log(LOG_DEBUG, "cannot get PSK, session not found\n");
231 goto error;
232 }
233
234 switch (type) {
235 case DTLS_PSK_IDENTITY:
236
237#if COAP_CLIENT_SUPPORT
238 if (coap_session->type != COAP_SESSION_TYPE_CLIENT)
239 goto error;
240
241 setup_cdata = &coap_session->cpsk_setup_data;
242
243 coap_bin_const_t temp;
244 temp.s = id;
245 temp.length = id_len;
246 coap_session_refresh_psk_hint(coap_session, &temp);
247
248 coap_log(LOG_DEBUG, "got psk_identity_hint: '%.*s'\n", (int)id_len,
249 id ? (const char*)id : "");
250
251 if (setup_cdata->validate_ih_call_back) {
252 coap_str_const_t lhint;
253
254 lhint.length = id_len;
255 lhint.s = id;
256 cpsk_info =
257 setup_cdata->validate_ih_call_back(&lhint,
258 coap_session,
259 setup_cdata->ih_call_back_arg);
260 if (cpsk_info) {
261 psk_identity = &cpsk_info->identity;
262 coap_session_refresh_psk_identity(coap_session, &cpsk_info->identity);
263 coap_session_refresh_psk_key(coap_session, &cpsk_info->key);
264 }
265 else {
266 psk_identity = NULL;
267 }
268 }
269 else {
270 psk_identity = coap_get_session_client_psk_identity(coap_session);
271 }
272 if (psk_identity == NULL) {
273 coap_log(LOG_WARNING, "no PSK identity given\n");
274 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
275 goto error;
276 }
277 if (psk_identity->length > result_length) {
279 "psk_identity too large, truncated to %zd bytes\n",
280 result_length);
281 }
282 else {
283 /* Reduce to match */
284 result_length = psk_identity->length;
285 }
286 memcpy(result, psk_identity->s, result_length);
287 return result_length;
288#else /* ! COAP_CLIENT_SUPPORT */
289 return 0;
290#endif /* ! COAP_CLIENT_SUPPORT */
291
292 case DTLS_PSK_KEY:
293#if COAP_CLIENT_SUPPORT
294 if (coap_session->type == COAP_SESSION_TYPE_CLIENT) {
295 psk_key = coap_get_session_client_psk_key(coap_session);
296 if (psk_key == NULL) {
297 coap_log(LOG_WARNING, "no PSK key given\n");
298 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
299 goto error;
300 }
301 if (psk_key->length > result_length) {
303 "psk_key too large, truncated to %zd bytes\n",
304 result_length);
305 }
306 else {
307 /* Reduce to match */
308 result_length = psk_key->length;
309 }
310 memcpy(result, psk_key->s, result_length);
311 return result_length;
312 }
313#endif /* COAP_CLIENT_SUPPORT */
314#if COAP_SERVER_SUPPORT
315 if (coap_session->type != COAP_SESSION_TYPE_CLIENT) {
316 coap_bin_const_t lidentity;
317
318 lidentity.length = id ? id_len : 0;
319 lidentity.s = id ? (const uint8_t*)id : (const uint8_t *)"";
320 setup_sdata = &coap_session->context->spsk_setup_data;
321
322 /* Track the Identity being used */
323 coap_session_refresh_psk_identity(coap_session, &lidentity);
324
325 coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n",
326 (int)lidentity.length, lidentity.s);
327
328 if (setup_sdata->validate_id_call_back) {
329 psk_key =
330 setup_sdata->validate_id_call_back(&lidentity,
331 coap_session,
332 setup_sdata->id_call_back_arg);
333 }
334 else {
335 psk_key = coap_get_session_server_psk_key(coap_session);
336 }
337
338 if (psk_key == NULL) {
339 coap_log(LOG_WARNING, "no PSK key given\n");
340 return 0;
341 }
342 if (setup_sdata->validate_id_call_back)
343 coap_session_refresh_psk_key(coap_session, psk_key);
344 if (psk_key->length > result_length) {
346 "psk_key too large, truncated to %zd bytes\n",
347 result_length);
348 }
349 else {
350 /* Reduce to match */
351 result_length = psk_key->length;
352 }
353 memcpy(result, psk_key->s, result_length);
354 return result_length;
355 }
356#endif /* COAP_SERVER_SUPPORT */
357 return 0;
358
359 case DTLS_PSK_HINT:
360#if COAP_SERVER_SUPPORT
361 psk_hint = coap_get_session_server_psk_hint(coap_session);
362 if (psk_hint == NULL)
363 return 0;
364 if (psk_hint->length > result_length) {
366 "psk_hint too large, truncated to %zd bytes\n",
367 result_length);
368 }
369 else {
370 /* Reduce to match */
371 result_length = psk_hint->length;
372 }
373 memcpy(result, psk_hint->s, result_length);
374 return result_length;
375#else /* COAP_SERVER_SUPPORT */
376 return 0;
377#endif /* COAP_SERVER_SUPPORT */
378
379 default:
380 coap_log(LOG_WARNING, "unsupported request type: %d\n", type);
381 }
382
383error:
384 return dtls_alert_fatal_create(fatal_error);
385}
386
387#ifdef DTLS_ECC
388static int
389get_ecdsa_key(struct dtls_context_t *dtls_context,
390 const session_t *dtls_session COAP_UNUSED,
391 const dtls_ecdsa_key_t **result) {
392 static dtls_ecdsa_key_t ecdsa_key;
393 coap_tiny_context_t *t_context =
394 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
395
396 ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1;
397 ecdsa_key.priv_key = t_context->priv_key->s;
398 ecdsa_key.pub_key_x = t_context->pub_key->s;
399 ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE];
400
401 *result = &ecdsa_key;
402 return 0;
403}
404
405/* first part of Raw public key, the is the start of the Subject Public Key */
406static const unsigned char cert_asn1_header[] = {
407 0x30, 0x59, /* SEQUENCE, length 89 bytes */
408 0x30, 0x13, /* SEQUENCE, length 19 bytes */
409 0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */
410 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
411 0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */
412 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
413 0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */
414 0x04 /* uncompressed, followed by the r and s values of the public key */
415};
416#define DTLS_CE_LENGTH (sizeof(cert_asn1_header) + key_size + key_size)
417
418static int
419verify_ecdsa_key(struct dtls_context_t *dtls_context COAP_UNUSED,
420 const session_t *dtls_session COAP_UNUSED,
421 const uint8_t *other_pub_x,
422 const uint8_t *other_pub_y,
423 size_t key_size) {
424 coap_tiny_context_t *t_context =
425 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
426 if (t_context && t_context->setup_data.validate_cn_call_back) {
427 /* Need to build asn.1 certificate - code taken from tinydtls */
428 uint8 *p;
429 uint8 buf[DTLS_CE_LENGTH];
430 coap_session_t *c_session;
431 coap_address_t remote_addr;
432
433 /* Certificate
434 *
435 * Start message construction at beginning of buffer. */
436 p = buf;
437
438 memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
439 p += sizeof(cert_asn1_header);
440
441 memcpy(p, other_pub_x, key_size);
442 p += key_size;
443
444 memcpy(p, other_pub_y, key_size);
445 p += key_size;
446
447 assert(p <= (buf + sizeof(buf)));
448
449 get_session_addr(dtls_session, &remote_addr);
450 c_session = coap_session_get_by_peer(t_context->coap_context,
451 &remote_addr, dtls_session->ifindex);
452 if (!c_session)
453 return -3;
454 if (!t_context->setup_data.validate_cn_call_back(COAP_DTLS_RPK_CERT_CN,
455 buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg)) {
456 return -1;
457 }
458 }
459 return 0;
460}
461static dtls_handler_t ec_cb = {
462 .write = dtls_send_to_peer,
463 .read = dtls_application_data,
464 .event = dtls_event,
465 .get_psk_info = NULL,
466 .get_ecdsa_key = get_ecdsa_key,
467 .verify_ecdsa_key = verify_ecdsa_key
468};
469#endif /* DTLS_ECC */
470
471static dtls_handler_t psk_cb = {
472 .write = dtls_send_to_peer,
473 .read = dtls_application_data,
474 .event = dtls_event,
475 .get_psk_info = get_psk_info,
476#ifdef DTLS_ECC
477 .get_ecdsa_key = NULL,
478 .verify_ecdsa_key = NULL
479#endif
480};
481
482void *
484 coap_tiny_context_t *t_context = coap_malloc(sizeof(coap_tiny_context_t));
485 struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL;
486 if (!dtls_context)
487 goto error;
488 memset(t_context, 0, sizeof(coap_tiny_context_t));
489 t_context->coap_context = coap_context;
490 t_context->dtls_context = dtls_context;
491 dtls_set_handler(dtls_context, &psk_cb);
492 return t_context;
493error:
494 if (t_context)
495 coap_free(t_context);
496 if (dtls_context)
497 coap_dtls_free_context(dtls_context);
498 return NULL;
499}
500
501void
502coap_dtls_free_context(void *handle) {
503 if (handle) {
504 coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
505#ifdef DTLS_ECC
506 if (t_context->priv_key) {
507 coap_delete_binary(t_context->priv_key);
508 t_context->priv_key = NULL;
509 }
510 if (t_context->pub_key) {
511 coap_delete_binary(t_context->pub_key);
512 t_context->pub_key = NULL;
513 }
514#endif /* DTLS_ECC */
515 if (t_context->dtls_context)
516 dtls_free_context(t_context->dtls_context);
517 coap_free(t_context);
518 }
519}
520
521static session_t *
522coap_dtls_new_session(coap_session_t *session) {
523 session_t *dtls_session = coap_malloc_type(COAP_DTLS_SESSION, sizeof(session_t));
524
525 if (dtls_session) {
526 /* create tinydtls session object from remote address and local
527 * endpoint handle */
528 dtls_session_init(dtls_session);
529 put_session_addr(&session->addr_info.remote, dtls_session);
530 dtls_session->ifindex = session->ifindex;
531 coap_log(LOG_DEBUG, "***new session %p\n", (void *)dtls_session);
532 }
533
534 return dtls_session;
535}
536
537#if COAP_SERVER_SUPPORT
539 return coap_dtls_new_session(session);
540}
541#endif /* COAP_SERVER_SUPPORT */
542
543#if COAP_CLIENT_SUPPORT
545 dtls_peer_t *peer;
546 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
547 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
548 session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL;
549
550 if (!dtls_session)
551 return NULL;
552 peer =
553 dtls_get_peer(dtls_context, dtls_session);
554
555 if (!peer) {
556 /* The peer connection does not yet exist. */
557 /* dtls_connect() returns a value greater than zero if a new
558 * connection attempt is made, 0 for session reuse. */
559 if (dtls_connect(dtls_context, dtls_session) >= 0) {
560 peer =
561 dtls_get_peer(dtls_context, dtls_session);
562 }
563 }
564
565 if (!peer) {
566 /* delete existing session because the peer object has been invalidated */
567 coap_free_type(COAP_DTLS_SESSION, dtls_session);
568 dtls_session = NULL;
569 }
570
571 return dtls_session;
572}
573#endif /* COAP_CLIENT_SUPPORT */
574
575void
577 (void)session;
578}
579
580void
582 coap_tiny_context_t *t_context =
583 (coap_tiny_context_t *)coap_session->context->dtls_context;
584 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
585
586 if (dtls_context == NULL)
587 return;
588 if (coap_session->tls && dtls_context) {
589 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->tls);
590 if ( peer )
591 dtls_reset_peer(dtls_context, peer);
592 else
593 dtls_close(dtls_context, (session_t *)coap_session->tls);
594 coap_log(LOG_DEBUG, "***removed session %p\n", coap_session->tls);
595 coap_free_type(COAP_DTLS_SESSION, coap_session->tls);
596 coap_session->tls = NULL;
597 coap_handle_event(coap_session->context, COAP_EVENT_DTLS_CLOSED, coap_session);
598 }
599}
600
601int
603 const uint8_t *data,
604 size_t data_len
605) {
606 int res;
607 uint8_t *data_rw;
608 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
609 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
610
611 assert(dtls_context);
612 coap_log(LOG_DEBUG, "call dtls_write\n");
613
614 coap_event_dtls = -1;
615 /* Need to do this to not get a compiler warning about const parameters */
616 memcpy (&data_rw, &data, sizeof(data_rw));
617 res = dtls_write(dtls_context,
618 (session_t *)session->tls, data_rw, data_len);
619
620 if (res < 0)
621 coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n");
622
623 if (coap_event_dtls >= 0) {
624 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
625 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
626 coap_handle_event(session->context, coap_event_dtls, session);
627 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
628 coap_session_connected(session);
629 else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
631 }
632
633 return res;
634}
635
637 return 1;
638}
639
640coap_tick_t coap_dtls_get_context_timeout(void *tiny_context) {
641 clock_time_t next = 0;
642 coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
643 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
644 if (tiny_context)
645 dtls_check_retransmit(dtls_context, &next);
646 if (next > 0)
647 return ((coap_tick_t)(next - dtls_tick_0)) * COAP_TICKS_PER_SECOND / DTLS_TICKS_PER_SECOND + coap_tick_0;
648 return 0;
649}
650
652 (void)session;
653 (void)now;
654 return 0;
655}
656
657/*
658 * return 1 timed out
659 * 0 still timing out
660 */
661int
663 (void)session;
664 return 0;
665}
666
667int
669 const uint8_t *data,
670 size_t data_len
671) {
672 session_t *dtls_session = (session_t *)session->tls;
673 int err;
674 uint8_t *data_rw;
675 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
676 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
677
678 assert(dtls_context);
679 coap_event_dtls = -1;
680 /* Need to do this to not get a compiler warning about const parameters */
681 memcpy (&data_rw, &data, sizeof(data_rw));
682 err = dtls_handle_message(dtls_context, dtls_session, data_rw, (int)data_len);
683
684 if (err){
685 coap_event_dtls = COAP_EVENT_DTLS_ERROR;
686 }
687
688 if (coap_event_dtls >= 0) {
689 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
690 if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED)
691 coap_handle_event(session->context, coap_event_dtls, session);
692 if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED)
693 coap_session_connected(session);
694 else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR)
696 }
697
698 return err;
699}
700
701#if COAP_SERVER_SUPPORT
702int
704 const uint8_t *data,
705 size_t data_len
706) {
707 session_t dtls_session;
708 coap_tiny_context_t *t_context = (coap_tiny_context_t *)session->context->dtls_context;
709 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
710 uint8_t *data_rw;
711
712 assert(dtls_context);
713 dtls_session_init(&dtls_session);
714 put_session_addr(&session->addr_info.remote, &dtls_session);
715 dtls_session.ifindex = session->ifindex;
716 /* Need to do this to not get a compiler warning about const parameters */
717 memcpy (&data_rw, &data, sizeof(data_rw));
718 int res = dtls_handle_message(dtls_context, &dtls_session,
719 data_rw, (int)data_len);
720 if (res >= 0) {
721 if (dtls_get_peer(dtls_context, &dtls_session))
722 res = 1;
723 else
724 res = 0;
725 }
726 return res;
727}
728#endif /* COAP_SERVER_SUPPORT */
729
730unsigned int coap_dtls_get_overhead(coap_session_t *session) {
731 (void)session;
732 return 13 + 8 + 8;
733}
734
735int coap_tls_is_supported(void) {
736 return 0;
737}
738
741 static coap_tls_version_t version;
742 const char *vers = dtls_package_version();
743
744 version.version = 0;
745 if (vers) {
746 long int p1, p2 = 0, p3 = 0;
747 char* endptr;
748
749 p1 = strtol(vers, &endptr, 10);
750 if (*endptr == '.') {
751 p2 = strtol(endptr+1, &endptr, 10);
752 if (*endptr == '.') {
753 p3 = strtol(endptr+1, &endptr, 10);
754 }
755 }
756 version.version = (p1 << 16) | (p2 << 8) | p3;
757 }
758 version.built_version = version.version;
760 return &version;
761}
762
763#ifdef DTLS_ECC
764static const uint8_t b64_6[256] =
765 {
766 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
767 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
768/* + / */
769 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
770/* 0 1 2 3 4 5 6 7 8 9 = */
771 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
772/* A B C D E F G H I J K L M N O */
773 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
774/* P Q R S T U V W X Y Z */
775 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
776/* a b c d e f g h i j k l m n o */
777 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
778/* p q r s t u v w x y z */
779 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
780 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
781 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
782 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
783 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
784 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
785 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
786 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
787 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
788 };
789
790/* caller must free off returned coap_binary_t* */
791static coap_binary_t *
792pem_base64_decode (const uint8_t *data, size_t size)
793{
794 uint8_t *tbuf = coap_malloc(size);
795 size_t nbytesdecoded;
796 size_t i;
797 coap_binary_t *decoded;
798 uint8_t *ptr;
799 uint8_t *out;
800 size_t nb64bytes = 0;
801
802 for (i = 0; i < size; i++) {
803 switch (data[i]) {
804 case ' ':
805 case '\r':
806 case '\n':
807 case '\t':
808 break;
809 default:
810 if (b64_6[data[i]] == 64)
811 goto end;
812 tbuf[nb64bytes++] = data[i];
813 break;
814 }
815 }
816
817end:
818 nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
819 decoded = coap_new_binary(nbytesdecoded + 1);
820 if (!decoded)
821 return NULL;
822
823 out = decoded->s;
824 ptr = tbuf;
825
826 while (nb64bytes > 4) {
827 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
828 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
829 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
830 ptr += 4;
831 nb64bytes -= 4;
832 }
833
834 /* Note: (nb64bytes == 1) is an error */
835 if (nb64bytes > 1) {
836 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
837 }
838 if (nb64bytes > 2) {
839 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
840 }
841 if (nb64bytes > 3) {
842 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
843 }
844
845 decoded->length = nbytesdecoded - ((4 - nb64bytes) & 3);
846 coap_free(tbuf);
847 return decoded;
848}
849
850typedef coap_binary_t * (*asn1_callback)(const uint8_t *data, size_t size);
851
852static int
853asn1_verify_privkey(const uint8_t *data, size_t size)
854{
855 /* Check if we have the private key (with optional leading 0x00) */
856 /* skip leading 0x00 */
857 if (size - 1 == DTLS_EC_KEY_SIZE && *data == '\000') {
858 --size;
859 ++data;
860 }
861
862 /* Check if we have the private key */
863 if (size != DTLS_EC_KEY_SIZE)
864 return 0;
865
866 return 1;
867}
868
869static int
870asn1_verify_pubkey(const uint8_t *data, size_t size)
871{
872 (void)data;
873
874 /* We have the public key
875 (with a leading 0x00 (no unused bits) 0x04 (not compressed() */
876 if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
877 return 0;
878
879 return 1;
880}
881
882static int
883asn1_verify_curve(const uint8_t *data, size_t size)
884{
885 static uint8_t prime256v1_oid[] =
886 /* OID 1.2.840.10045.3.1.7 */
887 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
888
889 /* Check that we have the correct EC (only one supported) */
890 if (size != sizeof(prime256v1_oid) ||
891 memcmp(data, prime256v1_oid, size) != 0)
892 return 0;
893
894 return 1;
895}
896
897static int
898asn1_verify_pkcs8_version(const uint8_t *data, size_t size)
899{
900 /* Check that we have the version */
901 if (size != 1 || *data != 0)
902 return 0;
903
904 return 1;
905}
906
907static int
908asn1_verify_ec_identifier(const uint8_t *data, size_t size)
909{
910 static uint8_t ec_public_key_oid[] =
911 /* OID 1.2.840.10045.2.1 */
912 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
913
914 /* Check that we have the correct ecPublicKey */
915 if (size != sizeof(ec_public_key_oid) ||
916 memcmp(data, ec_public_key_oid, size) != 0)
917 return 0;
918
919 return 1;
920}
921
922static int
923asn1_verify_ec_key(const uint8_t *data, size_t size)
924{
925 (void)data;
926
927 if (size == 0)
928 return 0;
929
930 return 1;
931}
932
933static int
934asn1_derive_keys(coap_tiny_context_t *t_context,
935 const uint8_t *priv_data, size_t priv_len,
936 const uint8_t *pub_data, size_t pub_len,
937 int is_pkcs8)
938{
939 coap_binary_t *test;
940
941 t_context->priv_key = get_asn1_tag(COAP_ASN1_OCTETSTRING, priv_data,
942 priv_len, asn1_verify_privkey);
943 if (!t_context->priv_key) {
944 coap_log(LOG_INFO, "EC Private Key (RPK) invalid\n");
945 return 0;
946 }
947 /* skip leading 0x00 */
948 if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
949 t_context->priv_key->s[0] == '\000') {
950 t_context->priv_key->length--;
951 t_context->priv_key->s++;
952 }
953
954 if (!is_pkcs8) {
955 /* pkcs8 abstraction tested for valid eliptic curve */
956 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, priv_data, priv_len,
957 asn1_verify_curve);
958 if (!test) {
959 coap_log(LOG_INFO, "EC Private Key (RPK) invalid elliptic curve\n");
960 coap_delete_binary(t_context->priv_key);
961 t_context->priv_key = NULL;
962 return 0;
963 }
964 coap_delete_binary(test);
965 }
966
967 t_context->pub_key = get_asn1_tag(COAP_ASN1_BITSTRING, pub_data, pub_len,
968 asn1_verify_pubkey);
969 if (!t_context->pub_key) {
970 coap_log(LOG_INFO, "EC Public Key (RPK) invalid\n");
971 coap_delete_binary(t_context->priv_key);
972 t_context->priv_key = NULL;
973 return 0;
974 }
975 /* Drop leading 0x00 and 0x04 */
976 t_context->pub_key->s += 2;
977 t_context->pub_key->length -= 2;
978 dtls_set_handler(t_context->dtls_context, &ec_cb);
979 return 1;
980}
981
982static coap_binary_t *
983ec_abstract_pkcs8_asn1(const uint8_t *asn1_ptr, size_t asn1_length)
984{
985 coap_binary_t *test;
986
987 test = get_asn1_tag(COAP_ASN1_INTEGER, asn1_ptr, asn1_length,
988 asn1_verify_pkcs8_version);
989 if (!test)
990 return 0;
991
992 coap_delete_binary(test);
993
994 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
995 asn1_verify_ec_identifier);
996 if (!test)
997 return 0;
998 coap_delete_binary(test);
999
1000 test = get_asn1_tag(COAP_ASN1_IDENTIFIER, asn1_ptr, asn1_length,
1001 asn1_verify_curve);
1002 if (!test) {
1003 coap_log(LOG_INFO, "EC Private Key (RPK) invalid elliptic curve\n");
1004 return 0;
1005 }
1006 coap_delete_binary(test);
1007
1008 test = get_asn1_tag(COAP_ASN1_OCTETSTRING, asn1_ptr, asn1_length,
1009 asn1_verify_ec_key);
1010 return test;
1011}
1012
1013static coap_binary_t *
1014pem_decode_mem_asn1(const char *begstr, const uint8_t *str)
1015{
1016 char *bcp = str ? strstr((const char*)str, begstr) : NULL;
1017 char *tcp = bcp ? strstr(bcp, "-----END ") : NULL;
1018
1019 if (bcp && tcp) {
1020 bcp += strlen(begstr);
1021 return pem_base64_decode ((const uint8_t *)bcp, tcp - bcp);
1022 }
1023 return NULL;
1024}
1025
1026#endif /* DTLS_ECC */
1027
1028int
1030 const coap_dtls_pki_t* setup_data,
1031 const coap_dtls_role_t role COAP_UNUSED
1032) {
1033#ifdef DTLS_ECC
1034 coap_tiny_context_t *t_context;
1035 coap_binary_t *asn1_priv;
1036 coap_binary_t *asn1_pub;
1037 coap_binary_t *asn1_temp;
1038 int is_pkcs8 = 0;
1039
1040 if (!setup_data)
1041 return 0;
1042 if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION)
1043 return 0;
1044 if (!setup_data->is_rpk_not_cert) {
1045 coap_log(LOG_WARNING, "Only RPK, not full PKI is supported\n");
1046 return 0;
1047 }
1048 if (!ctx)
1049 return 0;
1050 t_context = (coap_tiny_context_t *)ctx->dtls_context;
1051 if (!t_context)
1052 return 0;
1053 if (t_context->priv_key) {
1054 coap_delete_binary(t_context->priv_key);
1055 t_context->priv_key = NULL;
1056 }
1057 if (t_context->pub_key) {
1058 coap_delete_binary(t_context->pub_key);
1059 t_context->pub_key = NULL;
1060 }
1061 t_context->setup_data = *setup_data;
1062
1063 /* All should be RPK only now */
1064 switch (setup_data->pki_key.key_type) {
1065 case COAP_PKI_KEY_PEM:
1066 coap_log(LOG_WARNING, "RPK keys cannot be in COAP_PKI_KEY_PEM format\n");
1067 break;
1069 if (setup_data->pki_key.key.pem_buf.public_cert &&
1070 setup_data->pki_key.key.pem_buf.public_cert[0] &&
1071 setup_data->pki_key.key.pem_buf.private_key &&
1072 setup_data->pki_key.key.pem_buf.private_key[0]) {
1073 /* Need to take PEM memory information and convert to binary */
1074 asn1_priv = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1075 setup_data->pki_key.key.pem_buf.private_key);
1076 if (!asn1_priv) {
1077 asn1_priv = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1078 setup_data->pki_key.key.pem_buf.private_key);
1079 if (!asn1_priv) {
1080 coap_log(LOG_INFO, "Private Key (RPK) invalid\n");
1081 return 0;
1082 }
1083 asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->s, asn1_priv->length);
1084 if (!asn1_temp) {
1085 coap_log(LOG_INFO, "PKCS#8 Private Key (RPK) invalid\n");
1086 coap_delete_binary(asn1_priv);
1087 return 0;
1088 }
1089 coap_delete_binary(asn1_priv);
1090 asn1_priv = asn1_temp;
1091 is_pkcs8 = 1;
1092 }
1093 asn1_pub = pem_decode_mem_asn1(
1094 "-----BEGIN PUBLIC KEY-----",
1095 setup_data->pki_key.key.pem_buf.public_cert);
1096 if (!asn1_pub) {
1097 asn1_pub = pem_decode_mem_asn1("-----BEGIN EC PRIVATE KEY-----",
1098 setup_data->pki_key.key.pem_buf.private_key);
1099 if (!asn1_pub) {
1100 asn1_pub = pem_decode_mem_asn1("-----BEGIN PRIVATE KEY-----",
1101 setup_data->pki_key.key.pem_buf.private_key);
1102 if (!asn1_pub) {
1103 coap_log(LOG_INFO, "Public Key (RPK) invalid\n");
1104 coap_delete_binary(asn1_priv);
1105 return 0;
1106 }
1107 asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->s, asn1_pub->length);
1108 if (!asn1_temp) {
1109 coap_log(LOG_INFO, "PKCS#8 Private Key (RPK) invalid\n");
1110 coap_delete_binary(asn1_priv);
1111 coap_delete_binary(asn1_pub);
1112 return 0;
1113 }
1114 coap_delete_binary(asn1_pub);
1115 asn1_pub = asn1_temp;
1116 is_pkcs8 = 1;
1117 }
1118 }
1119 if (!asn1_derive_keys(t_context, asn1_priv->s, asn1_priv->length,
1120 asn1_pub->s, asn1_pub->length, is_pkcs8)) {
1121 coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n");
1122 coap_delete_binary(asn1_priv);
1123 coap_delete_binary(asn1_pub);
1124 return 0;
1125 }
1126 coap_delete_binary(asn1_priv);
1127 coap_delete_binary(asn1_pub);
1128 return 1;
1129 }
1130 break;
1131 case COAP_PKI_KEY_ASN1:
1132 if (setup_data->pki_key.key.asn1.private_key &&
1133 setup_data->pki_key.key.asn1.private_key_len &&
1135 const uint8_t* private_key = setup_data->pki_key.key.asn1.private_key;
1136 size_t private_key_len = setup_data->pki_key.key.asn1.private_key_len;
1137
1138 /* Check to see whether this is in pkcs8 format or not */
1139 asn1_temp = ec_abstract_pkcs8_asn1(
1140 setup_data->pki_key.key.asn1.private_key,
1141 setup_data->pki_key.key.asn1.private_key_len);
1142 if (asn1_temp) {
1143 private_key = asn1_temp->s;
1144 private_key_len = asn1_temp->length;
1145 is_pkcs8 = 1;
1146 }
1147 /* Need to take ASN1 memory information and convert to binary */
1148 if (setup_data->pki_key.key.asn1.public_cert &&
1149 setup_data->pki_key.key.asn1.public_cert_len) {
1150 if (!asn1_derive_keys(t_context,
1151 private_key,
1152 private_key_len,
1153 setup_data->pki_key.key.asn1.public_cert,
1154 setup_data->pki_key.key.asn1.public_cert_len,
1155 is_pkcs8)) {
1156 coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n");
1157 if (asn1_temp) coap_delete_binary(asn1_temp);
1158 return 0;
1159 }
1160 }
1161 else {
1162 if (!asn1_derive_keys(t_context,
1163 private_key,
1164 private_key_len,
1165 private_key,
1166 private_key_len,
1167 is_pkcs8)) {
1168 coap_log(LOG_INFO, "Unable to derive Public/Private Keys\n");
1169 if (asn1_temp) coap_delete_binary(asn1_temp);
1170 return 0;
1171 }
1172 }
1173 return 1;
1174 }
1175 break;
1177 coap_log(LOG_WARNING, "RPK keys cannot be in COAP_PKI_KEY_PCKS11 format\n");
1178 break;
1179 default:
1180 break;
1181 }
1182#else /* ! DTLS_ECC */
1183 (void)ctx;
1184 (void)setup_data;
1185#endif /* ! DTLS_ECC */
1186 return 0;
1187}
1188
1189int
1191 const char *ca_file COAP_UNUSED,
1192 const char *ca_path COAP_UNUSED
1193) {
1194 coap_log(LOG_WARNING, "Root CAs PKI not supported\n");
1195 return 0;
1196}
1197
1198#if COAP_CLIENT_SUPPORT
1199int
1201 coap_dtls_cpsk_t *setup_data
1202) {
1203 if (!setup_data)
1204 return 0;
1205
1206 return 1;
1207}
1208#endif /* COAP_CLIENT_SUPPORT */
1209
1210#if COAP_SERVER_SUPPORT
1211int
1213 coap_dtls_spsk_t *setup_data
1214) {
1215 if (!setup_data)
1216 return 0;
1217
1218 if (setup_data->validate_sni_call_back) {
1220 "CoAP Server with TinyDTLS does not support SNI selection\n");
1221 }
1222
1223 return 1;
1224}
1225#endif /* COAP_SERVER_SUPPORT */
1226
1227int
1229{
1230 return 1;
1231}
1232
1233#if !COAP_DISABLE_TCP
1234#if COAP_CLIENT_SUPPORT
1235void *coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) {
1236 return NULL;
1237}
1238#endif /* COAP_CLIENT_SUPPORT */
1239
1240#if COAP_SERVER_SUPPORT
1241void *coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED) {
1242 return NULL;
1243}
1244#endif /* COAP_SERVER_SUPPORT */
1245
1247}
1248
1250 const uint8_t *data COAP_UNUSED,
1251 size_t data_len COAP_UNUSED
1252) {
1253 return -1;
1254}
1255
1257 uint8_t *data COAP_UNUSED,
1258 size_t data_len COAP_UNUSED
1259) {
1260 return -1;
1261}
1262#endif /* !COAP_DISABLE_TCP */
1263
1264#if COAP_SERVER_SUPPORT
1266coap_digest_setup(void) {
1267 dtls_sha256_ctx *digest_ctx = coap_malloc(sizeof(dtls_sha256_ctx));
1268
1269 if (digest_ctx) {
1270 dtls_sha256_init(digest_ctx);
1271 }
1272
1273 return digest_ctx;
1274}
1275
1276void
1278 coap_free(digest_ctx);
1279}
1280
1281int
1283 const uint8_t *data,
1284 size_t data_len) {
1285 dtls_sha256_update(digest_ctx, data, data_len);
1286
1287 return 1;
1288}
1289
1290int
1292 coap_digest_t *digest_buffer) {
1293 dtls_sha256_final((uint8_t*)digest_buffer, digest_ctx);
1294
1295 coap_digest_free(digest_ctx);
1296 return 1;
1297}
1298#endif /* COAP_SERVER_SUPPORT */
1299
1300#else /* !HAVE_LIBTINYDTLS */
1301
1302#ifdef __clang__
1303/* Make compilers happy that do not like empty modules. As this function is
1304 * never used, we ignore -Wunused-function at the end of compiling this file
1305 */
1306#pragma GCC diagnostic ignored "-Wunused-function"
1307#endif
1308static inline void dummy(void) {
1309}
1310
1311#endif /* HAVE_LIBTINYDTLS */
Pulls together all the internal only header files.
@ COAP_NACK_TLS_FAILED
Definition: coap_io.h:73
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:41
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition: coap_notls.c:150
int 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:134
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:207
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition: coap_notls.c:145
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:164
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition: coap_notls.c:86
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:181
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition: coap_notls.c:75
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:200
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:130
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:49
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:159
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition: coap_notls.c:112
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:127
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition: coap_notls.c:107
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:197
coap_session_t * coap_session_get_by_peer(const coap_context_t *ctx, const coap_address_t *remote_addr, int ifindex)
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:68
@ 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.
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:127
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition: coap_time.h:142
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: net.c:2040
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: net.c:3352
const coap_bin_const_t * coap_get_session_client_psk_identity(const coap_session_t *session)
Get the current client's PSK identity.
Definition: net.c:318
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition: coap_notls.c:82
void * coap_dtls_new_client_session(coap_session_t *coap_session)
Create a new client-side session.
void * coap_tls_new_client_session(coap_session_t *coap_session, int *connected)
Create a new TLS client-side session.
void * coap_tls_new_server_session(coap_session_t *coap_session, int *connected)
Create a TLS new server-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:141
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:93
const coap_bin_const_t * coap_get_session_client_psk_key(const coap_session_t *coap_session)
Get the current client's PSK key.
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:33
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:251
#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
coap_tls_library_t
Definition: coap_dtls.h:64
@ COAP_PKI_KEY_PKCS11
The PKI key type is PKCS11 (DER)
Definition: coap_dtls.h:164
@ COAP_PKI_KEY_PEM_BUF
The PKI key type is PEM buffer.
Definition: coap_dtls.h:163
@ COAP_PKI_KEY_PEM
The PKI key type is PEM file.
Definition: coap_dtls.h:161
@ COAP_PKI_KEY_ASN1
The PKI key type is ASN.1 (DER) buffer.
Definition: coap_dtls.h:162
@ COAP_ASN1_PKEY_EC
EC type.
Definition: coap_dtls.h:150
@ COAP_TLS_LIBRARY_TINYDTLS
Using TinyDTLS library.
Definition: coap_dtls.h:66
@ 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
void coap_dtls_set_log_level(int level)
Sets the (D)TLS logging level to the specified level.
Definition: coap_notls.c:97
#define LOG_DEBUG
Definition: coap_debug.h:81
int coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition: coap_notls.c:102
#define LOG_WARNING
Definition: coap_debug.h:72
#define LOG_INFO
Definition: coap_debug.h:78
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:165
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).
ssize_t coap_session_send(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for datagram data transmission.
Definition: coap_session.c:401
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:534
int coap_session_refresh_psk_identity(coap_session_t *session, const coap_bin_const_t *psk_identity)
Refresh the session's current pre-shared identity (PSK).
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:593
@ COAP_SESSION_TYPE_CLIENT
client-side
Definition: coap_session.h:44
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition: str.c:72
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition: str.c:96
#define COAP_UNUSED
Definition: libcoap.h:60
COAP_STATIC_INLINE void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:110
COAP_STATIC_INLINE void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
Definition: mem.h:103
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().
coap_address_t remote
remote address and port
Definition: coap_io.h:56
multi-purpose address abstraction
Definition: coap_address.h:96
socklen_t size
size of addr
Definition: coap_address.h:97
struct sockaddr_in sin
Definition: coap_address.h:100
struct sockaddr_in6 sin6
Definition: coap_address.h:101
struct sockaddr sa
Definition: coap_address.h:99
union coap_address_t::@0 addr
CoAP binary data definition with const data.
Definition: str.h:64
size_t length
length of binary data
Definition: str.h:65
const uint8_t * s
read-only binary data
Definition: str.h:66
CoAP binary data definition.
Definition: str.h:56
size_t length
length of binary data
Definition: str.h:57
uint8_t * s
binary data
Definition: 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 Client PSK information.
Definition: coap_dtls.h:319
coap_bin_const_t key
Definition: coap_dtls.h:321
coap_bin_const_t identity
Definition: coap_dtls.h:320
The structure used for defining the Client PSK setup data to be used.
Definition: coap_dtls.h:350
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition: coap_dtls.h:371
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition: coap_dtls.h:370
union coap_dtls_key_t::@2 key
coap_pki_key_pem_buf_t pem_buf
for PEM memory keys
Definition: coap_dtls.h:228
coap_pki_key_t key_type
key format type
Definition: coap_dtls.h:225
coap_pki_key_asn1_t asn1
for ASN.1 (DER) memory keys
Definition: coap_dtls.h:229
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:256
uint8_t version
Definition: coap_dtls.h:257
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition: coap_dtls.h:274
coap_dtls_key_t pki_key
PKI key definition.
Definition: coap_dtls.h:313
The structure used for defining the Server PSK setup data to be used.
Definition: coap_dtls.h:437
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition: coap_dtls.h:464
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition: coap_dtls.h:456
void * id_call_back_arg
Passed in to the Identity callback function.
Definition: coap_dtls.h:457
const uint8_t * private_key
ASN1 (DER) Private Key.
Definition: coap_dtls.h:202
coap_asn1_privatekey_type_t private_key_type
Private Key Type.
Definition: coap_dtls.h:206
size_t public_cert_len
ASN1 Public Cert length.
Definition: coap_dtls.h:204
size_t private_key_len
ASN1 Private Key length.
Definition: coap_dtls.h:205
const uint8_t * public_cert
ASN1 (DER) Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:201
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:188
const uint8_t * public_cert
PEM buffer Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:187
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_addr_tuple_t addr_info
key: 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 string data definition with const data.
Definition: str.h:46
const uint8_t * s
read-only string data
Definition: str.h:48
size_t length
length of string
Definition: str.h:47
The structure used for returning the underlying (D)TLS library information.
Definition: coap_dtls.h:76
uint64_t built_version
(D)TLS Built against Library Version
Definition: coap_dtls.h:79
coap_tls_library_t type
Library type.
Definition: coap_dtls.h:78
uint64_t version
(D)TLS runtime Library Version
Definition: coap_dtls.h:77