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