libcoap 4.3.5-develop-f52fada
Loading...
Searching...
No Matches
coap_openhitls.c
Go to the documentation of this file.
1/*
2 * coap_openhitls.c -- openHiTLS Datagram Transport Layer Support for libcoap
3 *
4 * Copyright (C) 2026 openHiTLS Project.
5 *
6 * SPDX-License-Identifier: BSD-2-Clause
7 *
8 * This file is part of the CoAP library libcoap. Please see README for terms
9 * of use.
10 */
11
16
18
19#if COAP_WITH_LIBOPENHITLS || COAP_WITH_LIBOPENHITLS_OSCORE
20
21#include <errno.h>
22#include <limits.h>
23#include <stdbool.h>
24#include <stdint.h>
25#include <stdio.h>
26#include <string.h>
27
28#ifdef COAP_EPOLL_SUPPORT
29#include <sys/epoll.h>
30#endif /* COAP_EPOLL_SUPPORT */
31
32#include <hitls/bsl/bsl_err.h>
33#include <hitls/bsl/bsl_errno.h>
34#include <hitls/bsl/bsl_sal.h>
35#include <hitls/bsl/bsl_uio.h>
36#include <hitls/bsl/bsl_version.h>
37#include <hitls/crypto/crypt_eal_cipher.h>
38#include <hitls/crypto/crypt_eal_init.h>
39#include <hitls/crypto/crypt_eal_mac.h>
40#include <hitls/crypto/crypt_eal_md.h>
41#include <hitls/crypto/crypt_eal_pkey.h>
42#include <hitls/crypto/crypt_errno.h>
43#if COAP_WITH_LIBOPENHITLS
44#if defined(__GNUC__)
45#pragma GCC diagnostic push
46#pragma GCC diagnostic ignored "-Wpedantic"
47#endif /* defined(__GNUC__) */
48#include <hitls/bsl/bsl_list.h>
49#include <hitls/pki/hitls_pki_cert.h>
50#include <hitls/pki/hitls_pki_errno.h>
51#include <hitls/pki/hitls_pki_types.h>
52#include <hitls/pki/hitls_pki_utils.h>
53#include <hitls/pki/hitls_pki_x509.h>
54#if defined(__GNUC__)
55#pragma GCC diagnostic pop
56#endif /* defined(__GNUC__) */
57#include <hitls/tls/hitls.h>
58#include <hitls/tls/hitls_alpn.h>
59#include <hitls/tls/hitls_cert.h>
60#include <hitls/tls/hitls_cert_init.h>
61#include <hitls/tls/hitls_config.h>
62#include <hitls/tls/hitls_cookie.h>
63#include <hitls/tls/hitls_crypt_init.h>
64#include <hitls/tls/hitls_debug.h>
65#include <hitls/tls/hitls_error.h>
66#include <hitls/tls/hitls_psk.h>
67#include <hitls/tls/hitls_sni.h>
68#endif /* COAP_WITH_LIBOPENHITLS */
69
70#if COAP_WITH_LIBOPENHITLS
71#define IS_PSK 0x01
72#define IS_PKI 0x02
73#define COAP_HITLS_DTLS_OVERHEAD 37
74#define COAP_HITLS_IPV4_UDP_OVERHEAD 28
75#define COAP_HITLS_IPV6_UDP_OVERHEAD 48
76#define COAP_HITLS_COOKIE_SECRET_LEN 32
77#define COAP_HITLS_COOKIE_LEN 32
78/* +1 converts libcoap verify_depth to the intermediate-CA limit.
79 * +2 adds the leaf certificate and trust anchor for openHiTLS maxDepth.
80 */
81#define COAP_HITLS_VERIFY_DEPTH_TO_MAX_CHAIN_DEPTH(depth) \
82 ((depth) + 1 + 2)
83
84typedef struct coap_hitls_context_t {
85 coap_context_t *coap_context;
86 coap_dtls_pki_t setup_data;
87 char *root_ca_file;
88 char *root_ca_dir;
89 int psk_pki_enabled;
90 int trust_store_defined;
91 int cookie_secret_set;
92 uint8_t cookie_secret[COAP_HITLS_COOKIE_SECRET_LEN];
93} coap_hitls_context_t;
94
95typedef struct coap_hitls_env_t {
96 HITLS_Ctx *ctx;
97 BSL_UIO *uio;
98 BSL_UIO_Method *method;
99 const uint8_t *pdu;
100 size_t pdu_len;
101 coap_session_t *session;
102 int established;
103 coap_dtls_role_t role;
104 coap_proto_t proto;
105 int hello_verify_sent;
106 int mtu_exceeded;
107 int had_fatal;
108 coap_tick_t last_timeout;
109} coap_hitls_env_t;
110
112#endif /* COAP_WITH_LIBOPENHITLS */
113static int coap_hitls_started = 0;
114#if COAP_WITH_LIBOPENHITLS
115static const uint8_t coap_hitls_alpn[] = { 4, 'c', 'o', 'a', 'p' };
116static const uint16_t coap_hitls_psk_cipher_suites[] = {
117 HITLS_PSK_WITH_AES_128_GCM_SHA256,
118 HITLS_PSK_WITH_AES_256_GCM_SHA384,
119 HITLS_PSK_WITH_AES_256_CCM,
120 HITLS_PSK_WITH_CHACHA20_POLY1305_SHA256
121};
122static const uint16_t coap_hitls_pki_cipher_suites[] = {
123 HITLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
124 HITLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
125 HITLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
126 HITLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
127 HITLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
128 HITLS_DHE_RSA_WITH_AES_256_GCM_SHA384
129};
130static const uint16_t coap_hitls_psk_pki_cipher_suites[] = {
131 HITLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
132 HITLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
133 HITLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
134 HITLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
135 HITLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
136 HITLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
137 HITLS_PSK_WITH_AES_128_GCM_SHA256,
138 HITLS_PSK_WITH_AES_256_GCM_SHA384,
139 HITLS_PSK_WITH_AES_256_CCM,
140 HITLS_PSK_WITH_CHACHA20_POLY1305_SHA256
141};
142
143static void
144coap_hitls_get_cipher_suites(int enabled, const uint16_t **cipher_suites,
145 uint32_t *cipher_suites_count) {
146 if ((enabled & IS_PSK) && (enabled & IS_PKI)) {
147 *cipher_suites = coap_hitls_psk_pki_cipher_suites;
148 *cipher_suites_count =
149 (uint32_t)(sizeof(coap_hitls_psk_pki_cipher_suites) /
150 sizeof(coap_hitls_psk_pki_cipher_suites[0]));
151 } else if (enabled & IS_PKI) {
152 *cipher_suites = coap_hitls_pki_cipher_suites;
153 *cipher_suites_count =
154 (uint32_t)(sizeof(coap_hitls_pki_cipher_suites) /
155 sizeof(coap_hitls_pki_cipher_suites[0]));
156 } else {
157 *cipher_suites = coap_hitls_psk_cipher_suites;
158 *cipher_suites_count =
159 (uint32_t)(sizeof(coap_hitls_psk_cipher_suites) /
160 sizeof(coap_hitls_psk_cipher_suites[0]));
161 }
162}
163
164static void
165coap_hitls_mark_fatal(coap_session_t *session) {
166 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
167
168 if (env)
169 env->had_fatal = 1;
170}
171
172static void
173coap_hitls_log_err_stack(const coap_session_t *session) {
174 int32_t e;
175
176 while ((e = BSL_ERR_GetError()) != BSL_SUCCESS)
177 coap_dtls_log(COAP_LOG_WARN, "* %s: openHiTLS error 0x%08x\n",
178 coap_session_str(session), (unsigned int)e);
179}
180
181static void
182coap_hitls_log_fatal_err_stack(coap_session_t *session) {
183 coap_hitls_mark_fatal(session);
184 coap_hitls_log_err_stack(session);
185}
186
187/* TLS alert levels and descriptions as defined by RFC 5246 / RFC 8446. */
188enum {
189 ALERT_LEVEL_WARNING = 1,
190 ALERT_LEVEL_FATAL = 2,
191 ALERT_CLOSE_NOTIFY = 0,
192 ALERT_UNEXPECTED_MESSAGE = 10,
193 ALERT_BAD_RECORD_MAC = 20,
194 ALERT_RECORD_OVERFLOW = 22,
195 ALERT_HANDSHAKE_FAILURE = 40,
196 ALERT_BAD_CERTIFICATE = 42,
197 ALERT_UNSUPPORTED_CERTIFICATE = 43,
198 ALERT_CERTIFICATE_REVOKED = 44,
199 ALERT_CERTIFICATE_EXPIRED = 45,
200 ALERT_ILLEGAL_PARAMETER = 47,
201 ALERT_UNKNOWN_CA = 48,
202 ALERT_DECODE_ERROR = 50,
203 ALERT_DECRYPT_ERROR = 51,
204 ALERT_PROTOCOL_VERSION = 70,
205 ALERT_INSUFFICIENT_SECURITY = 71,
206 ALERT_INTERNAL_ERROR = 80,
207 ALERT_INAPPROPRIATE_FALLBACK = 86,
208 ALERT_NO_RENEGOTIATION = 100,
209 ALERT_MISSING_EXTENSION = 109,
210 ALERT_UNSUPPORTED_EXTENSION = 110,
211 ALERT_UNRECOGNIZED_NAME = 112,
212 ALERT_CERTIFICATE_REQUIRED = 116,
213 ALERT_NO_APPLICATION_PROTOCOL = 120
214};
215
216static const char *
217coap_hitls_alert_desc(int desc) {
218 switch (desc) {
219 case ALERT_CLOSE_NOTIFY:
220 return "close_notify";
221 case ALERT_UNEXPECTED_MESSAGE:
222 return "unexpected_message";
223 case ALERT_BAD_RECORD_MAC:
224 return "bad_record_mac";
225 case ALERT_RECORD_OVERFLOW:
226 return "record_overflow";
227 case ALERT_HANDSHAKE_FAILURE:
228 return "handshake_failure";
229 case ALERT_BAD_CERTIFICATE:
230 return "bad_certificate";
231 case ALERT_UNSUPPORTED_CERTIFICATE:
232 return "unsupported_certificate";
233 case ALERT_CERTIFICATE_REVOKED:
234 return "certificate_revoked";
235 case ALERT_CERTIFICATE_EXPIRED:
236 return "certificate_expired";
237 case ALERT_ILLEGAL_PARAMETER:
238 return "illegal_parameter";
239 case ALERT_UNKNOWN_CA:
240 return "unknown_ca";
241 case ALERT_DECODE_ERROR:
242 return "decode_error";
243 case ALERT_DECRYPT_ERROR:
244 return "decrypt_error";
245 case ALERT_PROTOCOL_VERSION:
246 return "protocol_version";
247 case ALERT_INSUFFICIENT_SECURITY:
248 return "insufficient_security";
249 case ALERT_INTERNAL_ERROR:
250 return "internal_error";
251 case ALERT_INAPPROPRIATE_FALLBACK:
252 return "inappropriate_fallback";
253 case ALERT_NO_RENEGOTIATION:
254 return "no_renegotiation";
255 case ALERT_MISSING_EXTENSION:
256 return "missing_extension";
257 case ALERT_UNSUPPORTED_EXTENSION:
258 return "unsupported_extension";
259 case ALERT_UNRECOGNIZED_NAME:
260 return "unrecognized_name";
261 case ALERT_CERTIFICATE_REQUIRED:
262 return "certificate_required";
263 case ALERT_NO_APPLICATION_PROTOCOL:
264 return "no_application_protocol";
265 default:
266 return "unknown";
267 }
268}
269
270/* The info callback packs the alert as (level << 8) | description. */
271static void
272coap_hitls_info_cb(const HITLS_Ctx *ctx, int32_t event_type, int32_t value) {
273 coap_session_t *session = (coap_session_t *)HITLS_GetUserData(ctx);
274 int alert_level = (value >> 8) & 0xff;
275 int alert_desc = value & 0xff;
276 const char *dir;
277
278 if ((event_type & INDICATE_EVENT_ALERT) == 0 || !session)
279 return;
280 dir = (event_type & INDICATE_EVENT_READ) ? "received" : "sent";
281 if (alert_level == ALERT_LEVEL_FATAL && alert_desc != ALERT_CLOSE_NOTIFY)
282 coap_log_warn("* %s: openHiTLS %s fatal alert: %s (%d)\n",
283 coap_session_str(session), dir,
284 coap_hitls_alert_desc(alert_desc), alert_desc);
285 else
286 coap_log_info("* %s: openHiTLS %s alert: %s (%d)\n",
287 coap_session_str(session), dir,
288 coap_hitls_alert_desc(alert_desc), alert_desc);
289}
290
291static const char *
292coap_hitls_verify_err_str(int32_t err) {
293 switch (err) {
294 case HITLS_X509_ERR_TIME_EXPIRED:
295 case HITLS_X509_ERR_VFY_NOTAFTER_EXPIRED:
296 return "certificate expired";
297 case HITLS_X509_ERR_TIME_FUTURE:
298 case HITLS_X509_ERR_VFY_NOTBEFORE_IN_FUTURE:
299 return "certificate not yet valid";
300 case HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND:
301 return "issuer certificate not found";
302 case HITLS_X509_ERR_ROOT_CERT_NOT_FOUND:
303 return "self-signed or root CA not found";
304 case HITLS_X509_ERR_VFY_CRL_NOT_FOUND:
305 return "CRL not found";
306 case HITLS_X509_ERR_VFY_THISUPDATE_IN_FUTURE:
307 case HITLS_X509_ERR_VFY_NEXTUPDATE_EXPIRED:
308 return "CRL expired or not yet valid";
309 case HITLS_X509_ERR_VFY_CHECK_SECBITS:
310 return "certificate security strength too low";
311 case HITLS_X509_ERR_VFY_HOSTNAME_FAIL:
312 return "hostname mismatch";
313 case HITLS_X509_ERR_VFY_GET_NOTBEFORE_FAIL:
314 return "cannot read certificate validity start";
315 case HITLS_X509_ERR_VFY_GET_NOTAFTER_FAIL:
316 return "cannot read certificate validity end";
317 case BSL_SAL_TIME_SYS_ERROR:
318 return "system time unavailable";
319 default:
320 return "certificate verification failed";
321 }
322}
323#endif /* COAP_WITH_LIBOPENHITLS */
324
325static int
326coap_hitls_startup(void) {
327 if (!coap_hitls_started) {
328 int32_t ret = CRYPT_EAL_Init(CRYPT_EAL_INIT_ALL);
329
330 if (ret != CRYPT_SUCCESS) {
331 coap_log_err("CRYPT_EAL_Init() returned 0x%x\n", (unsigned int)ret);
332 return 0;
333 }
334#if COAP_WITH_LIBOPENHITLS
335 ret = HITLS_CertMethodInit();
336 if (ret != HITLS_SUCCESS) {
337 coap_log_err("HITLS_CertMethodInit() returned 0x%x\n",
338 (unsigned int)ret);
339 CRYPT_EAL_Cleanup(CRYPT_EAL_INIT_ALL);
340 return 0;
341 }
342 HITLS_CryptMethodInit();
343#endif /* COAP_WITH_LIBOPENHITLS */
344 coap_hitls_started = 1;
345 }
346 return coap_hitls_started;
347}
348
349#if COAP_WITH_LIBOPENHITLS
350static char *
351coap_hitls_strdup(const char *s) {
352 size_t len;
353 char *copy;
354
355 if (!s)
356 return NULL;
357 len = strlen(s);
358 copy = (char *)coap_malloc_type(COAP_STRING, len + 1);
359 if (!copy)
360 return NULL;
361 memcpy(copy, s, len + 1);
362 return copy;
363}
364
365static uint8_t *
366coap_hitls_read_file(const char *file, uint32_t *buf_len) {
367 FILE *fp;
368 long file_len;
369 uint8_t *buf = NULL;
370 size_t read_len;
371
372 if (!file || !buf_len)
373 return NULL;
374
375 fp = fopen(file, "rb");
376 if (!fp)
377 return NULL;
378
379 if (fseek(fp, 0, SEEK_END) != 0)
380 goto fail;
381 file_len = ftell(fp);
382 if (file_len <= 0 || (uintmax_t)file_len > UINT32_MAX)
383 goto fail;
384 if (fseek(fp, 0, SEEK_SET) != 0)
385 goto fail;
386
387 buf = (uint8_t *)coap_malloc_type(COAP_STRING, (size_t)file_len);
388 if (!buf)
389 goto fail;
390 read_len = fread(buf, 1, (size_t)file_len, fp);
391 if (read_len != (size_t)file_len) {
393 buf = NULL;
394 goto fail;
395 }
396 fclose(fp);
397 *buf_len = (uint32_t)read_len;
398 return buf;
399
400fail:
401 fclose(fp);
402 return NULL;
403}
404
405static size_t
406coap_hitls_strnlen(const uint8_t *s, size_t max_len) {
407 size_t len = 0;
408
409 if (!s)
410 return 0;
411 while (len < max_len && s[len])
412 len++;
413 return len;
414}
415
416static uint32_t
417coap_hitls_copy_bin(uint8_t *dst, uint32_t dst_len,
418 const coap_bin_const_t *src, int add_nul) {
419 size_t extra = add_nul ? 1 : 0;
420
421 if (!dst || !src || !src->s ||
422 extra > (size_t)dst_len || src->length > (size_t)dst_len - extra)
423 return 0;
424 memcpy(dst, src->s, src->length);
425 if (add_nul)
426 dst[src->length] = '\000';
427 return (uint32_t)src->length;
428}
429
430#if COAP_SERVER_SUPPORT
431static int
432coap_hitls_cookie_mac(coap_session_t *session, uint8_t *cookie,
433 uint32_t *cookie_len) {
434 static const uint8_t cookie_label[] = "libcoap openhitls dtls cookie";
435 coap_hitls_context_t *context;
436 CRYPT_EAL_MacCtx *ctx = NULL;
437 uint32_t out_len;
438 int ret = 0;
439
440 if (!session || !session->context || !cookie || !cookie_len ||
441 *cookie_len < COAP_HITLS_COOKIE_LEN ||
442 session->addr_info.local.size == 0 ||
443 session->addr_info.remote.size == 0)
444 return 0;
445
446 context = (coap_hitls_context_t *)session->context->dtls_context;
447 if (!context || !context->cookie_secret_set)
448 return 0;
449
450 ctx = CRYPT_EAL_MacNewCtx(CRYPT_MAC_HMAC_SHA256);
451 if (!ctx)
452 return 0;
453
454 out_len = *cookie_len;
455 if (CRYPT_EAL_MacInit(ctx, context->cookie_secret,
456 COAP_HITLS_COOKIE_SECRET_LEN) != CRYPT_SUCCESS)
457 goto finish;
458 if (CRYPT_EAL_MacUpdate(ctx, cookie_label,
459 (uint32_t)sizeof(cookie_label) - 1) != CRYPT_SUCCESS)
460 goto finish;
461 if (CRYPT_EAL_MacUpdate(ctx,
462 (const uint8_t *)&session->addr_info.local.addr,
463 (uint32_t)session->addr_info.local.size) != CRYPT_SUCCESS)
464 goto finish;
465 if (CRYPT_EAL_MacUpdate(ctx,
466 (const uint8_t *)&session->addr_info.remote.addr,
467 (uint32_t)session->addr_info.remote.size) != CRYPT_SUCCESS)
468 goto finish;
469 if (CRYPT_EAL_MacFinal(ctx, cookie, &out_len) != CRYPT_SUCCESS ||
470 out_len != COAP_HITLS_COOKIE_LEN)
471 goto finish;
472
473 *cookie_len = out_len;
474 ret = 1;
475
476finish:
477 CRYPT_EAL_MacFreeCtx(ctx);
478 return ret;
479}
480
481static int
482coap_hitls_cookie_equal(const uint8_t *a, const uint8_t *b, uint32_t len) {
483 uint8_t diff = 0;
484 uint32_t i;
485
486 for (i = 0; i < len; i++)
487 diff |= (uint8_t)(a[i] ^ b[i]);
488 return diff == 0;
489}
490
491static int32_t
492coap_hitls_cookie_gen_cb(HITLS_Ctx *ctx, uint8_t *cookie,
493 uint32_t *cookie_len) {
494 coap_session_t *session = (coap_session_t *)HITLS_GetUserData(ctx);
495
496 return coap_hitls_cookie_mac(session, cookie, cookie_len) ?
497 HITLS_COOKIE_GENERATE_SUCCESS : HITLS_COOKIE_GENERATE_ERROR;
498}
499
500static int32_t
501coap_hitls_cookie_verify_cb(HITLS_Ctx *ctx, const uint8_t *cookie,
502 uint32_t cookie_len) {
503 uint8_t expected[COAP_HITLS_COOKIE_LEN];
504 uint32_t expected_len = sizeof(expected);
505 coap_session_t *session = (coap_session_t *)HITLS_GetUserData(ctx);
506
507 if (!cookie || cookie_len != COAP_HITLS_COOKIE_LEN ||
508 !coap_hitls_cookie_mac(session, expected, &expected_len) ||
509 expected_len != cookie_len ||
510 !coap_hitls_cookie_equal(cookie, expected, cookie_len))
511 return HITLS_COOKIE_VERIFY_ERROR;
512 return HITLS_COOKIE_VERIFY_SUCCESS;
513}
514
515static uint32_t
516coap_hitls_u24(const uint8_t *p) {
517 return ((uint32_t)p[0] << 16) | ((uint32_t)p[1] << 8) | p[2];
518}
519
520static int
521coap_hitls_client_hello_cookie_valid(coap_session_t *session,
522 const uint8_t *data, size_t data_len) {
523 uint8_t expected[COAP_HITLS_COOKIE_LEN];
524 uint32_t expected_len = sizeof(expected);
525 size_t body_offset = 13 + 12;
526 size_t body_end;
527 size_t offset;
528 uint32_t record_len;
529 uint32_t hs_len;
530 uint32_t frag_offset;
531 uint32_t frag_len;
532 uint8_t session_id_len;
533 uint8_t cookie_len;
534
535 if (!data || data_len < body_offset || data[0] != 22 || data[13] != 1)
536 return -1;
537
538 record_len = ((uint32_t)data[11] << 8) | data[12];
539 hs_len = coap_hitls_u24(&data[14]);
540 frag_offset = coap_hitls_u24(&data[19]);
541 frag_len = coap_hitls_u24(&data[22]);
542 if (record_len > data_len - 13 || hs_len > record_len - 12 ||
543 frag_offset != 0 || frag_len != hs_len)
544 return -1;
545
546 body_end = body_offset + hs_len;
547 if (body_end > data_len || body_end < body_offset + 35)
548 return -1;
549
550 offset = body_offset + 34;
551 session_id_len = data[offset++];
552 if (offset + session_id_len + 1 > body_end)
553 return -1;
554 offset += session_id_len;
555
556 cookie_len = data[offset++];
557 if (cookie_len == 0)
558 return 0;
559 if (offset + cookie_len > body_end ||
560 cookie_len != COAP_HITLS_COOKIE_LEN ||
561 !coap_hitls_cookie_mac(session, expected, &expected_len) ||
562 expected_len != cookie_len)
563 return -1;
564
565 return coap_hitls_cookie_equal(&data[offset], expected, cookie_len) ? 1 : -1;
566}
567#endif /* COAP_SERVER_SUPPORT */
568
569static int
570coap_hitls_pki_len(const uint8_t *buf, size_t len, HITLS_ParseFormat format,
571 uint32_t *out_len) {
572 if (!buf)
573 return 0;
574 if (format == TLS_PARSE_FORMAT_PEM && len && buf[len - 1] == '\000')
575 len--;
576 if (len > UINT32_MAX)
577 return 0;
578 *out_len = (uint32_t)len;
579 return 1;
580}
581
582static int
583coap_hitls_key_define_supported(coap_pki_define_t define) {
584 switch (define) {
589 return 1;
594 default:
595 return 0;
596 }
597}
598
599static int
600coap_hitls_check_define_key(coap_dtls_key_t *key, coap_define_issue_key_t type,
601 coap_pki_define_t define,
602 const coap_dtls_role_t role) {
603 if (coap_hitls_key_define_supported(define))
604 return 1;
606 role, 0);
607}
608
609static int
610coap_hitls_check_pki_key_supported(const coap_dtls_pki_t *setup_data,
611 const coap_dtls_role_t role) {
612 coap_dtls_key_t key;
613
614 if (setup_data->is_rpk_not_cert) {
615 coap_log_warn("openHiTLS backend has no RPK support\n");
616 return 0;
617 }
618 if (setup_data->pki_key.key_type == COAP_PKI_KEY_PKCS11) {
619 coap_log_warn("openHiTLS backend has no PKCS11 support\n");
620 return 0;
621 }
622
623 coap_dtls_map_key_type_to_define(setup_data, &key);
624 if (key.key_type != COAP_PKI_KEY_DEFINE)
625 return 0;
626
627 return coap_hitls_check_define_key(&key, COAP_DEFINE_KEY_CA,
628 key.key.define.ca_def, role) &&
629 coap_hitls_check_define_key(&key, COAP_DEFINE_KEY_PUBLIC,
630 key.key.define.public_cert_def, role) &&
631 coap_hitls_check_define_key(&key, COAP_DEFINE_KEY_PRIVATE,
632 key.key.define.private_key_def, role);
633}
634
635static int
636coap_hitls_verify_error_allowed(const coap_dtls_pki_t *setup_data,
637 int32_t err_code) {
638 if (err_code == HITLS_PKI_SUCCESS)
639 return 1;
640 if (!setup_data || !setup_data->verify_peer_cert)
641 return 1;
642
643 switch (err_code) {
644 case HITLS_X509_ERR_TIME_EXPIRED:
645 case HITLS_X509_ERR_TIME_FUTURE:
646 case HITLS_X509_ERR_VFY_NOTBEFORE_IN_FUTURE:
647 case HITLS_X509_ERR_VFY_NOTAFTER_EXPIRED:
648 return setup_data->allow_expired_certs;
649 case HITLS_X509_ERR_VFY_CRL_NOT_FOUND:
650 return !setup_data->check_cert_revocation || setup_data->allow_no_crl;
651 case HITLS_X509_ERR_VFY_THISUPDATE_IN_FUTURE:
652 case HITLS_X509_ERR_VFY_NEXTUPDATE_EXPIRED:
653 return !setup_data->check_cert_revocation ||
654 setup_data->allow_expired_crl;
655 default:
656 return 0;
657 }
658}
659
660static int
661coap_hitls_get_verify_session(HITLS_CERT_StoreCtx *store_ctx,
662 coap_session_t **session) {
663 HITLS_Ctx *ctx = NULL;
664
665 if (!store_ctx || !session)
666 return 0;
667 *session = NULL;
668 if (HITLS_X509_StoreCtxCtrl((HITLS_X509_StoreCtx *)store_ctx,
669 HITLS_X509_STORECTX_GET_USR_DATA,
670 &ctx, sizeof(ctx)) != HITLS_PKI_SUCCESS ||
671 !ctx)
672 return 0;
673 *session = (coap_session_t *)HITLS_GetUserData(ctx);
674 return *session != NULL;
675}
676
677static int
678coap_hitls_get_verify_cert(HITLS_CERT_StoreCtx *store_ctx,
679 HITLS_X509_Cert **cert, int32_t *depth) {
680 if (!store_ctx || !cert || !depth)
681 return 0;
682
683 *cert = NULL;
684 *depth = 0;
685 (void)HITLS_X509_StoreCtxCtrl((HITLS_X509_StoreCtx *)store_ctx,
686 HITLS_X509_STORECTX_GET_CUR_DEPTH,
687 depth, sizeof(*depth));
688 return HITLS_X509_StoreCtxCtrl((HITLS_X509_StoreCtx *)store_ctx,
689 HITLS_X509_STORECTX_GET_CUR_CERT,
690 cert, sizeof(*cert)) == HITLS_PKI_SUCCESS &&
691 *cert;
692}
693
694static int
695coap_hitls_cert_is_self_signed(HITLS_X509_Cert *cert) {
696 bool self_signed = false;
697
698 return cert &&
699 HITLS_X509_CertCtrl(cert, HITLS_X509_IS_SELF_SIGNED,
700 &self_signed,
701 sizeof(self_signed)) == HITLS_PKI_SUCCESS &&
702 self_signed;
703}
704
705/*
706 * The self-signed override bypasses the library chain verification, which is
707 * where the validity period is normally checked. Apply the same check here,
708 * using the library time helpers, so an expired or not-yet-valid self-signed
709 * leaf is not accepted. Returns HITLS_PKI_SUCCESS or a specific failure code.
710 */
711static int32_t
712coap_hitls_cert_time_valid(HITLS_X509_Cert *cert) {
713 BSL_TIME not_before;
714 BSL_TIME not_after;
715 int64_t start;
716 int64_t end;
717 int64_t now = BSL_SAL_CurrentSysTimeGet();
718
719 if (now <= 0)
720 return BSL_SAL_TIME_SYS_ERROR;
721 if (HITLS_X509_CertCtrl(cert, HITLS_X509_GET_BEFORE_TIME, &not_before,
722 sizeof(not_before)) != HITLS_PKI_SUCCESS ||
723 BSL_SAL_DateToUtcTimeConvert(&not_before, &start) != BSL_SUCCESS)
724 return HITLS_X509_ERR_VFY_GET_NOTBEFORE_FAIL;
725 if (start > now)
726 return HITLS_X509_ERR_VFY_NOTBEFORE_IN_FUTURE;
727 if (HITLS_X509_CertCtrl(cert, HITLS_X509_GET_AFTER_TIME, &not_after,
728 sizeof(not_after)) != HITLS_PKI_SUCCESS ||
729 BSL_SAL_DateToUtcTimeConvert(&not_after, &end) != BSL_SUCCESS)
730 return HITLS_X509_ERR_VFY_GET_NOTAFTER_FAIL;
731 if (end < now)
732 return HITLS_X509_ERR_VFY_NOTAFTER_EXPIRED;
733 return HITLS_PKI_SUCCESS;
734}
735
736static int
737coap_hitls_get_peer_leaf_cert(HITLS_CERT_StoreCtx *store_ctx,
738 HITLS_X509_Cert **cert,
739 int32_t *chain_count) {
740 HITLS_X509_List *peer_chain = NULL;
741
742 if (!store_ctx || !cert || !chain_count)
743 return 0;
744
745 *cert = NULL;
746 *chain_count = 0;
747 if (HITLS_X509_StoreCtxCtrl((HITLS_X509_StoreCtx *)store_ctx,
748 HITLS_X509_STORECTX_GET_PEER_CERT_CHAIN,
749 &peer_chain,
750 sizeof(peer_chain)) != HITLS_PKI_SUCCESS ||
751 !peer_chain)
752 return 0;
753
754 *chain_count = BSL_LIST_COUNT(peer_chain);
755 *cert = (HITLS_X509_Cert *)BSL_LIST_FIRST_ELMT(peer_chain);
756 return *cert != NULL;
757}
758
759static int
760coap_hitls_self_signed_leaf_allowed(const coap_dtls_pki_t *setup_data,
761 HITLS_CERT_StoreCtx *store_ctx,
762 HITLS_X509_Cert **leaf_cert) {
763 HITLS_X509_Cert *cert = NULL;
764 int32_t chain_count = 0;
765
766 if (leaf_cert)
767 *leaf_cert = NULL;
768 if (!setup_data || !setup_data->allow_self_signed ||
769 setup_data->check_common_ca)
770 return 0;
771 if (!coap_hitls_get_peer_leaf_cert(store_ctx, &cert, &chain_count) ||
772 chain_count != 1 || !coap_hitls_cert_is_self_signed(cert))
773 return 0;
774 if (leaf_cert)
775 *leaf_cert = cert;
776 return 1;
777}
778
779static int
780coap_hitls_verify_cb_self_signed_allowed(const coap_dtls_pki_t *setup_data,
781 HITLS_CERT_StoreCtx *store_ctx) {
782 HITLS_X509_Cert *cert = NULL;
783 int32_t depth = 0;
784
785 return setup_data && setup_data->allow_self_signed &&
786 !setup_data->check_common_ca &&
787 coap_hitls_get_verify_cert(store_ctx, &cert, &depth) &&
788 depth == 0 && coap_hitls_cert_is_self_signed(cert);
789}
790
791static char *
792coap_hitls_copy_name(const uint8_t *data, uint32_t data_len) {
793 char *copy;
794 size_t len = (size_t)data_len;
795
796 if (data_len && !data)
797 return NULL;
798 copy = (char *)coap_malloc_type(COAP_STRING, len + 1);
799 if (!copy)
800 return NULL;
801 if (len)
802 memcpy(copy, data, len);
803 copy[len] = '\000';
804 return copy;
805}
806
807static char *
808coap_hitls_get_san_from_cert(coap_session_t *session, HITLS_X509_Cert *cert,
809 const char *sni_match, int report_san) {
810 HITLS_X509_ExtSan san = {0};
811 char *dns_name = NULL;
812
813 if (HITLS_X509_CertCtrl(cert, HITLS_X509_EXT_GET_SAN, &san,
814 sizeof(san)) == HITLS_PKI_SUCCESS &&
815 san.names) {
816 int n = 0;
817
818 for (BslListNode *name_node = BSL_LIST_FirstNode(san.names);
819 name_node != NULL;
820 name_node = BSL_LIST_GetNextNode(san.names, name_node)) {
821 const HITLS_X509_GeneralName *name =
822 (const HITLS_X509_GeneralName *)BSL_LIST_GetData(name_node);
823
824 if (!name || name->type != HITLS_X509_GN_DNS)
825 continue;
826 if (name->value.dataLen &&
827 memchr(name->value.data, '\000', name->value.dataLen))
828 continue;
829 if (report_san) {
830 coap_log_debug(" %s: got DNS.%d '%*.*s'\n",
831 coap_session_str(session), n + 1, (int)name->value.dataLen, (int)name->value.dataLen,
832 name->value.data);
833 n++;
834 continue;
835 }
836 if (sni_match) {
837 if (strlen(sni_match) != name->value.dataLen ||
838 memcmp(name->value.data, sni_match, name->value.dataLen)) {
839 continue;
840 }
841 }
842 dns_name = coap_hitls_copy_name(name->value.data, name->value.dataLen);
843 break;
844 }
845 }
846
847 HITLS_X509_ClearSubjectAltName(&san);
848 return dns_name;
849}
850
851static char *
852coap_hitls_get_cn_from_cert(coap_session_t *session, HITLS_X509_Cert *cert, const char *sni_match) {
853 BSL_Buffer cn = {0};
854 char *cn_name = NULL;
855
856 if (HITLS_X509_CertCtrl(cert, HITLS_X509_GET_SUBJECT_CN_STR,
857 &cn, sizeof(cn)) == HITLS_PKI_SUCCESS) {
858 if (cn.data && coap_pki_name_match_sni((char *)cn.data, cn.dataLen, sni_match)) {
859 cn_name = coap_hitls_copy_name(cn.data, cn.dataLen);
860 }
861 }
862 if (cn.data && !cn_name) {
863 coap_log_debug(" %s: got CN '%*.*s'\n",
864 coap_session_str(session), (int)cn.dataLen, (int)cn.dataLen, cn.data);
865 }
866 if (cn.data)
867 BSL_SAL_Free(cn.data);
868 return cn_name;
869}
870
871static char *
872coap_hitls_get_san_or_cn_from_cert(coap_session_t *session, HITLS_X509_Cert *cert,
873 const char *sni_match) {
874 char *name;
875
876 if (!cert)
877 return NULL;
878 name = coap_hitls_get_san_from_cert(session, cert, sni_match, 0);
879 if (name)
880 return name;
881 name = coap_hitls_get_cn_from_cert(session, cert, sni_match);
882 if (!name) {
883 name = coap_hitls_get_san_from_cert(session, cert, sni_match, 1);
884 }
885 return name;
886}
887
888static int
889coap_hitls_validate_cn_cert(coap_session_t *session,
890 const coap_dtls_pki_t *setup_data,
891 HITLS_X509_Cert *cert,
892 unsigned depth,
893 int validated,
894 char **san_or_cn) {
895 uint8_t *der = NULL;
896 uint32_t der_len = 0;
897 int ret = 1;
898
899 (void)HITLS_X509_CertCtrl(cert, HITLS_X509_GET_ENCODELEN,
900 &der_len, sizeof(der_len));
901 if (der_len)
902 (void)HITLS_X509_CertCtrl(cert, HITLS_X509_GET_ENCODE,
903 &der, sizeof(der));
904 if (!*san_or_cn)
905 *san_or_cn = coap_hitls_get_san_or_cn_from_cert(session, cert, NULL);
906
907 if (setup_data->validate_cn_call_back) {
909 setup_data->validate_cn_call_back(
910 *san_or_cn ? *san_or_cn : "",
911 der, der_len, session, depth, validated,
912 setup_data->cn_call_back_arg));
913 }
914 return ret;
915}
916
917static int
918coap_hitls_verify_cb(int32_t err_code, HITLS_CERT_StoreCtx *store_ctx) {
919 coap_session_t *session = NULL;
920 coap_hitls_context_t *context;
921 coap_dtls_pki_t *setup_data;
922 HITLS_X509_Cert *cert;
923 int32_t depth;
924 int allowed;
925 char *san_or_cn = NULL;
926
927 if (!coap_hitls_get_verify_session(store_ctx, &session) ||
928 !session->context || !session->context->dtls_context)
929 return err_code;
930
931 context = (coap_hitls_context_t *)session->context->dtls_context;
932 setup_data = &context->setup_data;
933
934 if (!coap_hitls_get_verify_cert(store_ctx, &cert, &depth)) {
935 return err_code;
936 }
937 if (!setup_data->allow_sni_cn_mismatch && depth <= 0 &&
938 session->type == COAP_SESSION_TYPE_CLIENT && setup_data->client_sni) {
939
940 san_or_cn = coap_hitls_get_san_or_cn_from_cert(session, cert, setup_data->client_sni);
941 if (!san_or_cn) {
942 /* No match on returned Cert for requested host */
943 coap_log_warn("* %s: SNI '%s' not returned in certificate\n",
944 coap_session_str(session),
945 setup_data->client_sni);
946 return HITLS_X509_ERR_VFY_HOSTNAME_FAIL;
947 }
948 }
949 if (setup_data->validate_cn_call_back) {
950 if (!coap_hitls_validate_cn_cert(session, setup_data, cert,
951 depth < 0 ? 0 : (unsigned)depth,
952 err_code == HITLS_PKI_SUCCESS, &san_or_cn)) {
953 coap_log_warn("* %s: certificate verification failed: %s\n",
954 coap_session_str(session),
955 coap_hitls_verify_err_str(HITLS_X509_ERR_VFY_HOSTNAME_FAIL));
956 if (san_or_cn)
957 coap_free_type(COAP_STRING, san_or_cn);
958 return HITLS_X509_ERR_VFY_HOSTNAME_FAIL;
959 }
960 }
961 if (san_or_cn)
962 coap_free_type(COAP_STRING, san_or_cn);
963
964 if (err_code == HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND ||
965 err_code == HITLS_X509_ERR_ROOT_CERT_NOT_FOUND) {
966 allowed = coap_hitls_verify_cb_self_signed_allowed(setup_data,
967 store_ctx);
968 } else {
969 allowed = coap_hitls_verify_error_allowed(setup_data, err_code);
970 }
971 if (!allowed) {
972 coap_log_warn("* %s: certificate verification failed: %s (0x%x)\n",
973 coap_session_str(session),
974 coap_hitls_verify_err_str(err_code), (unsigned int)err_code);
975 return err_code;
976 }
977
978 return HITLS_PKI_SUCCESS;
979}
980
981static int32_t
982coap_hitls_app_verify_cb(HITLS_CERT_StoreCtx *store_ctx,
983 void *arg COAP_UNUSED) {
984 coap_session_t *session = NULL;
985 coap_hitls_context_t *context;
986 coap_dtls_pki_t *setup_data;
987 HITLS_X509_List *peer_chain = NULL;
988 HITLS_X509_Cert *leaf_cert = NULL;
989 int32_t ret;
990
991 if (!coap_hitls_get_verify_session(store_ctx, &session) ||
992 !session->context || !session->context->dtls_context)
993 return HITLS_X509_ERR_INVALID_PARAM;
994
995 if (HITLS_X509_StoreCtxCtrl((HITLS_X509_StoreCtx *)store_ctx,
996 HITLS_X509_STORECTX_GET_PEER_CERT_CHAIN,
997 &peer_chain,
998 sizeof(peer_chain)) != HITLS_PKI_SUCCESS ||
999 !peer_chain)
1000 return HITLS_X509_ERR_INVALID_PARAM;
1001
1002 ret = HITLS_X509_CertVerify((HITLS_X509_StoreCtx *)store_ctx, peer_chain);
1003 if (ret == HITLS_PKI_SUCCESS)
1004 return HITLS_APP_VERIFY_CALLBACK_SUCCESS;
1005
1006 context = (coap_hitls_context_t *)session->context->dtls_context;
1007 setup_data = &context->setup_data;
1008 if ((ret == HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND ||
1009 ret == HITLS_X509_ERR_ROOT_CERT_NOT_FOUND) &&
1010 coap_hitls_self_signed_leaf_allowed(setup_data, store_ctx,
1011 &leaf_cert)) {
1012 char *san_or_cn = NULL;
1013 if (!setup_data->allow_expired_certs) {
1014 int32_t time_ret = coap_hitls_cert_time_valid(leaf_cert);
1015
1016 if (time_ret != HITLS_PKI_SUCCESS) {
1017 coap_log_warn("* %s: certificate verification failed: %s\n",
1018 coap_session_str(session),
1019 coap_hitls_verify_err_str(time_ret));
1020 return time_ret;
1021 }
1022 }
1023 coap_log_info(" %s: %s: overridden: 'self-signed' depth=0\n",
1024 coap_session_str(session),
1025 coap_hitls_verify_err_str(ret));
1026 if (!coap_hitls_validate_cn_cert(session, setup_data, leaf_cert, 0, 0, &san_or_cn)) {
1027 if (san_or_cn)
1028 coap_free_type(COAP_STRING, san_or_cn);
1029 return HITLS_X509_ERR_VFY_HOSTNAME_FAIL;
1030 }
1031 if (san_or_cn)
1032 coap_free_type(COAP_STRING, san_or_cn);
1033 return HITLS_APP_VERIFY_CALLBACK_SUCCESS;
1034 }
1035
1036 return ret;
1037}
1038
1039static int
1040coap_hitls_is_retry(int32_t ret) {
1041 switch (ret) {
1042 case HITLS_WANT_CONNECT:
1043 case HITLS_WANT_ACCEPT:
1044 case HITLS_WANT_READ:
1045 case HITLS_WANT_WRITE:
1046 case HITLS_WANT_BACKUP:
1047 case HITLS_WANT_CLIENT_HELLO_CB:
1048 case HITLS_WANT_X509_LOOKUP:
1049 case HITLS_REC_NORMAL_IO_BUSY:
1050 case HITLS_REC_NORMAL_RECV_BUF_EMPTY:
1051 return 1;
1052 default:
1053 return 0;
1054 }
1055}
1056
1057static int
1058coap_hitls_is_closed(int32_t ret) {
1059 return ret == HITLS_CM_LINK_CLOSED;
1060}
1061
1062static uint8_t
1063coap_hitls_udp_overhead(const coap_hitls_env_t *env) {
1064#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
1065 if (env && env->session) {
1066 switch (env->session->addr_info.remote.addr.sa.sa_family) {
1067#ifdef AF_INET6
1068 case AF_INET6:
1069 return COAP_HITLS_IPV6_UDP_OVERHEAD;
1070#endif /* AF_INET6 */
1071#ifdef AF_INET
1072 case AF_INET:
1073#endif /* AF_INET */
1074 default:
1075 break;
1076 }
1077 }
1078#else /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
1079 (void)env;
1080#endif /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
1081 return COAP_HITLS_IPV4_UDP_OVERHEAD;
1082}
1083
1084static void
1085coap_hitls_set_connected(coap_session_t *session, coap_hitls_env_t *env) {
1086 if (env->established)
1087 return;
1088
1089 env->established = 1;
1090 if (session->state == COAP_SESSION_STATE_HANDSHAKE) {
1092 session);
1093 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
1094 }
1095}
1096
1097static int
1098coap_hitls_check_handshake_done(coap_session_t *session,
1099 coap_hitls_env_t *env) {
1100 uint8_t done = 0;
1101
1102 if (HITLS_IsHandShakeDone(env->ctx, &done) == HITLS_SUCCESS && done) {
1103 coap_hitls_set_connected(session, env);
1104 return 1;
1105 }
1106 return 0;
1107}
1108
1109static int
1110coap_hitls_handshake(coap_session_t *session, coap_hitls_env_t *env) {
1111 int32_t ret;
1112
1113 BSL_ERR_ClearError();
1114 if (env->role == COAP_DTLS_ROLE_CLIENT)
1115 ret = HITLS_Connect(env->ctx);
1116 else
1117 ret = HITLS_Accept(env->ctx);
1118
1119 if (ret == HITLS_SUCCESS)
1120 return coap_hitls_check_handshake_done(session, env);
1121 if (coap_hitls_check_handshake_done(session, env))
1122 return 1;
1123 if (coap_hitls_is_retry(ret))
1124 return 0;
1125
1126 coap_log_warn("coap_hitls_handshake: returned 0x%x\n", (unsigned int)ret);
1127 coap_hitls_log_fatal_err_stack(session);
1129 return -1;
1130}
1131
1132static int32_t
1133coap_hitls_uio_write(BSL_UIO *uio, const void *buf, uint32_t len,
1134 uint32_t *write_len) {
1135 coap_hitls_env_t *env = (coap_hitls_env_t *)BSL_UIO_GetUserData(uio);
1136 ssize_t ret;
1137
1138 if (write_len)
1139 *write_len = 0;
1140 if (!env || !env->session || !buf || !write_len)
1141 return BSL_NULL_INPUT;
1142 if (!coap_netif_available(env->session)
1144 && env->session->endpoint == NULL
1145#endif /* COAP_SERVER_SUPPORT */
1146 ) {
1147 errno = ECONNRESET;
1148 return BSL_UIO_IO_EXCEPTION;
1149 }
1150
1151 (void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
1152 ret = env->session->sock.lfunc[COAP_LAYER_TLS].l_write(env->session,
1153 (const uint8_t *)buf, len);
1154 if (ret < 0) {
1155#ifdef EMSGSIZE
1156 if (errno == EMSGSIZE) {
1157 env->mtu_exceeded = 1;
1158 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_WRITE | BSL_UIO_FLAGS_SHOULD_RETRY);
1159 return BSL_SUCCESS;
1160 }
1161#endif /* EMSGSIZE */
1162 if (errno == ENOTCONN || errno == ECONNREFUSED)
1163 env->session->dtls_event = COAP_EVENT_DTLS_ERROR;
1164 return BSL_UIO_IO_EXCEPTION;
1165 }
1166 if (ret == 0) {
1167 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_WRITE | BSL_UIO_FLAGS_SHOULD_RETRY);
1168 return BSL_SUCCESS;
1169 }
1170 *write_len = (uint32_t)ret;
1171 return BSL_SUCCESS;
1172}
1173
1174static int32_t
1175coap_hitls_uio_read(BSL_UIO *uio, void *buf, uint32_t len,
1176 uint32_t *read_len) {
1177 coap_hitls_env_t *env = (coap_hitls_env_t *)BSL_UIO_GetUserData(uio);
1178 size_t copy_len;
1179
1180 if (read_len)
1181 *read_len = 0;
1182 if (!env || !buf || !read_len)
1183 return BSL_NULL_INPUT;
1184 if (env->proto == COAP_PROTO_TLS) {
1185 ssize_t ret;
1186
1187 (void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
1188 ret = env->session->sock.lfunc[COAP_LAYER_TLS].l_read(env->session,
1189 (uint8_t *)buf, len);
1190 if (ret < 0)
1191 return errno == ECONNRESET ? BSL_UIO_IO_EOF : BSL_UIO_IO_EXCEPTION;
1192 if (ret == 0) {
1193 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_READ | BSL_UIO_FLAGS_SHOULD_RETRY);
1194 return BSL_SUCCESS;
1195 }
1196 *read_len = (uint32_t)ret;
1197 return BSL_SUCCESS;
1198 }
1199 if (!env->pdu || env->pdu_len == 0) {
1200 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_READ | BSL_UIO_FLAGS_SHOULD_RETRY);
1201 return BSL_SUCCESS;
1202 }
1203
1204 copy_len = env->pdu_len < len ? env->pdu_len : len;
1205 memcpy(buf, env->pdu, copy_len);
1206 env->pdu += copy_len;
1207 env->pdu_len -= copy_len;
1208 *read_len = (uint32_t)copy_len;
1209 return BSL_SUCCESS;
1210}
1211
1212static int32_t
1213coap_hitls_uio_ctrl(BSL_UIO *uio, int32_t cmd, int32_t larg, void *parg) {
1214 coap_hitls_env_t *env = (coap_hitls_env_t *)BSL_UIO_GetUserData(uio);
1215
1216 if (!env)
1217 return BSL_NULL_INPUT;
1218
1219 switch (cmd) {
1220 case BSL_UIO_GET_FD:
1221 if (parg) {
1222#if defined(_WIN32)
1223 *(int32_t *)parg = -1;
1224#elif COAP_SERVER_SUPPORT
1225 *(int32_t *)parg = (int32_t)(COAP_PROTO_NOT_RELIABLE(env->session->proto) ?
1226 env->session->type != COAP_SESSION_TYPE_CLIENT ?
1227 env->session->endpoint->sock.fd :
1228 env->session->sock.fd :
1229 env->session->sock.fd);
1230#else /* ! _WIN32 && ! COAP_SERVER_SUPPORT */
1231 *(int32_t *)parg = (int32_t)env->session->sock.fd;
1232#endif /* ! _WIN32 */
1233 }
1234 return BSL_SUCCESS;
1235 case BSL_UIO_SET_FD:
1236 case BSL_UIO_SET_PEER_IP_ADDR:
1237 case BSL_UIO_UDP_SET_CONNECTED:
1238 case BSL_UIO_FLUSH:
1239 case BSL_UIO_RESET:
1240 return BSL_SUCCESS;
1241 case BSL_UIO_GET_PEER_IP_ADDR:
1242 if (!parg || !env->session)
1243 return BSL_NULL_INPUT;
1244 if (larg == (int32_t)sizeof(BSL_UIO_CtrlGetPeerIpAddrParam)) {
1245 BSL_UIO_CtrlGetPeerIpAddrParam *param =
1246 (BSL_UIO_CtrlGetPeerIpAddrParam *)parg;
1247 uint32_t addr_len = (uint32_t)env->session->addr_info.remote.size;
1248
1249 if (!param->addr || param->size < addr_len)
1250 return BSL_INVALID_ARG;
1251 memcpy(param->addr, &env->session->addr_info.remote.addr.sa, addr_len);
1252 param->size = addr_len;
1253 return BSL_SUCCESS;
1254 }
1255 if (env->session->addr_info.remote.size > (socklen_t)larg)
1256 return BSL_INVALID_ARG;
1257 memcpy(parg, &env->session->addr_info.remote.addr.sa,
1258 env->session->addr_info.remote.size);
1259 return BSL_SUCCESS;
1260 case BSL_UIO_PENDING:
1261 case BSL_UIO_WPENDING:
1262 if (parg)
1263 *(uint64_t *)parg = cmd == BSL_UIO_PENDING ? env->pdu_len : 0;
1264 return BSL_SUCCESS;
1265 case BSL_UIO_UDP_GET_MTU_OVERHEAD:
1266 if (!parg)
1267 return BSL_NULL_INPUT;
1268 if (larg != (int32_t)sizeof(uint8_t))
1269 return BSL_INVALID_ARG;
1270 *(uint8_t *)parg = coap_hitls_udp_overhead(env);
1271 return BSL_SUCCESS;
1272 case BSL_UIO_UDP_QUERY_MTU:
1273 if (!parg)
1274 return BSL_NULL_INPUT;
1275 if (larg != (int32_t)sizeof(uint32_t))
1276 return BSL_INVALID_ARG;
1277 *(uint32_t *)parg = env->session->mtu > UINT32_MAX ?
1278 UINT32_MAX : (uint32_t)env->session->mtu;
1279 return BSL_SUCCESS;
1280 case BSL_UIO_UDP_MTU_EXCEEDED:
1281 if (!parg)
1282 return BSL_NULL_INPUT;
1283 if (larg != (int32_t)sizeof(bool))
1284 return BSL_INVALID_ARG;
1285 *(bool *)parg = env->mtu_exceeded != 0;
1286 env->mtu_exceeded = 0;
1287 return BSL_SUCCESS;
1288 default:
1289 return BSL_SUCCESS;
1290 }
1291}
1292
1293static int
1294coap_hitls_setup_uio(coap_hitls_env_t *env) {
1295 BSL_UIO *uio;
1296 BSL_UIO_TransportType type =
1297 env->proto == COAP_PROTO_DTLS ? BSL_UIO_UDP : BSL_UIO_TCP;
1298
1299 env->method = BSL_UIO_NewMethod();
1300 if (!env->method)
1301 return 0;
1302#if defined(__GNUC__)
1303#pragma GCC diagnostic push
1304#pragma GCC diagnostic ignored "-Wpedantic"
1305#endif /* defined(__GNUC__) */
1306 if (BSL_UIO_SetMethodType(env->method, type) != BSL_SUCCESS ||
1307 BSL_UIO_SetMethod(env->method, BSL_UIO_WRITE_CB,
1308 (void *)coap_hitls_uio_write) != BSL_SUCCESS ||
1309 BSL_UIO_SetMethod(env->method, BSL_UIO_READ_CB,
1310 (void *)coap_hitls_uio_read) != BSL_SUCCESS ||
1311 BSL_UIO_SetMethod(env->method, BSL_UIO_CTRL_CB,
1312 (void *)coap_hitls_uio_ctrl) != BSL_SUCCESS) {
1313 BSL_UIO_FreeMethod(env->method);
1314 env->method = NULL;
1315 return 0;
1316 }
1317#if defined(__GNUC__)
1318#pragma GCC diagnostic pop
1319#endif /* defined(__GNUC__) */
1320
1321 uio = BSL_UIO_New(env->method);
1322 if (!uio)
1323 return 0;
1324 if (BSL_UIO_SetUserData(uio, env) != BSL_SUCCESS) {
1325 BSL_UIO_Free(uio);
1326 return 0;
1327 }
1328 BSL_UIO_SetInit(uio, true);
1329 if (HITLS_SetUio(env->ctx, uio) != HITLS_SUCCESS) {
1330 BSL_UIO_SetUserData(uio, NULL);
1331 BSL_UIO_Free(uio);
1332 return 0;
1333 }
1334 env->uio = HITLS_GetUio(env->ctx);
1335 BSL_UIO_Free(uio);
1336 return 1;
1337}
1338
1339static void
1340coap_hitls_update_mtu(coap_hitls_env_t *env) {
1341 uint16_t mtu;
1342 int32_t ret;
1343
1344 if (!env || !env->ctx || !env->session || env->proto != COAP_PROTO_DTLS)
1345 return;
1346
1347 mtu = env->session->mtu > UINT16_MAX ? UINT16_MAX :
1348 (uint16_t)env->session->mtu;
1349 ret = HITLS_SetMtu(env->ctx, mtu);
1350 if (ret != HITLS_SUCCESS) {
1351 coap_log_warn("HITLS_SetMtu(%u) returned 0x%x\n", mtu,
1352 (unsigned int)ret);
1353 }
1354}
1355
1356#if COAP_CLIENT_SUPPORT
1357static uint32_t
1358coap_hitls_psk_client_cb(HITLS_Ctx *ctx, const uint8_t *hint,
1359 uint8_t *identity, uint32_t max_identity_len,
1360 uint8_t *psk, uint32_t max_psk_len) {
1361 coap_session_t *session = (coap_session_t *)HITLS_GetUserData(ctx);
1362 coap_dtls_cpsk_t *setup_data;
1363 const coap_dtls_cpsk_info_t *cpsk_info;
1364 const coap_bin_const_t *psk_identity;
1365 const coap_bin_const_t *psk_key;
1366
1367 if (!session || !session->context)
1368 return 0;
1369
1370 setup_data = &session->cpsk_setup_data;
1371 if (setup_data->validate_ih_call_back) {
1372 coap_bin_const_t temp;
1373 coap_str_const_t lhint;
1374
1375 temp.s = hint ? hint : (const uint8_t *)"";
1376 temp.length = coap_hitls_strnlen(temp.s, COAP_DTLS_MAX_PSK_IDENTITY);
1377 coap_session_refresh_psk_hint(session, &temp);
1378
1379 lhint.s = temp.s;
1380 lhint.length = temp.length;
1381 coap_lock_callback_ret(cpsk_info,
1382 setup_data->validate_ih_call_back(&lhint,
1383 session,
1384 setup_data->ih_call_back_arg));
1385 if (!cpsk_info)
1386 return 0;
1387 coap_session_refresh_psk_identity(session, &cpsk_info->identity);
1388 coap_session_refresh_psk_key(session, &cpsk_info->key);
1389 psk_identity = &cpsk_info->identity;
1390 psk_key = &cpsk_info->key;
1391 } else {
1392 psk_identity = coap_get_session_client_psk_identity(session);
1393 psk_key = coap_get_session_client_psk_key(session);
1394 }
1395
1396 if (coap_hitls_copy_bin(identity, max_identity_len, psk_identity, 1) == 0 ||
1397 coap_hitls_copy_bin(psk, max_psk_len, psk_key, 0) == 0)
1398 return 0;
1399 return (uint32_t)psk_key->length;
1400}
1401#endif /* COAP_CLIENT_SUPPORT */
1402
1403#if COAP_SERVER_SUPPORT
1404static HITLS_Config *coap_hitls_new_server_sni_config(coap_session_t *session, coap_proto_t proto,
1405 const coap_dtls_key_t *new_key);
1406
1407static int32_t
1408coap_hitls_sni_cb(HITLS_Ctx *ctx, int *alert COAP_UNUSED,
1409 void *arg COAP_UNUSED) {
1410 coap_session_t *session = (coap_session_t *)HITLS_GetUserData(ctx);
1411 coap_hitls_context_t *context =
1412 session && session->context ?
1413 (coap_hitls_context_t *)session->context->dtls_context : NULL;
1414 coap_dtls_pki_t *pki_setup_data = context ? &context->setup_data : NULL;
1415 coap_dtls_spsk_t *psk_setup_data;
1416 const char *sni;
1417 int accepted = 0;
1418
1419 if (!session || !session->context)
1420 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1421 sni = HITLS_GetServerName(ctx, HITLS_SNI_HOSTNAME_TYPE);
1422 if (!sni)
1423 sni = "";
1424
1425 if (pki_setup_data && pki_setup_data->validate_sni_call_back) {
1426 coap_dtls_key_t *new_key;
1427 HITLS_Config *new_config;
1428
1429 coap_lock_callback_ret(new_key,
1430 pki_setup_data->validate_sni_call_back(
1431 sni, pki_setup_data->sni_call_back_arg));
1432 if (!new_key)
1433 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1434 new_config = coap_hitls_new_server_sni_config(session, session->proto,
1435 new_key);
1436 if (!new_config)
1437 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1438 if (!HITLS_SetNewConfig(ctx, new_config)) {
1439 HITLS_CFG_FreeConfig(new_config);
1440 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1441 }
1442 HITLS_CFG_FreeConfig(new_config);
1443 accepted = 1;
1444 }
1445
1446 psk_setup_data = &session->context->spsk_setup_data;
1447 if (psk_setup_data->validate_sni_call_back) {
1448 const coap_dtls_spsk_info_t *new_entry;
1449
1450 coap_lock_callback_ret(new_entry,
1451 psk_setup_data->validate_sni_call_back(
1452 sni, session, psk_setup_data->sni_call_back_arg));
1453 if (!new_entry)
1454 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1455 if (!coap_session_refresh_psk_hint(session, &new_entry->hint) ||
1456 !coap_session_refresh_psk_key(session, &new_entry->key))
1457 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1458 if (new_entry->hint.s && new_entry->hint.length > 0 &&
1459 new_entry->hint.length <= UINT32_MAX &&
1460 HITLS_SetPskIdentityHint(ctx, new_entry->hint.s,
1461 (uint32_t)new_entry->hint.length) != HITLS_SUCCESS)
1462 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1463 accepted = 1;
1464 }
1465
1466 return accepted ? HITLS_ACCEPT_SNI_ERR_OK : HITLS_ACCEPT_SNI_ERR_NOACK;
1467}
1468
1469static uint32_t
1470coap_hitls_psk_server_cb(HITLS_Ctx *ctx, const uint8_t *identity,
1471 uint8_t *psk, uint32_t max_psk_len) {
1472 coap_session_t *session = (coap_session_t *)HITLS_GetUserData(ctx);
1473 coap_dtls_spsk_t *setup_data;
1474 coap_bin_const_t lidentity;
1475 const coap_bin_const_t *psk_key;
1476
1477 if (!session || !session->context)
1478 return 0;
1479
1480 setup_data = &session->context->spsk_setup_data;
1481 lidentity.s = identity ? identity : (const uint8_t *)"";
1482 lidentity.length = coap_hitls_strnlen(lidentity.s,
1484 coap_session_refresh_psk_identity(session, &lidentity);
1485
1486 if (setup_data->validate_id_call_back) {
1487 coap_lock_callback_ret(psk_key,
1488 setup_data->validate_id_call_back(&lidentity,
1489 session,
1490 setup_data->id_call_back_arg));
1491 coap_session_refresh_psk_key(session, psk_key);
1492 } else {
1493 psk_key = coap_get_session_server_psk_key(session);
1494 }
1495
1496 if (coap_hitls_copy_bin(psk, max_psk_len, psk_key, 0) == 0)
1497 return 0;
1498 return (uint32_t)psk_key->length;
1499}
1500#endif /* COAP_SERVER_SUPPORT */
1501
1502static int32_t
1503coap_hitls_alpn_select_cb(HITLS_Ctx *ctx COAP_UNUSED,
1504 uint8_t **selected_proto,
1505 uint8_t *selected_proto_len,
1506 uint8_t *client_alpn_list,
1507 uint32_t client_alpn_list_size,
1508 void *user_data COAP_UNUSED) {
1509 if (HITLS_SelectAlpnProtocol(selected_proto, selected_proto_len,
1510 coap_hitls_alpn, sizeof(coap_hitls_alpn),
1511 client_alpn_list,
1512 client_alpn_list_size) != HITLS_SUCCESS ||
1513 !selected_proto || !*selected_proto ||
1514 !selected_proto_len || *selected_proto_len != 4)
1515 return HITLS_ALPN_ERR_ALERT_FATAL;
1516 return HITLS_ALPN_ERR_OK;
1517}
1518
1519static int
1520coap_hitls_load_ca(HITLS_Config *config, coap_dtls_key_t *key,
1521 coap_dtls_role_t role) {
1522 coap_pki_key_define_t *define = &key->key.define;
1523 uint32_t len;
1524 uint8_t *buf;
1525 int32_t ret;
1526
1527 switch (define->ca_def) {
1529 if (!define->ca.s_byte || !define->ca.s_byte[0])
1530 return 1;
1531 if (HITLS_CFG_LoadVerifyFile(config, define->ca.s_byte) == HITLS_SUCCESS)
1532 return 1;
1534 COAP_DEFINE_FAIL_BAD, key, role, 0);
1536 if (!define->ca.u_byte || !define->ca_len)
1537 return 1;
1538 if (!coap_hitls_pki_len(define->ca.u_byte, define->ca_len,
1539 TLS_PARSE_FORMAT_PEM, &len))
1541 COAP_DEFINE_FAIL_BAD, key, role, 0);
1542 if (HITLS_CFG_LoadVerifyBuffer(config, define->ca.u_byte, len,
1543 TLS_PARSE_FORMAT_PEM) == HITLS_SUCCESS)
1544 return 1;
1546 COAP_DEFINE_FAIL_BAD, key, role, 0);
1548 if (!define->ca.u_byte || !define->ca_len)
1549 return 1;
1550 if (!coap_hitls_pki_len(define->ca.u_byte, define->ca_len,
1551 TLS_PARSE_FORMAT_ASN1, &len))
1553 COAP_DEFINE_FAIL_BAD, key, role, 0);
1554 if (HITLS_CFG_LoadVerifyBuffer(config, define->ca.u_byte, len,
1555 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1556 return 1;
1558 COAP_DEFINE_FAIL_BAD, key, role, 0);
1560 if (!define->ca.s_byte || !define->ca.s_byte[0])
1561 return 1;
1562 buf = coap_hitls_read_file(define->ca.s_byte, &len);
1563 if (!buf)
1565 COAP_DEFINE_FAIL_BAD, key, role, 0);
1566 ret = HITLS_CFG_LoadVerifyBuffer(config, buf, len, TLS_PARSE_FORMAT_ASN1);
1568 if (ret == HITLS_SUCCESS)
1569 return 1;
1571 COAP_DEFINE_FAIL_BAD, key, role, ret);
1576 if (define->ca.u_byte && define->ca.u_byte[0])
1579 role, 0);
1580 return 1;
1581 default:
1582 return 1;
1583 }
1584}
1585
1586static int
1587coap_hitls_load_public_cert(HITLS_Config *config, coap_dtls_key_t *key,
1588 coap_dtls_role_t role) {
1589 coap_pki_key_define_t *define = &key->key.define;
1590 uint32_t len;
1591
1592 switch (define->public_cert_def) {
1594 if (!define->public_cert.s_byte || !define->public_cert.s_byte[0])
1595 return 1;
1596 /* A PEM buffer may hold leaf + intermediate CAs; load the whole chain. */
1597 if (HITLS_CFG_UseCertificateChainFile(config,
1598 define->public_cert.s_byte) == HITLS_SUCCESS)
1599 return 1;
1601 COAP_DEFINE_FAIL_BAD, key, role, 0);
1603 if (!define->public_cert.s_byte || !define->public_cert.s_byte[0])
1604 return 1;
1605 if (HITLS_CFG_LoadCertFile(config, define->public_cert.s_byte,
1606 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1607 return 1;
1609 COAP_DEFINE_FAIL_BAD, key, role, 0);
1611 if (!define->public_cert.u_byte || !define->public_cert_len)
1612 return 1;
1613 if (!coap_hitls_pki_len(define->public_cert.u_byte,
1614 define->public_cert_len, TLS_PARSE_FORMAT_PEM,
1615 &len))
1617 COAP_DEFINE_FAIL_BAD, key, role, 0);
1618 /* A PEM buffer may hold leaf + intermediate CAs; load the whole chain. */
1619 if (HITLS_CFG_UseCertificateChainBuffer(config, define->public_cert.u_byte,
1620 len, TLS_PARSE_FORMAT_PEM) == HITLS_SUCCESS)
1621 return 1;
1623 COAP_DEFINE_FAIL_BAD, key, role, 0);
1625 if (!define->public_cert.u_byte || !define->public_cert_len)
1626 return 1;
1627 if (!coap_hitls_pki_len(define->public_cert.u_byte,
1628 define->public_cert_len, TLS_PARSE_FORMAT_ASN1,
1629 &len))
1631 COAP_DEFINE_FAIL_BAD, key, role, 0);
1632 if (HITLS_CFG_LoadCertBuffer(config, define->public_cert.u_byte, len,
1633 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1634 return 1;
1636 COAP_DEFINE_FAIL_BAD, key, role, 0);
1641 if (define->public_cert.u_byte && define->public_cert.u_byte[0])
1644 role, 0);
1645 return 1;
1646 default:
1647 return 1;
1648 }
1649}
1650
1651static int
1652coap_hitls_load_private_key(HITLS_Config *config, coap_dtls_key_t *key,
1653 coap_dtls_role_t role) {
1654 coap_pki_key_define_t *define = &key->key.define;
1655 uint32_t len;
1656
1657 switch (define->private_key_def) {
1659 if (!define->private_key.s_byte || !define->private_key.s_byte[0])
1660 return 1;
1661 if (HITLS_CFG_LoadKeyFile(config, define->private_key.s_byte,
1662 TLS_PARSE_FORMAT_PEM) == HITLS_SUCCESS)
1663 return 1;
1665 COAP_DEFINE_FAIL_BAD, key, role, 0);
1667 if (!define->private_key.s_byte || !define->private_key.s_byte[0])
1668 return 1;
1669 if (HITLS_CFG_LoadKeyFile(config, define->private_key.s_byte,
1670 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1671 return 1;
1673 COAP_DEFINE_FAIL_BAD, key, role, 0);
1675 if (!define->private_key.u_byte || !define->private_key_len)
1676 return 1;
1677 if (!coap_hitls_pki_len(define->private_key.u_byte,
1678 define->private_key_len, TLS_PARSE_FORMAT_PEM,
1679 &len))
1681 COAP_DEFINE_FAIL_BAD, key, role, 0);
1682 if (HITLS_CFG_LoadKeyBuffer(config, define->private_key.u_byte, len,
1683 TLS_PARSE_FORMAT_PEM) == HITLS_SUCCESS)
1684 return 1;
1686 COAP_DEFINE_FAIL_BAD, key, role, 0);
1688 if (!define->private_key.u_byte || !define->private_key_len)
1689 return 1;
1690 if (!coap_hitls_pki_len(define->private_key.u_byte,
1691 define->private_key_len, TLS_PARSE_FORMAT_ASN1,
1692 &len))
1694 COAP_DEFINE_FAIL_BAD, key, role, 0);
1695 if (HITLS_CFG_LoadKeyBuffer(config, define->private_key.u_byte, len,
1696 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1697 return 1;
1699 COAP_DEFINE_FAIL_BAD, key, role, 0);
1704 if (define->private_key.u_byte && define->private_key.u_byte[0])
1707 role, 0);
1708 return 1;
1709 default:
1710 return 1;
1711 }
1712}
1713
1714static int
1715coap_hitls_load_root_cas(HITLS_Config *config, coap_hitls_context_t *context) {
1716 if (context->root_ca_file &&
1717 HITLS_CFG_LoadVerifyFile(config, context->root_ca_file) != HITLS_SUCCESS) {
1718 coap_log_warn("Unable to install root CA file '%s'\n",
1719 context->root_ca_file);
1720 return 0;
1721 }
1722 if (context->root_ca_dir &&
1723 HITLS_CFG_LoadVerifyDir(config, context->root_ca_dir) != HITLS_SUCCESS) {
1724 coap_log_warn("Unable to install root CA directory '%s'\n",
1725 context->root_ca_dir);
1726 return 0;
1727 }
1728 if (context->trust_store_defined &&
1729 HITLS_CFG_LoadDefaultCAPath(config) != HITLS_SUCCESS) {
1730 coap_log_warn("Unable to load trusted root CAs\n");
1731 return 0;
1732 }
1733 return 1;
1734}
1735
1736static int
1737coap_hitls_configure_pki(HITLS_Config *config, coap_session_t *session,
1738 coap_dtls_role_t role,
1739 const coap_dtls_pki_t *pki_setup_data) {
1740 coap_hitls_context_t *context =
1741 session && session->context ?
1742 (coap_hitls_context_t *)session->context->dtls_context : NULL;
1743 coap_dtls_pki_t setup_data_copy;
1744 coap_dtls_pki_t *setup_data = context ? &context->setup_data : NULL;
1745 coap_dtls_key_t key;
1746
1747 if (pki_setup_data) {
1748 setup_data_copy = *pki_setup_data;
1749 setup_data = &setup_data_copy;
1750 }
1751 if (!context || !setup_data)
1752 return 0;
1753 if (!coap_hitls_check_pki_key_supported(setup_data, role))
1754 return 0;
1755
1756 coap_dtls_map_key_type_to_define(setup_data, &key);
1757 if (key.key_type != COAP_PKI_KEY_DEFINE)
1758 return 0;
1759
1760 if (!coap_hitls_load_root_cas(config, context) ||
1761 !coap_hitls_load_ca(config, &key, role) ||
1762 !coap_hitls_load_public_cert(config, &key, role) ||
1763 !coap_hitls_load_private_key(config, &key, role))
1764 return 0;
1765
1766 if (setup_data->cert_chain_validation &&
1767 HITLS_CFG_SetVerifyDepth(config,
1768 COAP_HITLS_VERIFY_DEPTH_TO_MAX_CHAIN_DEPTH(
1769 setup_data->cert_chain_verify_depth)) !=
1770 HITLS_SUCCESS)
1771 return 0;
1772 if (setup_data->check_cert_revocation &&
1773 HITLS_CFG_SetVerifyFlags(config,
1774 HITLS_X509_VFY_FLAG_CRL_ALL) != HITLS_SUCCESS)
1775 return 0;
1776 if (HITLS_CFG_SetVerifyCb(config, coap_hitls_verify_cb) != HITLS_SUCCESS)
1777 return 0;
1778 if (HITLS_CFG_SetCertVerifyCb(config, coap_hitls_app_verify_cb,
1779 NULL) != HITLS_SUCCESS)
1780 return 0;
1781
1782 if (role == COAP_DTLS_ROLE_CLIENT) {
1783 if (setup_data->client_sni && setup_data->client_sni[0] &&
1784 HITLS_CFG_SetServerName(config,
1785 (uint8_t *)setup_data->client_sni,
1786 (uint32_t)strlen(setup_data->client_sni)) != HITLS_SUCCESS)
1787 return 0;
1788 } else {
1789 if (HITLS_CFG_SetClientVerifySupport(config,
1790 setup_data->verify_peer_cert ? true : false) != HITLS_SUCCESS)
1791 return 0;
1792 if (setup_data->verify_peer_cert &&
1793 HITLS_CFG_SetNoClientCertSupport(config, false) != HITLS_SUCCESS)
1794 return 0;
1795 }
1796
1797 if (HITLS_CFG_SetVerifyNoneSupport(config,
1798 setup_data->verify_peer_cert ? false : true) != HITLS_SUCCESS)
1799 return 0;
1800 return 1;
1801}
1802
1803#if COAP_SERVER_SUPPORT
1804static HITLS_Config *
1805coap_hitls_new_server_sni_config(coap_session_t *session, coap_proto_t proto,
1806 const coap_dtls_key_t *new_key) {
1807 coap_hitls_context_t *context =
1808 session && session->context ?
1809 (coap_hitls_context_t *)session->context->dtls_context : NULL;
1810 const uint16_t *cipher_suites;
1811 uint32_t cipher_suites_count;
1812 int enabled = context && context->psk_pki_enabled ?
1813 context->psk_pki_enabled : IS_PKI;
1814 coap_dtls_pki_t pki_setup_data;
1815 HITLS_Config *config;
1816
1817 if (!context || !new_key)
1818 return NULL;
1819
1820 config = proto == COAP_PROTO_DTLS ? HITLS_CFG_NewDTLS12Config() :
1821 HITLS_CFG_NewTLS12Config();
1822 if (!config)
1823 return NULL;
1824
1825 coap_hitls_get_cipher_suites(enabled, &cipher_suites, &cipher_suites_count);
1826 if (HITLS_CFG_SetCipherSuites(config, cipher_suites,
1827 cipher_suites_count) != HITLS_SUCCESS) {
1828 HITLS_CFG_FreeConfig(config);
1829 return NULL;
1830 }
1831 if (proto == COAP_PROTO_DTLS &&
1832 (HITLS_CFG_SetFlightTransmitSwitch(config, true) != HITLS_SUCCESS ||
1833 HITLS_CFG_SetDtlsCookieExchangeSupport(config, true) != HITLS_SUCCESS ||
1834 HITLS_CFG_SetCookieGenCb(config,
1835 coap_hitls_cookie_gen_cb) != HITLS_SUCCESS ||
1836 HITLS_CFG_SetCookieVerifyCb(config,
1837 coap_hitls_cookie_verify_cb) != HITLS_SUCCESS)) {
1838 HITLS_CFG_FreeConfig(config);
1839 return NULL;
1840 }
1841 if (proto == COAP_PROTO_TLS &&
1842 HITLS_CFG_SetAlpnProtosSelectCb(config, coap_hitls_alpn_select_cb,
1843 NULL) != HITLS_SUCCESS) {
1844 HITLS_CFG_FreeConfig(config);
1845 return NULL;
1846 }
1847 if (enabled & IS_PSK) {
1849
1850 if (hint && hint->s && hint->length <= UINT32_MAX &&
1851 HITLS_CFG_SetPskIdentityHint(config, hint->s,
1852 (uint32_t)hint->length) != HITLS_SUCCESS) {
1853 HITLS_CFG_FreeConfig(config);
1854 return NULL;
1855 }
1856 if (HITLS_CFG_SetPskServerCallback(config,
1857 coap_hitls_psk_server_cb) != HITLS_SUCCESS) {
1858 HITLS_CFG_FreeConfig(config);
1859 return NULL;
1860 }
1861 }
1862
1863 pki_setup_data = context->setup_data;
1864 pki_setup_data.pki_key = *new_key;
1865 if (!coap_hitls_configure_pki(config, session, COAP_DTLS_ROLE_SERVER,
1866 &pki_setup_data)) {
1867 HITLS_CFG_FreeConfig(config);
1868 return NULL;
1869 }
1870
1871 (void)HITLS_CFG_SetInfoCb(config, coap_hitls_info_cb);
1872 return config;
1873}
1874#endif /* COAP_SERVER_SUPPORT */
1875
1876static HITLS_Config *
1877coap_hitls_new_config(coap_session_t *session, coap_dtls_role_t role,
1878 coap_proto_t proto) {
1879 coap_hitls_context_t *hitls_context =
1880 session && session->context ?
1881 (coap_hitls_context_t *)session->context->dtls_context : NULL;
1882 const uint16_t *cipher_suites;
1883 uint32_t cipher_suites_count;
1884 int enabled = hitls_context && hitls_context->psk_pki_enabled ?
1885 hitls_context->psk_pki_enabled : IS_PSK;
1886 HITLS_Config *config = proto == COAP_PROTO_DTLS ?
1887 HITLS_CFG_NewDTLS12Config() :
1888 HITLS_CFG_NewTLS12Config();
1889
1890 if (!config)
1891 return NULL;
1892
1893 coap_hitls_get_cipher_suites(enabled, &cipher_suites, &cipher_suites_count);
1894
1895 if (HITLS_CFG_SetCipherSuites(config, cipher_suites,
1896 cipher_suites_count) != HITLS_SUCCESS) {
1897 HITLS_CFG_FreeConfig(config);
1898 return NULL;
1899 }
1900 if (proto == COAP_PROTO_DTLS &&
1901 (HITLS_CFG_SetFlightTransmitSwitch(config, true) != HITLS_SUCCESS ||
1902 HITLS_CFG_SetDtlsCookieExchangeSupport(config,
1903 role == COAP_DTLS_ROLE_SERVER) != HITLS_SUCCESS)) {
1904 HITLS_CFG_FreeConfig(config);
1905 return NULL;
1906 }
1907#if COAP_SERVER_SUPPORT
1908 if (proto == COAP_PROTO_DTLS && role == COAP_DTLS_ROLE_SERVER &&
1909 (HITLS_CFG_SetCookieGenCb(config,
1910 coap_hitls_cookie_gen_cb) != HITLS_SUCCESS ||
1911 HITLS_CFG_SetCookieVerifyCb(config,
1912 coap_hitls_cookie_verify_cb) != HITLS_SUCCESS)) {
1913 HITLS_CFG_FreeConfig(config);
1914 return NULL;
1915 }
1916#endif /* COAP_SERVER_SUPPORT */
1917 if (proto == COAP_PROTO_TLS &&
1918 ((role == COAP_DTLS_ROLE_CLIENT &&
1919 HITLS_CFG_SetAlpnProtos(config, coap_hitls_alpn,
1920 sizeof(coap_hitls_alpn)) != HITLS_SUCCESS) ||
1921 (role == COAP_DTLS_ROLE_SERVER &&
1922 HITLS_CFG_SetAlpnProtosSelectCb(config,
1923 coap_hitls_alpn_select_cb,
1924 NULL) != HITLS_SUCCESS))) {
1925 HITLS_CFG_FreeConfig(config);
1926 return NULL;
1927 }
1928
1929 if (role == COAP_DTLS_ROLE_CLIENT && (enabled & IS_PSK)) {
1930#if COAP_CLIENT_SUPPORT
1931 coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
1932
1933 if (setup_data->client_sni && setup_data->client_sni[0] &&
1934 HITLS_CFG_SetServerName(config,
1935 (uint8_t *)setup_data->client_sni,
1936 (uint32_t)strlen(setup_data->client_sni)) != HITLS_SUCCESS) {
1937 HITLS_CFG_FreeConfig(config);
1938 return NULL;
1939 }
1940 if (HITLS_CFG_SetPskClientCallback(config,
1941 coap_hitls_psk_client_cb) != HITLS_SUCCESS) {
1942 HITLS_CFG_FreeConfig(config);
1943 return NULL;
1944 }
1945#else /* ! COAP_CLIENT_SUPPORT */
1946 (void)session;
1947 HITLS_CFG_FreeConfig(config);
1948 return NULL;
1949#endif /* ! COAP_CLIENT_SUPPORT */
1950 } else if (role == COAP_DTLS_ROLE_SERVER && (enabled & IS_PSK)) {
1951#if COAP_SERVER_SUPPORT
1953
1954 if (hint && hint->s && hint->length <= UINT32_MAX &&
1955 HITLS_CFG_SetPskIdentityHint(config, hint->s,
1956 (uint32_t)hint->length) != HITLS_SUCCESS) {
1957 HITLS_CFG_FreeConfig(config);
1958 return NULL;
1959 }
1960 if (HITLS_CFG_SetPskServerCallback(config,
1961 coap_hitls_psk_server_cb) != HITLS_SUCCESS) {
1962 HITLS_CFG_FreeConfig(config);
1963 return NULL;
1964 }
1965#else /* ! COAP_SERVER_SUPPORT */
1966 (void)session;
1967 HITLS_CFG_FreeConfig(config);
1968 return NULL;
1969#endif /* ! COAP_SERVER_SUPPORT */
1970 }
1971
1972#if COAP_SERVER_SUPPORT
1973 if (role == COAP_DTLS_ROLE_SERVER) {
1974 int needs_sni = 0;
1975
1976 if ((enabled & IS_PSK) && session && session->context &&
1977 session->context->spsk_setup_data.validate_sni_call_back)
1978 needs_sni = 1;
1979 if ((enabled & IS_PKI) && hitls_context &&
1980 hitls_context->setup_data.validate_sni_call_back)
1981 needs_sni = 1;
1982 if (needs_sni &&
1983 (HITLS_CFG_SetServerNameCb(config,
1984 coap_hitls_sni_cb) != HITLS_SUCCESS ||
1985 HITLS_CFG_SetServerNameArg(config, NULL) != HITLS_SUCCESS)) {
1986 HITLS_CFG_FreeConfig(config);
1987 return NULL;
1988 }
1989 }
1990#endif /* COAP_SERVER_SUPPORT */
1991
1992 if ((enabled & IS_PKI) &&
1993 !coap_hitls_configure_pki(config, session, role, NULL)) {
1994 HITLS_CFG_FreeConfig(config);
1995 return NULL;
1996 }
1997
1998 (void)HITLS_CFG_SetInfoCb(config, coap_hitls_info_cb);
1999 return config;
2000}
2001
2002static void
2003coap_hitls_free_env(coap_hitls_env_t *env) {
2004 if (!env)
2005 return;
2006 if (env->ctx) {
2007 if (env->established && !env->had_fatal)
2008 (void)HITLS_Close(env->ctx);
2009 if (env->uio)
2010 BSL_UIO_SetUserData(env->uio, NULL);
2011 HITLS_Free(env->ctx);
2012 } else if (env->uio) {
2013 BSL_UIO_SetUserData(env->uio, NULL);
2014 }
2015 if (env->method)
2016 BSL_UIO_FreeMethod(env->method);
2018}
2019
2020static coap_hitls_env_t *
2021coap_hitls_live_env(coap_session_t *session, coap_hitls_env_t *env) {
2022 return session && session->tls == (void *)env ? env : NULL;
2023}
2024
2025static void
2026coap_hitls_clear_pdu(coap_hitls_env_t *env) {
2027 if (env) {
2028 env->pdu = NULL;
2029 env->pdu_len = 0;
2030 }
2031}
2032
2033static coap_hitls_env_t *
2034coap_hitls_new_env(coap_session_t *session, coap_dtls_role_t role,
2035 coap_proto_t proto) {
2036 coap_hitls_env_t *env =
2037 (coap_hitls_env_t *)coap_malloc_type(COAP_STRING, sizeof(*env));
2038 coap_hitls_context_t *hitls_context =
2039 session && session->context ?
2040 (coap_hitls_context_t *)session->context->dtls_context : NULL;
2041 HITLS_Config *config;
2042
2043 if (!env)
2044 return NULL;
2045 memset(env, 0, sizeof(*env));
2046 env->session = session;
2047 env->role = role;
2048 env->proto = proto;
2049
2050 config = coap_hitls_new_config(session, role, proto);
2051 if (!config) {
2053 return NULL;
2054 }
2055
2056 env->ctx = HITLS_New(config);
2057 HITLS_CFG_FreeConfig(config);
2058 if (!env->ctx) {
2060 return NULL;
2061 }
2062 if (HITLS_SetUserData(env->ctx, session) != HITLS_SUCCESS ||
2063 !coap_hitls_setup_uio(env)) {
2064 coap_hitls_free_env(env);
2065 return NULL;
2066 }
2067 coap_hitls_update_mtu(env);
2068 if (hitls_context && (hitls_context->psk_pki_enabled & IS_PKI) &&
2069 hitls_context->setup_data.additional_tls_setup_call_back &&
2070 !hitls_context->setup_data.additional_tls_setup_call_back(env->ctx,
2071 &hitls_context->setup_data)) {
2072 coap_hitls_free_env(env);
2073 return NULL;
2074 }
2075
2076 return env;
2077}
2078
2079int
2081 return 1;
2082}
2083
2084int
2086#if !COAP_DISABLE_TCP
2087 return 1;
2088#else /* COAP_DISABLE_TCP */
2089 return 0;
2090#endif /* COAP_DISABLE_TCP */
2091}
2092
2093int
2095 return 1;
2096}
2097
2098int
2100 return 1;
2101}
2102
2103int
2105 return 0;
2106}
2107
2108int
2110 return 0;
2111}
2112
2113int
2115 return 0;
2116}
2117
2118#if COAP_CLIENT_SUPPORT
2119int
2121 uint8_t every COAP_UNUSED) {
2122 return 0;
2123}
2124#endif /* COAP_CLIENT_SUPPORT */
2125
2126void
2128 dtls_log_level = level;
2129}
2130
2133 return dtls_log_level;
2134}
2135#endif /* COAP_WITH_LIBOPENHITLS */
2136
2139 static coap_tls_version_t version;
2140
2141 version.version = HITLS_VersionNum();
2142 version.built_version = OPENHITLS_VERSION_I;
2144 return &version;
2145}
2146
2147void
2148coap_dtls_startup(void) {
2149 (void)coap_hitls_startup();
2150}
2151
2152void
2153coap_dtls_shutdown(void) {
2154 if (coap_hitls_started) {
2155#if COAP_WITH_LIBOPENHITLS
2156 HITLS_CertMethodDeinit();
2157#endif /* COAP_WITH_LIBOPENHITLS */
2158 CRYPT_EAL_Cleanup(CRYPT_EAL_INIT_ALL);
2159 coap_hitls_started = 0;
2160 }
2162}
2163
2164void
2166 BSL_ERR_RemoveErrorStack(false);
2167}
2168
2169#if COAP_WITH_LIBOPENHITLS
2170void *
2171coap_dtls_get_tls(const coap_session_t *session, coap_tls_library_t *tls_lib) {
2172 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
2173
2174 if (tls_lib)
2175 *tls_lib = COAP_TLS_LIBRARY_OPENHITLS;
2176 return env ? env->ctx : NULL;
2177}
2178
2179void *
2181 coap_hitls_context_t *context =
2182 (coap_hitls_context_t *)coap_malloc_type(COAP_STRING, sizeof(*context));
2183
2184 if (!context)
2185 return NULL;
2186 memset(context, 0, sizeof(*context));
2187 context->coap_context = coap_context;
2188 if (!coap_prng_lkd(context->cookie_secret,
2189 sizeof(context->cookie_secret))) {
2190 coap_free_type(COAP_STRING, context);
2191 return NULL;
2192 }
2193 context->cookie_secret_set = 1;
2194 return context;
2195}
2196
2197void
2198coap_dtls_free_context(void *dtls_context) {
2199 coap_hitls_context_t *context = (coap_hitls_context_t *)dtls_context;
2200
2201 if (context) {
2202 if (context->root_ca_file)
2203 coap_free_type(COAP_STRING, context->root_ca_file);
2204 if (context->root_ca_dir)
2205 coap_free_type(COAP_STRING, context->root_ca_dir);
2206 memset(context->cookie_secret, 0, sizeof(context->cookie_secret));
2207 context->cookie_secret_set = 0;
2208 coap_free_type(COAP_STRING, context);
2209 }
2210}
2211
2212#if COAP_SERVER_SUPPORT
2213int
2214coap_dtls_context_set_spsk(coap_context_t *coap_context,
2215 coap_dtls_spsk_t *setup_data) {
2216 coap_hitls_context_t *context;
2217
2218 if (!coap_context || !setup_data)
2219 return 0;
2220 context = (coap_hitls_context_t *)coap_context->dtls_context;
2221 if (!context)
2222 return 0;
2223 context->psk_pki_enabled |= IS_PSK;
2224 return 1;
2225}
2226#endif /* COAP_SERVER_SUPPORT */
2227
2228#if COAP_CLIENT_SUPPORT
2229int
2230coap_dtls_context_set_cpsk(coap_context_t *coap_context,
2231 coap_dtls_cpsk_t *setup_data) {
2232 coap_hitls_context_t *context;
2233
2234 if (!coap_context || !setup_data)
2235 return 0;
2236 context = (coap_hitls_context_t *)coap_context->dtls_context;
2237 if (!context)
2238 return 0;
2239 context->psk_pki_enabled |= IS_PSK;
2240 return 1;
2241}
2242#endif /* COAP_CLIENT_SUPPORT */
2243
2244int
2246 const coap_dtls_pki_t *setup_data,
2247 const coap_dtls_role_t role) {
2248 coap_hitls_context_t *context;
2249
2250 if (!coap_context || !setup_data)
2251 return 0;
2252 context = (coap_hitls_context_t *)coap_context->dtls_context;
2253 if (!context)
2254 return 0;
2255 if (!coap_hitls_check_pki_key_supported(setup_data, role))
2256 return 0;
2257 context->setup_data = *setup_data;
2258 if (!context->setup_data.verify_peer_cert) {
2259 /* Needs to be clear so that no CA DNs are transmitted */
2260 context->setup_data.check_common_ca = 0;
2261 /* Allow all of these but warn if issue */
2262 context->setup_data.allow_self_signed = 1;
2263 context->setup_data.allow_expired_certs = 1;
2264 context->setup_data.cert_chain_validation = 1;
2265 context->setup_data.cert_chain_verify_depth = 10;
2266 context->setup_data.check_cert_revocation = 1;
2267 context->setup_data.allow_no_crl = 1;
2268 context->setup_data.allow_expired_crl = 1;
2269 context->setup_data.allow_bad_md_hash = 1;
2270 context->setup_data.allow_short_rsa_length = 1;
2271 }
2272#if COAP_CLIENT_SUPPORT
2273 if (role == COAP_DTLS_ROLE_CLIENT)
2274 context->psk_pki_enabled &= ~IS_PSK;
2275#else /* ! COAP_CLIENT_SUPPORT */
2276 (void)role;
2277#endif /* ! COAP_CLIENT_SUPPORT */
2278 context->psk_pki_enabled |= IS_PKI;
2279 if (setup_data->use_cid)
2280 coap_log_warn("openHiTLS backend has no Connection-ID support\n");
2281 return 1;
2282}
2283
2284int
2286 const char *ca_file,
2287 const char *ca_dir) {
2288 coap_hitls_context_t *context;
2289 char *new_ca_file = NULL;
2290 char *new_ca_dir = NULL;
2291
2292 if (!coap_context || (!ca_file && !ca_dir))
2293 return 0;
2294 context = (coap_hitls_context_t *)coap_context->dtls_context;
2295 if (!context)
2296 return 0;
2297 if (ca_file) {
2298 new_ca_file = coap_hitls_strdup(ca_file);
2299 if (!new_ca_file)
2300 return 0;
2301 }
2302 if (ca_dir) {
2303 new_ca_dir = coap_hitls_strdup(ca_dir);
2304 if (!new_ca_dir) {
2305 if (new_ca_file)
2306 coap_free_type(COAP_STRING, new_ca_file);
2307 return 0;
2308 }
2309 }
2310 if (context->root_ca_file)
2311 coap_free_type(COAP_STRING, context->root_ca_file);
2312 if (context->root_ca_dir)
2313 coap_free_type(COAP_STRING, context->root_ca_dir);
2314 context->root_ca_file = new_ca_file;
2315 context->root_ca_dir = new_ca_dir;
2316 return 1;
2317}
2318
2319int
2321 coap_hitls_context_t *context =
2322 coap_context ? (coap_hitls_context_t *)coap_context->dtls_context : NULL;
2323
2324 if (!context)
2325 return 0;
2326 context->trust_store_defined = 1;
2327 return 1;
2328}
2329
2330int
2332 coap_hitls_context_t *context =
2333 coap_context ? (coap_hitls_context_t *)coap_context->dtls_context : NULL;
2334
2335 return context && context->psk_pki_enabled;
2336}
2337#endif /* COAP_WITH_LIBOPENHITLS */
2338
2339#if COAP_SERVER_SUPPORT
2340coap_digest_ctx_t *
2341coap_digest_setup(void) {
2342 CRYPT_EAL_MdCtx *digest_ctx;
2343
2344 if (!coap_hitls_startup())
2345 return NULL;
2346 digest_ctx = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
2347 if (!digest_ctx)
2348 return NULL;
2349 if (CRYPT_EAL_MdInit(digest_ctx) != CRYPT_SUCCESS) {
2350 CRYPT_EAL_MdFreeCtx(digest_ctx);
2351 return NULL;
2352 }
2353 return digest_ctx;
2354}
2355
2356void
2357coap_digest_free(coap_digest_ctx_t *digest_ctx) {
2358 if (digest_ctx)
2359 CRYPT_EAL_MdFreeCtx((CRYPT_EAL_MdCtx *)digest_ctx);
2360}
2361
2362int
2363coap_digest_update(coap_digest_ctx_t *digest_ctx,
2364 const uint8_t *data,
2365 size_t data_len) {
2366 CRYPT_EAL_MdCtx *ctx = (CRYPT_EAL_MdCtx *)digest_ctx;
2367
2368 if (!ctx || (!data && data_len))
2369 return 0;
2370 while (data_len) {
2371 uint32_t chunk = data_len > UINT32_MAX ? UINT32_MAX : (uint32_t)data_len;
2372
2373 if (CRYPT_EAL_MdUpdate(ctx, data, chunk) != CRYPT_SUCCESS)
2374 return 0;
2375 data += chunk;
2376 data_len -= chunk;
2377 }
2378 return 1;
2379}
2380
2381int
2382coap_digest_final(coap_digest_ctx_t *digest_ctx,
2383 coap_digest_t *digest_buffer) {
2384 CRYPT_EAL_MdCtx *ctx = (CRYPT_EAL_MdCtx *)digest_ctx;
2385 uint32_t len = sizeof(*digest_buffer);
2386 int ret;
2387
2388 if (!ctx || !digest_buffer)
2389 return 0;
2390 ret = CRYPT_EAL_MdFinal(ctx, (uint8_t *)digest_buffer, &len) == CRYPT_SUCCESS &&
2391 len == sizeof(*digest_buffer);
2392 coap_digest_free(digest_ctx);
2393 return ret;
2394}
2395#endif /* COAP_SERVER_SUPPORT */
2396
2397#if COAP_WS_SUPPORT
2398static const struct {
2399 cose_alg_t alg;
2400 CRYPT_MD_AlgId md;
2401 uint32_t length;
2402} coap_hitls_hashs[] = {
2403 {COSE_ALGORITHM_SHA_1, CRYPT_MD_SHA1, 20},
2404 {COSE_ALGORITHM_SHA_256_64, CRYPT_MD_SHA256, 8},
2405 {COSE_ALGORITHM_SHA_256_256, CRYPT_MD_SHA256, 32},
2406 {COSE_ALGORITHM_SHA_512, CRYPT_MD_SHA512, 64},
2407};
2408
2409int
2411 const coap_bin_const_t *data,
2412 coap_bin_const_t **hash) {
2413 coap_binary_t *digest;
2414 uint32_t len;
2415 size_t i;
2416 CRYPT_MD_AlgId md = CRYPT_MD_SHA1;
2417 uint32_t out_len = 0;
2418
2419 if (!data || !hash || data->length > UINT32_MAX || !coap_hitls_startup())
2420 return 0;
2421 for (i = 0; i < sizeof(coap_hitls_hashs) / sizeof(coap_hitls_hashs[0]); i++) {
2422 if (coap_hitls_hashs[i].alg == alg) {
2423 md = coap_hitls_hashs[i].md;
2424 out_len = coap_hitls_hashs[i].length;
2425 break;
2426 }
2427 }
2428 if (out_len == 0) {
2429 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
2430 return 0;
2431 }
2432
2433 len = CRYPT_EAL_MdGetDigestSize(md);
2434 digest = coap_new_binary(len);
2435 if (!digest)
2436 return 0;
2437
2438 if (CRYPT_EAL_Md(md, data->s, (uint32_t)data->length,
2439 digest->s, &len) != CRYPT_SUCCESS ||
2440 len != digest->length) {
2441 coap_delete_binary(digest);
2442 return 0;
2443 }
2444 if (out_len < digest->length)
2445 digest->length = out_len;
2446
2447 *hash = (coap_bin_const_t *)digest;
2448 return 1;
2449}
2450#endif /* COAP_WS_SUPPORT */
2451
2452#if COAP_OSCORE_SUPPORT
2453
2454int
2456 return 1;
2457}
2458
2459static int
2460coap_hitls_get_cipher_alg(cose_alg_t alg, CRYPT_CIPHER_AlgId *cipher_alg,
2461 size_t *key_len) {
2462 switch ((int)alg) {
2464 if (cipher_alg)
2465 *cipher_alg = CRYPT_CIPHER_AES128_CCM;
2466 if (key_len)
2467 *key_len = 16;
2468 return 1;
2470 if (cipher_alg)
2471 *cipher_alg = CRYPT_CIPHER_AES256_CCM;
2472 if (key_len)
2473 *key_len = 32;
2474 return 1;
2475 default:
2476 coap_log_debug("coap_hitls_get_cipher_alg: COSE cipher %d not supported\n",
2477 alg);
2478 return 0;
2479 }
2480}
2481
2482static int
2483coap_hitls_get_hmac_alg(cose_hmac_alg_t hmac_alg, CRYPT_MAC_AlgId *mac_alg,
2484 size_t *mac_len) {
2485 switch ((int)hmac_alg) {
2487 if (mac_alg)
2488 *mac_alg = CRYPT_MAC_HMAC_SHA256;
2489 if (mac_len)
2491 return 1;
2493 if (mac_alg)
2494 *mac_alg = CRYPT_MAC_HMAC_SHA384;
2495 if (mac_len)
2497 return 1;
2499 if (mac_alg)
2500 *mac_alg = CRYPT_MAC_HMAC_SHA512;
2501 if (mac_len)
2503 return 1;
2504 default:
2505 coap_log_debug("coap_hitls_get_hmac_alg: COSE HMAC %d not supported\n",
2506 hmac_alg);
2507 return 0;
2508 }
2509}
2510
2511int
2513 return coap_hitls_get_cipher_alg(alg, NULL, NULL);
2514}
2515
2516int
2518 cose_hmac_alg_t hmac_alg;
2519
2520 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
2521 return 0;
2522 return coap_hitls_get_hmac_alg(hmac_alg, NULL, NULL);
2523}
2524
2525static int
2526coap_hitls_check_ccm_params(const coap_crypto_aes_ccm_t *ccm, size_t key_len) {
2527 if (!ccm || !ccm->key.s || !ccm->nonce || ccm->key.length != key_len)
2528 return 0;
2529 if (ccm->l == 0 || ccm->l > 8)
2530 return 0;
2531 if (ccm->tag_len == 0 || ccm->tag_len > UINT32_MAX)
2532 return 0;
2533 return 1;
2534}
2535
2536static int
2537coap_hitls_aead_set_common(CRYPT_EAL_CipherCtx *ctx,
2538 const coap_crypto_aes_ccm_t *ccm,
2539 const coap_bin_const_t *aad, uint64_t msg_len) {
2540 uint32_t tag_len = (uint32_t)ccm->tag_len;
2541 uint32_t aad_len = 0;
2542
2543 if (CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_TAGLEN,
2544 &tag_len, sizeof(tag_len)) != CRYPT_SUCCESS)
2545 return 0;
2546 if (CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_MSGLEN,
2547 &msg_len, sizeof(msg_len)) != CRYPT_SUCCESS)
2548 return 0;
2549 if (aad && aad->length) {
2550 if (aad->length > UINT32_MAX)
2551 return 0;
2552 aad_len = (uint32_t)aad->length;
2553 }
2554 return CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_AAD,
2555 aad_len ? (void *)(uintptr_t)aad->s : NULL,
2556 aad_len) == CRYPT_SUCCESS;
2557}
2558
2559int
2561 coap_bin_const_t *data,
2562 coap_bin_const_t *aad,
2563 uint8_t *result,
2564 size_t *max_result_len) {
2565 CRYPT_CIPHER_AlgId cipher_alg;
2566 CRYPT_EAL_CipherCtx *ctx = NULL;
2567 const coap_crypto_aes_ccm_t *ccm;
2568 size_t key_len;
2569 uint32_t out_len;
2570 uint32_t tag_len;
2571 uint64_t msg_len;
2572 int ret = 0;
2573
2574 if (!params || !data || !result || !max_result_len)
2575 return 0;
2576 if (!coap_hitls_get_cipher_alg(params->alg, &cipher_alg, &key_len))
2577 return 0;
2578
2579 ccm = &params->params.aes;
2580 if (!coap_hitls_check_ccm_params(ccm, key_len) ||
2581 data->length > UINT32_MAX ||
2582 ccm->tag_len > *max_result_len ||
2583 data->length > *max_result_len - ccm->tag_len ||
2584 !coap_hitls_startup())
2585 return 0;
2586
2587 ctx = CRYPT_EAL_CipherNewCtx(cipher_alg);
2588 if (!ctx)
2589 return 0;
2590
2591 out_len = (uint32_t)data->length;
2592 tag_len = (uint32_t)ccm->tag_len;
2593 msg_len = data->length;
2594 if (CRYPT_EAL_CipherInit(ctx, ccm->key.s, (uint32_t)ccm->key.length,
2595 ccm->nonce, (uint32_t)(15 - ccm->l),
2596 true) != CRYPT_SUCCESS)
2597 goto finish;
2598 if (!coap_hitls_aead_set_common(ctx, ccm, aad, msg_len))
2599 goto finish;
2600 if (CRYPT_EAL_CipherUpdate(ctx, data->s, (uint32_t)data->length,
2601 result, &out_len) != CRYPT_SUCCESS)
2602 goto finish;
2603 if (out_len != data->length)
2604 goto finish;
2605 if (CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_GET_TAG,
2606 result + out_len, tag_len) != CRYPT_SUCCESS)
2607 goto finish;
2608
2609 *max_result_len = (size_t)out_len + ccm->tag_len;
2610 ret = 1;
2611
2612finish:
2613 CRYPT_EAL_CipherFreeCtx(ctx);
2614 return ret;
2615}
2616
2617int
2619 coap_bin_const_t *data,
2620 coap_bin_const_t *aad,
2621 uint8_t *result,
2622 size_t *max_result_len) {
2623 CRYPT_CIPHER_AlgId cipher_alg;
2624 CRYPT_EAL_CipherCtx *ctx = NULL;
2625 const coap_crypto_aes_ccm_t *ccm;
2626 const uint8_t *tag;
2627 size_t key_len;
2628 size_t cipher_len;
2629 uint32_t out_len;
2630 uint32_t final_len;
2631 uint32_t tag_len;
2632 uint64_t msg_len;
2633 int ret = 0;
2634
2635 if (!params || !data || !result || !max_result_len)
2636 return 0;
2637 if (!coap_hitls_get_cipher_alg(params->alg, &cipher_alg, &key_len))
2638 return 0;
2639
2640 ccm = &params->params.aes;
2641 if (!coap_hitls_check_ccm_params(ccm, key_len) ||
2642 data->length < ccm->tag_len ||
2643 data->length > UINT32_MAX ||
2644 !coap_hitls_startup())
2645 return 0;
2646
2647 cipher_len = data->length - ccm->tag_len;
2648 if (*max_result_len < cipher_len)
2649 return 0;
2650
2651 ctx = CRYPT_EAL_CipherNewCtx(cipher_alg);
2652 if (!ctx)
2653 return 0;
2654
2655 tag = data->s + cipher_len;
2656 out_len = (uint32_t)cipher_len;
2657 final_len = 0;
2658 tag_len = (uint32_t)ccm->tag_len;
2659 msg_len = cipher_len;
2660 if (CRYPT_EAL_CipherInit(ctx, ccm->key.s, (uint32_t)ccm->key.length,
2661 ccm->nonce, (uint32_t)(15 - ccm->l),
2662 false) != CRYPT_SUCCESS)
2663 goto finish;
2664 if (!coap_hitls_aead_set_common(ctx, ccm, aad, msg_len))
2665 goto finish;
2666 if (CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_TAG,
2667 (void *)(uintptr_t)tag, tag_len) != CRYPT_SUCCESS)
2668 goto finish;
2669 if (CRYPT_EAL_CipherUpdate(ctx, data->s, (uint32_t)cipher_len,
2670 result, &out_len) != CRYPT_SUCCESS)
2671 goto finish;
2672 if (out_len != cipher_len)
2673 goto finish;
2674 if (CRYPT_EAL_CipherFinal(ctx, result, &final_len) != CRYPT_SUCCESS)
2675 goto finish;
2676 if (final_len != 0)
2677 goto finish;
2678
2679 *max_result_len = out_len;
2680 ret = 1;
2681
2682finish:
2683 CRYPT_EAL_CipherFreeCtx(ctx);
2684 return ret;
2685}
2686
2687int
2689 coap_bin_const_t *key,
2690 coap_bin_const_t *data,
2691 coap_bin_const_t **hmac) {
2692 CRYPT_MAC_AlgId mac_alg;
2693 CRYPT_EAL_MacCtx *ctx = NULL;
2695 size_t mac_len;
2696 uint32_t out_len;
2697 int ret = 0;
2698
2699 if (!key || !data || !hmac ||
2700 key->length > UINT32_MAX || data->length > UINT32_MAX ||
2701 !coap_hitls_get_hmac_alg(hmac_alg, &mac_alg, &mac_len) ||
2702 !coap_hitls_startup())
2703 return 0;
2704
2705 dummy = coap_new_binary(mac_len);
2706 if (!dummy)
2707 return 0;
2708
2709 ctx = CRYPT_EAL_MacNewCtx(mac_alg);
2710 if (!ctx)
2711 goto finish;
2712
2713 out_len = (uint32_t)dummy->length;
2714 if (CRYPT_EAL_MacInit(ctx, key->s, (uint32_t)key->length) != CRYPT_SUCCESS)
2715 goto finish;
2716 if (CRYPT_EAL_MacUpdate(ctx, data->s, (uint32_t)data->length) != CRYPT_SUCCESS)
2717 goto finish;
2718 if (CRYPT_EAL_MacFinal(ctx, dummy->s, &out_len) != CRYPT_SUCCESS ||
2719 out_len != dummy->length)
2720 goto finish;
2721
2722 *hmac = (coap_bin_const_t *)dummy;
2723 dummy = NULL;
2724 ret = 1;
2725
2726finish:
2727 CRYPT_EAL_MacFreeCtx(ctx);
2729 return ret;
2730}
2731
2732#endif /* COAP_OSCORE_SUPPORT */
2733
2734#if COAP_WITH_LIBOPENHITLS
2735#if COAP_CLIENT_SUPPORT
2736void *
2737coap_dtls_new_client_session(coap_session_t *session) {
2738 coap_hitls_env_t *env =
2739 coap_hitls_new_env(session, COAP_DTLS_ROLE_CLIENT, COAP_PROTO_DTLS);
2740
2741 session->tls = env;
2742 if (env && coap_hitls_handshake(session, env) < 0) {
2743 coap_hitls_free_env(env);
2744 session->tls = NULL;
2745 return NULL;
2746 }
2747 return env;
2748}
2749#endif /* COAP_CLIENT_SUPPORT */
2750
2751#if COAP_SERVER_SUPPORT
2752void *
2753coap_dtls_new_server_session(coap_session_t *session) {
2754 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
2755
2756 if (!env)
2757 return NULL;
2758 if (coap_hitls_handshake(session, env) < 0) {
2759 coap_hitls_free_env(env);
2760 session->tls = NULL;
2761 return NULL;
2762 }
2763 return env;
2764}
2765#endif /* COAP_SERVER_SUPPORT */
2766
2767void
2769 if (session && session->context && session->tls) {
2770 coap_hitls_free_env((coap_hitls_env_t *)session->tls);
2771 session->tls = NULL;
2773 }
2774}
2775
2776void
2778 if (session)
2779 coap_hitls_update_mtu((coap_hitls_env_t *)session->tls);
2780}
2781
2782ssize_t
2783coap_dtls_send(coap_session_t *session, const uint8_t *data, size_t data_len) {
2784 coap_hitls_env_t *env = (coap_hitls_env_t *)session->tls;
2785 uint32_t written = 0;
2786 int32_t ret;
2787
2788 if (!env || data_len > UINT32_MAX)
2789 return -1;
2790
2791 session->dtls_event = -1;
2792 coap_log_debug("* %s: dtls: sent %4d bytes\n",
2793 coap_session_str(session), (int)data_len);
2794 if (!env->established) {
2795 ret = coap_hitls_handshake(session, env);
2796 if (ret == 1)
2797 return coap_dtls_send(session, data, data_len);
2798 return ret == 0 ? 0 : -1;
2799 }
2800
2801 BSL_ERR_ClearError();
2802 ret = HITLS_Write(env->ctx, data, (uint32_t)data_len, &written);
2803 if (ret == HITLS_SUCCESS) {
2804 if (written == 0)
2805 return 0;
2806 return (ssize_t)written;
2807 }
2808 if (coap_hitls_is_retry(ret))
2809 return 0;
2810
2811 session->dtls_event = coap_hitls_is_closed(ret) ?
2813 if (session->dtls_event == COAP_EVENT_DTLS_ERROR) {
2814 coap_log_warn("coap_dtls_send: returned 0x%x\n", (unsigned int)ret);
2815 coap_hitls_log_fatal_err_stack(session);
2816 }
2817 coap_handle_event_lkd(session->context, session->dtls_event, session);
2818 return -1;
2819}
2820
2821int
2823 return 0;
2824}
2825
2827coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED) {
2828 return 0;
2829}
2830
2833 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
2834 uint64_t timeout_us = 0;
2835 int32_t ret;
2836
2837 if (!env)
2838 return 0;
2839 ret = HITLS_DtlsGetTimeout(env->ctx, &timeout_us);
2840 if (ret == HITLS_MSG_HANDLE_ERR_WITHOUT_TIMEOUT_ACTION)
2841 return 0;
2842 if (ret != HITLS_SUCCESS) {
2843 coap_log_warn("HITLS_DtlsGetTimeout() returned 0x%x\n",
2844 (unsigned int)ret);
2845 return 0;
2846 }
2847 if (timeout_us == 0) {
2848 /*
2849 * Timer already due: pace it so one I/O cycle does not fire DTLS timeouts
2850 * back-to-back and exhaust dtls_timeout_count prematurely.
2851 */
2852 if (env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS > now)
2853 return env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS;
2854 env->last_timeout = now;
2855 return now;
2856 }
2857 return now + (coap_tick_t)((timeout_us * COAP_TICKS_PER_SECOND + 999999) /
2858 1000000);
2859}
2860
2861int
2863 coap_hitls_env_t *env = (coap_hitls_env_t *)session->tls;
2864 int32_t ret;
2865
2866 if (!env)
2867 return 1;
2868 if (++session->dtls_timeout_count > session->max_retransmit) {
2870 return 1;
2871 }
2872
2873 BSL_ERR_ClearError();
2874 ret = HITLS_DtlsProcessTimeout(env->ctx);
2875 if (ret == HITLS_SUCCESS ||
2876 ret == HITLS_MSG_HANDLE_DTLS_RETRANSMIT_NOT_TIMEOUT ||
2877 coap_hitls_is_retry(ret))
2878 return 0;
2879
2880 coap_log_warn("HITLS_DtlsProcessTimeout() returned 0x%x\n",
2881 (unsigned int)ret);
2882 coap_hitls_log_fatal_err_stack(session);
2884 return 1;
2885}
2886
2887int
2888coap_dtls_receive(coap_session_t *session, const uint8_t *data,
2889 size_t data_len) {
2890 coap_hitls_env_t *env = (coap_hitls_env_t *)session->tls;
2891 int ret = -1;
2892
2893 if (!env)
2894 return -1;
2895 if (env->pdu_len)
2896 coap_log_err("** %s: Previous data not read %" PRIuS " bytes\n",
2897 coap_session_str(session), env->pdu_len);
2898
2899 session->dtls_event = -1;
2900 env->pdu = data;
2901 env->pdu_len = data_len;
2902
2903 if (env->established) {
2904#if COAP_CONSTRAINED_STACK
2905 static uint8_t pdu[COAP_RXBUFFER_SIZE];
2906#else /* ! COAP_CONSTRAINED_STACK */
2907 uint8_t pdu[COAP_RXBUFFER_SIZE];
2908#endif /* ! COAP_CONSTRAINED_STACK */
2909 uint32_t read_len = 0;
2910 int32_t hret;
2911
2912 BSL_ERR_ClearError();
2913 hret = HITLS_Read(env->ctx, pdu, sizeof(pdu), &read_len);
2914
2915 if (hret == HITLS_SUCCESS && read_len > 0) {
2916 coap_log_debug("* %s: dtls: recv %4d bytes\n",
2917 coap_session_str(session), (int)read_len);
2918 ret = coap_handle_dgram(session->context, session, pdu, read_len);
2919 goto finish;
2920 }
2921 if (hret == HITLS_SUCCESS || coap_hitls_is_retry(hret)) {
2922 ret = -1;
2923 goto finish;
2924 }
2925 session->dtls_event = coap_hitls_is_closed(hret) ?
2927 if (session->dtls_event == COAP_EVENT_DTLS_ERROR) {
2928 coap_log_warn("coap_dtls_receive: returned 0x%x (length %" PRIdS ")\n",
2929 (unsigned int)hret, data_len);
2930 coap_hitls_log_fatal_err_stack(session);
2931 }
2932 } else {
2933 /*
2934 * On completion coap_hitls_set_connected() drives l_establish(); on error
2935 * session->dtls_event is set and handled below, so the handshake return
2936 * value is not needed here.
2937 */
2938 (void)coap_hitls_handshake(session, env);
2939 ret = -1;
2940 }
2941
2942 if (session->dtls_event >= 0) {
2943 coap_handle_event_lkd(session->context, session->dtls_event, session);
2944 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2945 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2947 ret = -1;
2948 }
2949 }
2950
2951finish:
2952 coap_hitls_clear_pdu(coap_hitls_live_env(session, env));
2953 return ret;
2954}
2955
2956#if COAP_SERVER_SUPPORT
2957int
2958coap_dtls_hello(coap_session_t *session, const uint8_t *data,
2959 size_t data_len) {
2960 coap_hitls_env_t *env = (coap_hitls_env_t *)session->tls;
2961 int32_t ret;
2962 int cookie_valid = 0;
2963
2964 if (!env) {
2965 env = coap_hitls_new_env(session, COAP_DTLS_ROLE_SERVER, COAP_PROTO_DTLS);
2966 if (!env)
2967 return -1;
2968 session->tls = env;
2969 }
2970
2971 env->pdu = data;
2972 env->pdu_len = data_len;
2973
2974 if (!env->hello_verify_sent) {
2975 BSL_ERR_ClearError();
2976 ret = HITLS_Listen(env->ctx, &session->addr_info.remote.addr.sa);
2977 if (env->pdu_len) {
2978 coap_log_debug("coap_dtls_hello: ret 0x%x: remaining data %" PRIuS "\n",
2979 (unsigned int)ret, env->pdu_len);
2980 }
2981 coap_hitls_clear_pdu(env);
2982
2983 if (ret == HITLS_SUCCESS)
2984 return 1;
2985 if (coap_hitls_is_retry(ret)) {
2986 /* HITLS_Listen emits HelloVerifyRequest; Accept flushes it. */
2987 ret = coap_hitls_handshake(session, env);
2988 if (ret < 0)
2989 return -1;
2990 env = coap_hitls_live_env(session, env);
2991 if (!env)
2992 return -1;
2993 env->hello_verify_sent = 1;
2994 return 0;
2995 }
2996
2997 coap_log_warn("coap_dtls_hello: returned 0x%x\n", (unsigned int)ret);
2998 coap_hitls_log_fatal_err_stack(session);
3000 return -1;
3001 }
3002
3003 cookie_valid = coap_hitls_client_hello_cookie_valid(session, data, data_len);
3004 ret = coap_hitls_handshake(session, env);
3005 env = coap_hitls_live_env(session, env);
3006 coap_hitls_clear_pdu(env);
3007
3008 if (ret < 0 || !env)
3009 return -1;
3010 return cookie_valid == 1 ? 1 : 0;
3011}
3012#endif /* COAP_SERVER_SUPPORT */
3013
3014unsigned int
3016 return COAP_HITLS_DTLS_OVERHEAD;
3017}
3018
3019#if !COAP_DISABLE_TCP
3020#if COAP_CLIENT_SUPPORT
3021void *
3022coap_tls_new_client_session(coap_session_t *session) {
3023 coap_hitls_env_t *env =
3024 coap_hitls_new_env(session, COAP_DTLS_ROLE_CLIENT, COAP_PROTO_TLS);
3025
3026 session->tls = env;
3027 if (env && coap_hitls_handshake(session, env) < 0) {
3028 coap_hitls_free_env(env);
3029 session->tls = NULL;
3030 return NULL;
3031 }
3032 return env;
3033}
3034#endif /* COAP_CLIENT_SUPPORT */
3035
3036#if COAP_SERVER_SUPPORT
3037void *
3038coap_tls_new_server_session(coap_session_t *session) {
3039 coap_hitls_env_t *env =
3040 coap_hitls_new_env(session, COAP_DTLS_ROLE_SERVER, COAP_PROTO_TLS);
3041
3042 session->tls = env;
3043 if (env && coap_hitls_handshake(session, env) < 0) {
3044 coap_hitls_free_env(env);
3045 session->tls = NULL;
3046 return NULL;
3047 }
3048 return env;
3049}
3050#endif /* COAP_SERVER_SUPPORT */
3051
3052void
3054 coap_dtls_free_session(session);
3055}
3056
3057static void
3058coap_hitls_tcp_want(coap_session_t *session, HITLS_Ctx *ctx) {
3059 uint8_t rwstate = HITLS_NOTHING;
3060
3061 (void)HITLS_GetRwstate(ctx, &rwstate);
3062 if (rwstate == HITLS_WRITING) {
3063 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3064#ifdef COAP_EPOLL_SUPPORT
3065 coap_epoll_ctl_mod(&session->sock,
3066 EPOLLOUT |
3067 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3068 EPOLLIN : 0),
3069 __func__);
3070#endif /* COAP_EPOLL_SUPPORT */
3071 } else {
3072 session->sock.flags |= COAP_SOCKET_WANT_READ;
3073 }
3074}
3075
3076ssize_t
3078 const uint8_t *data,
3079 size_t data_len) {
3080 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
3081 uint32_t written = 0;
3082 int32_t ret;
3083
3084 if (!env || data_len > UINT32_MAX) {
3085 errno = ENXIO;
3086 return -1;
3087 }
3088
3089 session->dtls_event = -1;
3090 if (!env->established) {
3091 ret = coap_hitls_handshake(session, env);
3092 if (ret < 0)
3093 return -1;
3094 if (ret == 0)
3095 coap_hitls_tcp_want(session, env->ctx);
3096 return 0;
3097 }
3098
3099 BSL_ERR_ClearError();
3100 ret = HITLS_Write(env->ctx, data, (uint32_t)data_len, &written);
3101 if (ret == HITLS_SUCCESS) {
3102 if (written > 0) {
3103 if (written == data_len)
3104 coap_log_debug("* %s: tls: sent %4d bytes\n",
3105 coap_session_str(session), (int)written);
3106 else
3107 coap_log_debug("* %s: tls: sent %4d of %4" PRIdS " bytes\n",
3108 coap_session_str(session), (int)written, data_len);
3109 }
3110 return (ssize_t)written;
3111 }
3112 if (coap_hitls_is_retry(ret)) {
3113 coap_hitls_tcp_want(session, env->ctx);
3114 return 0;
3115 }
3116
3117 session->dtls_event = coap_hitls_is_closed(ret) ?
3119 if (session->dtls_event == COAP_EVENT_DTLS_ERROR) {
3120 coap_log_warn("coap_tls_write: returned 0x%x\n", (unsigned int)ret);
3121 coap_hitls_log_fatal_err_stack(session);
3122 }
3123 coap_handle_event_lkd(session->context, session->dtls_event, session);
3124 return -1;
3125}
3126
3127ssize_t
3129 uint8_t *data,
3130 size_t data_len) {
3131 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
3132 uint32_t read_len = 0;
3133 int32_t ret;
3134
3135 if (!env || data_len > UINT32_MAX) {
3136 errno = ENXIO;
3137 return -1;
3138 }
3139
3140 session->dtls_event = -1;
3141 if (!env->established) {
3142 ret = coap_hitls_handshake(session, env);
3143 if (ret < 0)
3144 return -1;
3145 if (ret == 0)
3146 coap_hitls_tcp_want(session, env->ctx);
3147 return 0;
3148 }
3149
3150 BSL_ERR_ClearError();
3151 ret = HITLS_Read(env->ctx, data, (uint32_t)data_len, &read_len);
3152 if (ret == HITLS_SUCCESS) {
3153 if (read_len > 0)
3154 coap_log_debug("* %s: tls: recv %4d bytes\n",
3155 coap_session_str(session), (int)read_len);
3156 return (ssize_t)read_len;
3157 }
3158 if (coap_hitls_is_retry(ret)) {
3159 coap_hitls_tcp_want(session, env->ctx);
3160 errno = EAGAIN;
3161 return 0;
3162 }
3163
3164 session->dtls_event = coap_hitls_is_closed(ret) ?
3166 if (session->dtls_event == COAP_EVENT_DTLS_ERROR) {
3167 coap_log_warn("coap_tls_read: returned 0x%x (length %" PRIdS ")\n",
3168 (unsigned int)ret, data_len);
3169 coap_hitls_log_fatal_err_stack(session);
3170 }
3171 coap_handle_event_lkd(session->context, session->dtls_event, session);
3172 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3175 return -1;
3176}
3177#endif /* !COAP_DISABLE_TCP */
3178#endif /* COAP_WITH_LIBOPENHITLS */
3179
3180#endif /* COAP_WITH_LIBOPENHITLS || COAP_WITH_LIBOPENHITLS_OSCORE */
static void dummy(void)
struct coap_context_t coap_context_t
struct coap_session_t coap_session_t
#define COAP_SERVER_SUPPORT
#define PRIuS
#define PRIdS
#define COAP_RXBUFFER_SIZE
Definition coap_io.h:31
@ COAP_NACK_TLS_FAILED
Definition coap_io.h:68
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
#define COAP_SOCKET_WANT_WRITE
non blocking socket is waiting for writing
void coap_epoll_ctl_mod(coap_socket_t *sock, uint32_t events, const char *func)
Epoll specific function to modify the state of events that epoll is tracking on the appropriate file ...
@ COAP_LAYER_TLS
Library specific build wrapper for coap_internal.h.
@ COAP_STRING
Definition coap_mem.h:33
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
int coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, const coap_dtls_pki_t *setup_data COAP_UNUSED, const coap_dtls_role_t role COAP_UNUSED)
Definition coap_notls.c:258
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition coap_notls.c:370
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:442
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition coap_notls.c:365
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:384
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition coap_notls.c:304
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:402
int coap_dtls_context_load_pki_trust_store(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:274
static coap_log_t dtls_log_level
Definition coap_notls.c:301
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:297
ssize_t coap_dtls_send(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:353
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:430
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:349
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:266
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:379
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition coap_notls.c:327
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:345
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition coap_notls.c:322
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:421
#define NULL
Definition coap_option.h:30
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:149
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition coap_time.h:164
int coap_prng_lkd(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition coap_prng.c:192
int coap_handle_event_lkd(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
Definition coap_net.c:5202
int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *msg, size_t msg_len)
Parses and interprets a CoAP datagram with context ctx.
Definition coap_net.c:3097
int coap_crypto_hmac(cose_hmac_alg_t hmac_alg, coap_bin_const_t *key, coap_bin_const_t *data, coap_bin_const_t **hmac)
Create a HMAC hash of the provided data.
int coap_crypto_aead_decrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Decrypt the provided encrypted data into plaintext.
int coap_crypto_aead_encrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Encrypt the provided plaintext data.
int coap_crypto_hash(cose_alg_t alg, const coap_bin_const_t *data, coap_bin_const_t **hash)
Create a hash of the provided data.
int coap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg)
Check whether the defined hkdf algorithm is supported by the underlying crypto library.
int coap_crypto_check_cipher_alg(cose_alg_t alg)
Check whether the defined cipher algorithm is supported by the underlying crypto library.
const coap_bin_const_t * coap_get_session_client_psk_identity(const coap_session_t *coap_session)
Get the current client's PSK identity.
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition coap_notls.c:109
int coap_dtls_define_issue(coap_define_issue_key_t type, coap_define_issue_fail_t fail, coap_dtls_key_t *key, const coap_dtls_role_t role, int ret)
Report PKI DEFINE type issue.
Definition coap_dtls.c:159
coap_define_issue_key_t
int coap_pki_name_match_sni(const char *name_entry, size_t name_length, const char *sni_match)
Check if the PKI name entry is a (wildcard) match for the requested SNI.
Definition coap_dtls.c:288
void coap_dtls_thread_shutdown(void)
Close down the underlying (D)TLS Library layer.
Definition coap_notls.c:118
int coap_dtls_set_cid_tuple_change(coap_context_t *context, uint8_t every)
Set the Connection ID client tuple frequency change for testing CIDs.
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition coap_notls.c:360
void coap_dtls_shutdown(void)
Close down the underlying (D)TLS Library layer.
Definition coap_notls.c:113
const coap_bin_const_t * coap_get_session_client_psk_key(const coap_session_t *coap_session)
Get the current client's PSK key.
#define COAP_DTLS_RETRANSMIT_COAP_TICKS
void coap_dtls_map_key_type_to_define(const coap_dtls_pki_t *setup_data, coap_dtls_key_t *key)
Map the PKI key definitions to the new DEFINE format.
Definition coap_dtls.c:26
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_DEFINE_KEY_PRIVATE
@ COAP_DEFINE_KEY_CA
@ COAP_DEFINE_KEY_PUBLIC
@ COAP_DEFINE_FAIL_NOT_SUPPORTED
@ COAP_DEFINE_FAIL_BAD
coap_pki_define_t
The enum to define the format of the key parameter definition.
Definition coap_dtls.h:238
#define COAP_DTLS_MAX_PSK_IDENTITY
Definition coap_dtls.h:42
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:101
coap_dtls_role_t
Definition coap_dtls.h:48
coap_tls_library_t
Definition coap_dtls.h:74
struct coap_dtls_pki_t coap_dtls_pki_t
Definition coap_dtls.h:36
@ COAP_PKI_KEY_DEF_PKCS11
The PKI key type is PKCS11 (pkcs11:...).
Definition coap_dtls.h:250
@ COAP_PKI_KEY_DEF_DER_BUF
The PKI key type is DER buffer (ASN.1).
Definition coap_dtls.h:247
@ COAP_PKI_KEY_DEF_PEM_BUF
The PKI key type is PEM buffer.
Definition coap_dtls.h:241
@ COAP_PKI_KEY_DEF_PEM
The PKI key type is PEM file.
Definition coap_dtls.h:239
@ COAP_PKI_KEY_DEF_ENGINE
The PKI key type is to be passed to ENGINE.
Definition coap_dtls.h:256
@ COAP_PKI_KEY_DEF_RPK_BUF
The PKI key type is RPK in buffer.
Definition coap_dtls.h:243
@ COAP_PKI_KEY_DEF_DER
The PKI key type is DER file.
Definition coap_dtls.h:245
@ COAP_PKI_KEY_DEF_PKCS11_RPK
The PKI key type is PKCS11 w/ RPK (pkcs11:...).
Definition coap_dtls.h:253
@ COAP_DTLS_ROLE_SERVER
Internal function invoked for server.
Definition coap_dtls.h:50
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
Definition coap_dtls.h:49
@ COAP_PKI_KEY_PKCS11
The PKI key type is PKCS11 (DER).
Definition coap_dtls.h:176
@ COAP_PKI_KEY_DEFINE
The individual PKI key types are Definable.
Definition coap_dtls.h:177
@ COAP_TLS_LIBRARY_OPENHITLS
Using openHiTLS library.
Definition coap_dtls.h:81
@ COAP_EVENT_DTLS_CLOSED
Triggerred when (D)TLS session closed.
Definition coap_event.h:41
@ COAP_EVENT_DTLS_CONNECTED
Triggered when (D)TLS session connected.
Definition coap_event.h:43
@ COAP_EVENT_DTLS_ERROR
Triggered when (D)TLS error occurs.
Definition coap_event.h:47
#define coap_lock_callback_ret(r, func)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:126
coap_log_t
Logging type.
Definition coap_debug.h:56
coap_log_t coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition coap_notls.c:317
#define coap_dtls_log(level,...)
Logging function.
Definition coap_debug.h:306
void coap_dtls_set_log_level(coap_log_t level)
Sets the (D)TLS logging level to the specified level.
Definition coap_notls.c:312
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
Definition coap_debug.h:114
#define coap_log_warn(...)
Definition coap_debug.h:108
#define coap_log_err(...)
Definition coap_debug.h:102
@ COAP_LOG_EMERG
Definition coap_debug.h:57
@ COAP_LOG_WARN
Definition coap_debug.h:61
int coap_netif_available(coap_session_t *session)
Function interface to check whether netif for session is still available.
Definition coap_netif.c:25
#define COSE_ALGORITHM_HMAC384_384_HASH_LEN
#define COSE_ALGORITHM_HMAC512_512_HASH_LEN
int cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg)
cose_hkdf_alg_t
#define COSE_ALGORITHM_HMAC256_256_HASH_LEN
cose_hmac_alg_t
cose_alg_t
@ COSE_HMAC_ALG_HMAC384_384
@ COSE_HMAC_ALG_HMAC256_256
@ COSE_HMAC_ALG_HMAC512_512
@ COSE_ALGORITHM_SHA_256_64
@ COSE_ALGORITHM_SHA_256_256
@ COSE_ALGORITHM_SHA_1
@ COSE_ALGORITHM_AES_CCM_16_64_128
@ COSE_ALGORITHM_SHA_512
@ COSE_ALGORITHM_AES_CCM_16_64_256
coap_proto_t
CoAP protocol types Note: coap_layers_coap[] needs updating if extended.
Definition coap_pdu.h:234
@ COAP_PROTO_DTLS
Definition coap_pdu.h:237
@ COAP_PROTO_TLS
Definition coap_pdu.h:239
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
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_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
#define COAP_PROTO_NOT_RELIABLE(p)
@ COAP_SESSION_TYPE_CLIENT
client-side
@ COAP_SESSION_STATE_HANDSHAKE
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition coap_str.c:81
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition coap_str.c:114
int coap_dtls_cid_is_supported(void)
Check whether (D)TLS CID is available.
Definition coap_notls.c:86
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition coap_notls.c:50
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition coap_notls.c:41
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition coap_notls.c:36
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition coap_notls.c:59
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition coap_notls.c:77
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition coap_notls.c:68
#define COAP_UNUSED
Definition libcoap.h:74
coap_address_t remote
remote address and port
Definition coap_io.h:58
coap_address_t local
local address and port
Definition coap_io.h:59
socklen_t size
size of addr
struct sockaddr sa
union coap_address_t::@250171263277076317333044054015357360100234370325 addr
CoAP binary data definition with const data.
Definition coap_str.h:65
size_t length
length of binary data
Definition coap_str.h:66
const uint8_t * s
read-only binary data
Definition coap_str.h:67
CoAP binary data definition.
Definition coap_str.h:57
size_t length
length of binary data
Definition coap_str.h:58
uint8_t * s
binary data
Definition coap_str.h:59
The CoAP stack's global state is stored in a coap_context_t object.
The structure that holds the AES Crypto information.
size_t l
The number of bytes in the length field.
const uint8_t * nonce
must be exactly 15 - l bytes
coap_crypto_key_t key
The Key to use.
size_t tag_len
The size of the Tag.
The common structure that holds the Crypto information.
union coap_crypto_param_t::@157113072004166322362146125210066265265052014356 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
cose_alg_t alg
The COSE algorith to use.
The structure that holds the Client PSK information.
Definition coap_dtls.h:387
coap_bin_const_t key
Definition coap_dtls.h:389
coap_bin_const_t identity
Definition coap_dtls.h:388
The structure used for defining the Client PSK setup data to be used.
Definition coap_dtls.h:418
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition coap_dtls.h:442
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:445
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition coap_dtls.h:441
The structure that holds the PKI key information.
Definition coap_dtls.h:284
coap_pki_key_define_t define
for definable type keys
Definition coap_dtls.h:291
union coap_dtls_key_t::@347061073371360224072225335172343174030036152126 key
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:285
The structure used for defining the PKI setup data to be used.
Definition coap_dtls.h:317
uint8_t allow_no_crl
1 ignore if CRL not there
Definition coap_dtls.h:331
void * cn_call_back_arg
Passed in to the CN callback function.
Definition coap_dtls.h:359
uint8_t allow_sni_cn_mismatch
1 if SNI and returnd CN allowed to mismatch (Client only).
Definition coap_dtls.h:341
uint8_t cert_chain_validation
1 if to check cert_chain_verify_depth
Definition coap_dtls.h:328
uint8_t use_cid
1 if DTLS Connection ID is to be used (Client only, server always enabled) if supported
Definition coap_dtls.h:338
uint8_t check_cert_revocation
1 if revocation checks wanted
Definition coap_dtls.h:330
coap_dtls_pki_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:366
uint8_t cert_chain_verify_depth
recommended depth is 3
Definition coap_dtls.h:329
uint8_t allow_expired_certs
1 if expired certs are allowed
Definition coap_dtls.h:327
uint8_t verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:322
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:376
uint8_t allow_self_signed
1 if self-signed certs are allowed.
Definition coap_dtls.h:325
void * sni_call_back_arg
Passed in to the sni callback function.
Definition coap_dtls.h:367
coap_dtls_cn_callback_t validate_cn_call_back
CN check callback function.
Definition coap_dtls.h:358
uint8_t allow_expired_crl
1 if expired crl is allowed
Definition coap_dtls.h:332
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition coap_dtls.h:335
uint8_t check_common_ca
1 if peer cert is to be signed by the same CA as the local cert
Definition coap_dtls.h:323
coap_dtls_key_t pki_key
PKI key definition.
Definition coap_dtls.h:381
The structure that holds the Server Pre-Shared Key and Identity Hint information.
Definition coap_dtls.h:458
coap_bin_const_t hint
Definition coap_dtls.h:459
coap_bin_const_t key
Definition coap_dtls.h:460
The structure used for defining the Server PSK setup data to be used.
Definition coap_dtls.h:509
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:538
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition coap_dtls.h:530
void * id_call_back_arg
Passed in to the Identity callback function.
Definition coap_dtls.h:531
void * sni_call_back_arg
Passed in to the SNI callback function.
Definition coap_dtls.h:539
coap_layer_establish_t l_establish
The structure that holds the PKI Definable key type definitions.
Definition coap_dtls.h:264
coap_const_char_ptr_t public_cert
define: Public Cert
Definition coap_dtls.h:266
coap_const_char_ptr_t private_key
define: Private Key
Definition coap_dtls.h:267
coap_const_char_ptr_t ca
define: Common CA Certificate
Definition coap_dtls.h:265
size_t public_cert_len
define Public Cert length (if needed)
Definition coap_dtls.h:269
size_t ca_len
define CA Cert length (if needed)
Definition coap_dtls.h:268
coap_pki_define_t private_key_def
define: Private Key type definition
Definition coap_dtls.h:273
size_t private_key_len
define Private Key length (if needed)
Definition coap_dtls.h:270
coap_pki_define_t ca_def
define: Common CA type definition
Definition coap_dtls.h:271
coap_pki_define_t public_cert_def
define: Public Cert type definition
Definition coap_dtls.h:272
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
unsigned int dtls_timeout_count
dtls setup retry counter
coap_socket_t sock
socket object for the session, if any
coap_session_state_t state
current state of relationship with peer
coap_addr_tuple_t addr_info
remote/local address info
coap_proto_t proto
protocol used
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
int dtls_event
Tracking any (D)TLS events on this session.
void * tls
security parameters
uint16_t max_retransmit
maximum re-transmit count (default 4)
coap_session_type_t type
client or server side socket
coap_context_t * context
session's context
coap_layer_func_t lfunc[COAP_LAYER_LAST]
Layer functions to use.
coap_socket_flags_t flags
1 or more of COAP_SOCKET* flag values
CoAP string data definition with const data.
Definition coap_str.h:47
const uint8_t * s
read-only string data
Definition coap_str.h:49
size_t length
length of string
Definition coap_str.h:48
The structure used for returning the underlying (D)TLS library information.
Definition coap_dtls.h:88
uint64_t built_version
(D)TLS Built against Library Version
Definition coap_dtls.h:91
coap_tls_library_t type
Library type.
Definition coap_dtls.h:90
uint64_t version
(D)TLS runtime Library Version
Definition coap_dtls.h:89
const char * s_byte
signed char ptr
Definition coap_str.h:84
const uint8_t * u_byte
unsigned char ptr
Definition coap_str.h:85