libcoap 4.3.5-develop-e2463f0
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(HITLS_X509_Cert *cert) {
809 HITLS_X509_ExtSan san = {0};
810 char *dns_name = NULL;
811
812 if (HITLS_X509_CertCtrl(cert, HITLS_X509_EXT_GET_SAN, &san,
813 sizeof(san)) == HITLS_PKI_SUCCESS &&
814 san.names) {
815 for (BslListNode *name_node = BSL_LIST_FirstNode(san.names);
816 name_node != NULL;
817 name_node = BSL_LIST_GetNextNode(san.names, name_node)) {
818 const HITLS_X509_GeneralName *name =
819 (const HITLS_X509_GeneralName *)BSL_LIST_GetData(name_node);
820
821 if (!name || name->type != HITLS_X509_GN_DNS)
822 continue;
823 if (name->value.dataLen &&
824 memchr(name->value.data, '\000', name->value.dataLen))
825 continue;
826 dns_name = coap_hitls_copy_name(name->value.data, name->value.dataLen);
827 break;
828 }
829 }
830
831 HITLS_X509_ClearSubjectAltName(&san);
832 return dns_name;
833}
834
835static char *
836coap_hitls_get_cn_from_cert(HITLS_X509_Cert *cert) {
837 BSL_Buffer cn = {0};
838 char *cn_name = NULL;
839
840 if (HITLS_X509_CertCtrl(cert, HITLS_X509_GET_SUBJECT_CN_STR,
841 &cn, sizeof(cn)) == HITLS_PKI_SUCCESS) {
842 cn_name = coap_hitls_copy_name(cn.data, cn.dataLen);
843 }
844 if (cn.data)
845 BSL_SAL_Free(cn.data);
846 return cn_name;
847}
848
849static char *
850coap_hitls_get_san_or_cn_from_cert(HITLS_X509_Cert *cert) {
851 char *name;
852
853 if (!cert)
854 return NULL;
855 name = coap_hitls_get_san_from_cert(cert);
856 if (name)
857 return name;
858 return coap_hitls_get_cn_from_cert(cert);
859}
860
861static int
862coap_hitls_validate_cn_cert(coap_session_t *session,
863 const coap_dtls_pki_t *setup_data,
864 HITLS_X509_Cert *cert,
865 unsigned depth,
866 int validated) {
867 uint8_t *der = NULL;
868 uint32_t der_len = 0;
869 char *san_or_cn;
870 int ret = 1;
871
872 (void)HITLS_X509_CertCtrl(cert, HITLS_X509_GET_ENCODELEN,
873 &der_len, sizeof(der_len));
874 if (der_len)
875 (void)HITLS_X509_CertCtrl(cert, HITLS_X509_GET_ENCODE,
876 &der, sizeof(der));
877 san_or_cn = coap_hitls_get_san_or_cn_from_cert(cert);
878
879 if (setup_data->validate_cn_call_back) {
881 setup_data->validate_cn_call_back(
882 san_or_cn ? san_or_cn : "",
883 der, der_len, session, depth, validated,
884 setup_data->cn_call_back_arg));
885 }
886 if (depth == 0 && session->type == COAP_SESSION_TYPE_CLIENT &&
887 setup_data->client_sni && !setup_data->allow_sni_cn_mismatch &&
888 san_or_cn && strcmp(san_or_cn, setup_data->client_sni)) {
889 ret = 0;
890 }
891 if (san_or_cn)
892 coap_free_type(COAP_STRING, san_or_cn);
893 return ret;
894}
895
896static int
897coap_hitls_verify_cb(int32_t err_code, HITLS_CERT_StoreCtx *store_ctx) {
898 coap_session_t *session = NULL;
899 coap_hitls_context_t *context;
900 coap_dtls_pki_t *setup_data;
901 HITLS_X509_Cert *cert;
902 int32_t depth;
903 int allowed;
904
905 if (!coap_hitls_get_verify_session(store_ctx, &session) ||
906 !session->context || !session->context->dtls_context)
907 return err_code;
908
909 context = (coap_hitls_context_t *)session->context->dtls_context;
910 setup_data = &context->setup_data;
911 if (err_code == HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND ||
912 err_code == HITLS_X509_ERR_ROOT_CERT_NOT_FOUND) {
913 allowed = coap_hitls_verify_cb_self_signed_allowed(setup_data,
914 store_ctx);
915 } else {
916 allowed = coap_hitls_verify_error_allowed(setup_data, err_code);
917 }
918 if (!allowed) {
919 coap_log_warn("* %s: certificate verification failed: %s (0x%x)\n",
920 coap_session_str(session),
921 coap_hitls_verify_err_str(err_code), (unsigned int)err_code);
922 return err_code;
923 }
924
925 if (setup_data->validate_cn_call_back &&
926 coap_hitls_get_verify_cert(store_ctx, &cert, &depth)) {
927 if (!coap_hitls_validate_cn_cert(session, setup_data, cert,
928 depth < 0 ? 0 : (unsigned)depth,
929 err_code == HITLS_PKI_SUCCESS)) {
930 coap_log_warn("* %s: certificate verification failed: %s\n",
931 coap_session_str(session),
932 coap_hitls_verify_err_str(HITLS_X509_ERR_VFY_HOSTNAME_FAIL));
933 return HITLS_X509_ERR_VFY_HOSTNAME_FAIL;
934 }
935 }
936
937 return HITLS_PKI_SUCCESS;
938}
939
940static int32_t
941coap_hitls_app_verify_cb(HITLS_CERT_StoreCtx *store_ctx,
942 void *arg COAP_UNUSED) {
943 coap_session_t *session = NULL;
944 coap_hitls_context_t *context;
945 coap_dtls_pki_t *setup_data;
946 HITLS_X509_List *peer_chain = NULL;
947 HITLS_X509_Cert *leaf_cert = NULL;
948 int32_t ret;
949
950 if (!coap_hitls_get_verify_session(store_ctx, &session) ||
951 !session->context || !session->context->dtls_context)
952 return HITLS_X509_ERR_INVALID_PARAM;
953
954 if (HITLS_X509_StoreCtxCtrl((HITLS_X509_StoreCtx *)store_ctx,
955 HITLS_X509_STORECTX_GET_PEER_CERT_CHAIN,
956 &peer_chain,
957 sizeof(peer_chain)) != HITLS_PKI_SUCCESS ||
958 !peer_chain)
959 return HITLS_X509_ERR_INVALID_PARAM;
960
961 ret = HITLS_X509_CertVerify((HITLS_X509_StoreCtx *)store_ctx, peer_chain);
962 if (ret == HITLS_PKI_SUCCESS)
963 return HITLS_APP_VERIFY_CALLBACK_SUCCESS;
964
965 context = (coap_hitls_context_t *)session->context->dtls_context;
966 setup_data = &context->setup_data;
967 if ((ret == HITLS_X509_ERR_ISSUE_CERT_NOT_FOUND ||
968 ret == HITLS_X509_ERR_ROOT_CERT_NOT_FOUND) &&
969 coap_hitls_self_signed_leaf_allowed(setup_data, store_ctx,
970 &leaf_cert)) {
971 if (!setup_data->allow_expired_certs) {
972 int32_t time_ret = coap_hitls_cert_time_valid(leaf_cert);
973
974 if (time_ret != HITLS_PKI_SUCCESS) {
975 coap_log_warn("* %s: certificate verification failed: %s\n",
976 coap_session_str(session),
977 coap_hitls_verify_err_str(time_ret));
978 return time_ret;
979 }
980 }
981 coap_log_info(" %s: %s: overridden: 'self-signed' depth=0\n",
982 coap_session_str(session),
983 coap_hitls_verify_err_str(ret));
984 if (!coap_hitls_validate_cn_cert(session, setup_data, leaf_cert, 0, 0))
985 return HITLS_X509_ERR_VFY_HOSTNAME_FAIL;
986 return HITLS_APP_VERIFY_CALLBACK_SUCCESS;
987 }
988
989 return ret;
990}
991
992static int
993coap_hitls_is_retry(int32_t ret) {
994 switch (ret) {
995 case HITLS_WANT_CONNECT:
996 case HITLS_WANT_ACCEPT:
997 case HITLS_WANT_READ:
998 case HITLS_WANT_WRITE:
999 case HITLS_WANT_BACKUP:
1000 case HITLS_WANT_CLIENT_HELLO_CB:
1001 case HITLS_WANT_X509_LOOKUP:
1002 case HITLS_REC_NORMAL_IO_BUSY:
1003 case HITLS_REC_NORMAL_RECV_BUF_EMPTY:
1004 return 1;
1005 default:
1006 return 0;
1007 }
1008}
1009
1010static int
1011coap_hitls_is_closed(int32_t ret) {
1012 return ret == HITLS_CM_LINK_CLOSED;
1013}
1014
1015static uint8_t
1016coap_hitls_udp_overhead(const coap_hitls_env_t *env) {
1017#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
1018 if (env && env->session) {
1019 switch (env->session->addr_info.remote.addr.sa.sa_family) {
1020#ifdef AF_INET6
1021 case AF_INET6:
1022 return COAP_HITLS_IPV6_UDP_OVERHEAD;
1023#endif /* AF_INET6 */
1024#ifdef AF_INET
1025 case AF_INET:
1026#endif /* AF_INET */
1027 default:
1028 break;
1029 }
1030 }
1031#else /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
1032 (void)env;
1033#endif /* WITH_LWIP || WITH_CONTIKI || RIOT_VERSION */
1034 return COAP_HITLS_IPV4_UDP_OVERHEAD;
1035}
1036
1037static void
1038coap_hitls_set_connected(coap_session_t *session, coap_hitls_env_t *env) {
1039 if (env->established)
1040 return;
1041
1042 env->established = 1;
1043 if (session->state == COAP_SESSION_STATE_HANDSHAKE) {
1045 session);
1046 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
1047 }
1048}
1049
1050static int
1051coap_hitls_check_handshake_done(coap_session_t *session,
1052 coap_hitls_env_t *env) {
1053 uint8_t done = 0;
1054
1055 if (HITLS_IsHandShakeDone(env->ctx, &done) == HITLS_SUCCESS && done) {
1056 coap_hitls_set_connected(session, env);
1057 return 1;
1058 }
1059 return 0;
1060}
1061
1062static int
1063coap_hitls_handshake(coap_session_t *session, coap_hitls_env_t *env) {
1064 int32_t ret;
1065
1066 BSL_ERR_ClearError();
1067 if (env->role == COAP_DTLS_ROLE_CLIENT)
1068 ret = HITLS_Connect(env->ctx);
1069 else
1070 ret = HITLS_Accept(env->ctx);
1071
1072 if (ret == HITLS_SUCCESS)
1073 return coap_hitls_check_handshake_done(session, env);
1074 if (coap_hitls_check_handshake_done(session, env))
1075 return 1;
1076 if (coap_hitls_is_retry(ret))
1077 return 0;
1078
1079 coap_log_warn("coap_hitls_handshake: returned 0x%x\n", (unsigned int)ret);
1080 coap_hitls_log_fatal_err_stack(session);
1082 return -1;
1083}
1084
1085static int32_t
1086coap_hitls_uio_write(BSL_UIO *uio, const void *buf, uint32_t len,
1087 uint32_t *write_len) {
1088 coap_hitls_env_t *env = (coap_hitls_env_t *)BSL_UIO_GetUserData(uio);
1089 ssize_t ret;
1090
1091 if (write_len)
1092 *write_len = 0;
1093 if (!env || !env->session || !buf || !write_len)
1094 return BSL_NULL_INPUT;
1095 if (!coap_netif_available(env->session)
1097 && env->session->endpoint == NULL
1098#endif /* COAP_SERVER_SUPPORT */
1099 ) {
1100 errno = ECONNRESET;
1101 return BSL_UIO_IO_EXCEPTION;
1102 }
1103
1104 (void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
1105 ret = env->session->sock.lfunc[COAP_LAYER_TLS].l_write(env->session,
1106 (const uint8_t *)buf, len);
1107 if (ret < 0) {
1108#ifdef EMSGSIZE
1109 if (errno == EMSGSIZE) {
1110 env->mtu_exceeded = 1;
1111 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_WRITE | BSL_UIO_FLAGS_SHOULD_RETRY);
1112 return BSL_SUCCESS;
1113 }
1114#endif /* EMSGSIZE */
1115 if (errno == ENOTCONN || errno == ECONNREFUSED)
1116 env->session->dtls_event = COAP_EVENT_DTLS_ERROR;
1117 return BSL_UIO_IO_EXCEPTION;
1118 }
1119 if (ret == 0) {
1120 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_WRITE | BSL_UIO_FLAGS_SHOULD_RETRY);
1121 return BSL_SUCCESS;
1122 }
1123 *write_len = (uint32_t)ret;
1124 return BSL_SUCCESS;
1125}
1126
1127static int32_t
1128coap_hitls_uio_read(BSL_UIO *uio, void *buf, uint32_t len,
1129 uint32_t *read_len) {
1130 coap_hitls_env_t *env = (coap_hitls_env_t *)BSL_UIO_GetUserData(uio);
1131 size_t copy_len;
1132
1133 if (read_len)
1134 *read_len = 0;
1135 if (!env || !buf || !read_len)
1136 return BSL_NULL_INPUT;
1137 if (env->proto == COAP_PROTO_TLS) {
1138 ssize_t ret;
1139
1140 (void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
1141 ret = env->session->sock.lfunc[COAP_LAYER_TLS].l_read(env->session,
1142 (uint8_t *)buf, len);
1143 if (ret < 0)
1144 return errno == ECONNRESET ? BSL_UIO_IO_EOF : BSL_UIO_IO_EXCEPTION;
1145 if (ret == 0) {
1146 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_READ | BSL_UIO_FLAGS_SHOULD_RETRY);
1147 return BSL_SUCCESS;
1148 }
1149 *read_len = (uint32_t)ret;
1150 return BSL_SUCCESS;
1151 }
1152 if (!env->pdu || env->pdu_len == 0) {
1153 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_READ | BSL_UIO_FLAGS_SHOULD_RETRY);
1154 return BSL_SUCCESS;
1155 }
1156
1157 copy_len = env->pdu_len < len ? env->pdu_len : len;
1158 memcpy(buf, env->pdu, copy_len);
1159 env->pdu += copy_len;
1160 env->pdu_len -= copy_len;
1161 *read_len = (uint32_t)copy_len;
1162 return BSL_SUCCESS;
1163}
1164
1165static int32_t
1166coap_hitls_uio_ctrl(BSL_UIO *uio, int32_t cmd, int32_t larg, void *parg) {
1167 coap_hitls_env_t *env = (coap_hitls_env_t *)BSL_UIO_GetUserData(uio);
1168
1169 if (!env)
1170 return BSL_NULL_INPUT;
1171
1172 switch (cmd) {
1173 case BSL_UIO_GET_FD:
1174 if (parg) {
1175#if defined(_WIN32)
1176 *(int32_t *)parg = -1;
1177#elif COAP_SERVER_SUPPORT
1178 *(int32_t *)parg = (int32_t)(COAP_PROTO_NOT_RELIABLE(env->session->proto) ?
1179 env->session->type != COAP_SESSION_TYPE_CLIENT ?
1180 env->session->endpoint->sock.fd :
1181 env->session->sock.fd :
1182 env->session->sock.fd);
1183#else /* ! _WIN32 && ! COAP_SERVER_SUPPORT */
1184 *(int32_t *)parg = (int32_t)env->session->sock.fd;
1185#endif /* ! _WIN32 */
1186 }
1187 return BSL_SUCCESS;
1188 case BSL_UIO_SET_FD:
1189 case BSL_UIO_SET_PEER_IP_ADDR:
1190 case BSL_UIO_UDP_SET_CONNECTED:
1191 case BSL_UIO_FLUSH:
1192 case BSL_UIO_RESET:
1193 return BSL_SUCCESS;
1194 case BSL_UIO_GET_PEER_IP_ADDR:
1195 if (!parg || !env->session)
1196 return BSL_NULL_INPUT;
1197 if (larg == (int32_t)sizeof(BSL_UIO_CtrlGetPeerIpAddrParam)) {
1198 BSL_UIO_CtrlGetPeerIpAddrParam *param =
1199 (BSL_UIO_CtrlGetPeerIpAddrParam *)parg;
1200 uint32_t addr_len = (uint32_t)env->session->addr_info.remote.size;
1201
1202 if (!param->addr || param->size < addr_len)
1203 return BSL_INVALID_ARG;
1204 memcpy(param->addr, &env->session->addr_info.remote.addr.sa, addr_len);
1205 param->size = addr_len;
1206 return BSL_SUCCESS;
1207 }
1208 if (env->session->addr_info.remote.size > (socklen_t)larg)
1209 return BSL_INVALID_ARG;
1210 memcpy(parg, &env->session->addr_info.remote.addr.sa,
1211 env->session->addr_info.remote.size);
1212 return BSL_SUCCESS;
1213 case BSL_UIO_PENDING:
1214 case BSL_UIO_WPENDING:
1215 if (parg)
1216 *(uint64_t *)parg = cmd == BSL_UIO_PENDING ? env->pdu_len : 0;
1217 return BSL_SUCCESS;
1218 case BSL_UIO_UDP_GET_MTU_OVERHEAD:
1219 if (!parg)
1220 return BSL_NULL_INPUT;
1221 if (larg != (int32_t)sizeof(uint8_t))
1222 return BSL_INVALID_ARG;
1223 *(uint8_t *)parg = coap_hitls_udp_overhead(env);
1224 return BSL_SUCCESS;
1225 case BSL_UIO_UDP_QUERY_MTU:
1226 if (!parg)
1227 return BSL_NULL_INPUT;
1228 if (larg != (int32_t)sizeof(uint32_t))
1229 return BSL_INVALID_ARG;
1230 *(uint32_t *)parg = env->session->mtu > UINT32_MAX ?
1231 UINT32_MAX : (uint32_t)env->session->mtu;
1232 return BSL_SUCCESS;
1233 case BSL_UIO_UDP_MTU_EXCEEDED:
1234 if (!parg)
1235 return BSL_NULL_INPUT;
1236 if (larg != (int32_t)sizeof(bool))
1237 return BSL_INVALID_ARG;
1238 *(bool *)parg = env->mtu_exceeded != 0;
1239 env->mtu_exceeded = 0;
1240 return BSL_SUCCESS;
1241 default:
1242 return BSL_SUCCESS;
1243 }
1244}
1245
1246static int
1247coap_hitls_setup_uio(coap_hitls_env_t *env) {
1248 BSL_UIO *uio;
1249 BSL_UIO_TransportType type =
1250 env->proto == COAP_PROTO_DTLS ? BSL_UIO_UDP : BSL_UIO_TCP;
1251
1252 env->method = BSL_UIO_NewMethod();
1253 if (!env->method)
1254 return 0;
1255#if defined(__GNUC__)
1256#pragma GCC diagnostic push
1257#pragma GCC diagnostic ignored "-Wpedantic"
1258#endif /* defined(__GNUC__) */
1259 if (BSL_UIO_SetMethodType(env->method, type) != BSL_SUCCESS ||
1260 BSL_UIO_SetMethod(env->method, BSL_UIO_WRITE_CB,
1261 (void *)coap_hitls_uio_write) != BSL_SUCCESS ||
1262 BSL_UIO_SetMethod(env->method, BSL_UIO_READ_CB,
1263 (void *)coap_hitls_uio_read) != BSL_SUCCESS ||
1264 BSL_UIO_SetMethod(env->method, BSL_UIO_CTRL_CB,
1265 (void *)coap_hitls_uio_ctrl) != BSL_SUCCESS) {
1266 BSL_UIO_FreeMethod(env->method);
1267 env->method = NULL;
1268 return 0;
1269 }
1270#if defined(__GNUC__)
1271#pragma GCC diagnostic pop
1272#endif /* defined(__GNUC__) */
1273
1274 uio = BSL_UIO_New(env->method);
1275 if (!uio)
1276 return 0;
1277 if (BSL_UIO_SetUserData(uio, env) != BSL_SUCCESS) {
1278 BSL_UIO_Free(uio);
1279 return 0;
1280 }
1281 BSL_UIO_SetInit(uio, true);
1282 if (HITLS_SetUio(env->ctx, uio) != HITLS_SUCCESS) {
1283 BSL_UIO_SetUserData(uio, NULL);
1284 BSL_UIO_Free(uio);
1285 return 0;
1286 }
1287 env->uio = HITLS_GetUio(env->ctx);
1288 BSL_UIO_Free(uio);
1289 return 1;
1290}
1291
1292static void
1293coap_hitls_update_mtu(coap_hitls_env_t *env) {
1294 uint16_t mtu;
1295 int32_t ret;
1296
1297 if (!env || !env->ctx || !env->session || env->proto != COAP_PROTO_DTLS)
1298 return;
1299
1300 mtu = env->session->mtu > UINT16_MAX ? UINT16_MAX :
1301 (uint16_t)env->session->mtu;
1302 ret = HITLS_SetMtu(env->ctx, mtu);
1303 if (ret != HITLS_SUCCESS) {
1304 coap_log_warn("HITLS_SetMtu(%u) returned 0x%x\n", mtu,
1305 (unsigned int)ret);
1306 }
1307}
1308
1309#if COAP_CLIENT_SUPPORT
1310static uint32_t
1311coap_hitls_psk_client_cb(HITLS_Ctx *ctx, const uint8_t *hint,
1312 uint8_t *identity, uint32_t max_identity_len,
1313 uint8_t *psk, uint32_t max_psk_len) {
1314 coap_session_t *session = (coap_session_t *)HITLS_GetUserData(ctx);
1315 coap_dtls_cpsk_t *setup_data;
1316 const coap_dtls_cpsk_info_t *cpsk_info;
1317 const coap_bin_const_t *psk_identity;
1318 const coap_bin_const_t *psk_key;
1319
1320 if (!session || !session->context)
1321 return 0;
1322
1323 setup_data = &session->cpsk_setup_data;
1324 if (setup_data->validate_ih_call_back) {
1325 coap_bin_const_t temp;
1326 coap_str_const_t lhint;
1327
1328 temp.s = hint ? hint : (const uint8_t *)"";
1329 temp.length = coap_hitls_strnlen(temp.s, COAP_DTLS_MAX_PSK_IDENTITY);
1330 coap_session_refresh_psk_hint(session, &temp);
1331
1332 lhint.s = temp.s;
1333 lhint.length = temp.length;
1334 coap_lock_callback_ret(cpsk_info,
1335 setup_data->validate_ih_call_back(&lhint,
1336 session,
1337 setup_data->ih_call_back_arg));
1338 if (!cpsk_info)
1339 return 0;
1340 coap_session_refresh_psk_identity(session, &cpsk_info->identity);
1341 coap_session_refresh_psk_key(session, &cpsk_info->key);
1342 psk_identity = &cpsk_info->identity;
1343 psk_key = &cpsk_info->key;
1344 } else {
1345 psk_identity = coap_get_session_client_psk_identity(session);
1346 psk_key = coap_get_session_client_psk_key(session);
1347 }
1348
1349 if (coap_hitls_copy_bin(identity, max_identity_len, psk_identity, 1) == 0 ||
1350 coap_hitls_copy_bin(psk, max_psk_len, psk_key, 0) == 0)
1351 return 0;
1352 return (uint32_t)psk_key->length;
1353}
1354#endif /* COAP_CLIENT_SUPPORT */
1355
1356#if COAP_SERVER_SUPPORT
1357static HITLS_Config *coap_hitls_new_server_sni_config(coap_session_t *session, coap_proto_t proto,
1358 const coap_dtls_key_t *new_key);
1359
1360static int32_t
1361coap_hitls_sni_cb(HITLS_Ctx *ctx, int *alert COAP_UNUSED,
1362 void *arg COAP_UNUSED) {
1363 coap_session_t *session = (coap_session_t *)HITLS_GetUserData(ctx);
1364 coap_hitls_context_t *context =
1365 session && session->context ?
1366 (coap_hitls_context_t *)session->context->dtls_context : NULL;
1367 coap_dtls_pki_t *pki_setup_data = context ? &context->setup_data : NULL;
1368 coap_dtls_spsk_t *psk_setup_data;
1369 const char *sni;
1370 int accepted = 0;
1371
1372 if (!session || !session->context)
1373 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1374 sni = HITLS_GetServerName(ctx, HITLS_SNI_HOSTNAME_TYPE);
1375 if (!sni)
1376 sni = "";
1377
1378 if (pki_setup_data && pki_setup_data->validate_sni_call_back) {
1379 coap_dtls_key_t *new_key;
1380 HITLS_Config *new_config;
1381
1382 coap_lock_callback_ret(new_key,
1383 pki_setup_data->validate_sni_call_back(
1384 sni, pki_setup_data->sni_call_back_arg));
1385 if (!new_key)
1386 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1387 new_config = coap_hitls_new_server_sni_config(session, session->proto,
1388 new_key);
1389 if (!new_config)
1390 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1391 if (!HITLS_SetNewConfig(ctx, new_config)) {
1392 HITLS_CFG_FreeConfig(new_config);
1393 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1394 }
1395 HITLS_CFG_FreeConfig(new_config);
1396 accepted = 1;
1397 }
1398
1399 psk_setup_data = &session->context->spsk_setup_data;
1400 if (psk_setup_data->validate_sni_call_back) {
1401 const coap_dtls_spsk_info_t *new_entry;
1402
1403 coap_lock_callback_ret(new_entry,
1404 psk_setup_data->validate_sni_call_back(
1405 sni, session, psk_setup_data->sni_call_back_arg));
1406 if (!new_entry)
1407 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1408 if (!coap_session_refresh_psk_hint(session, &new_entry->hint) ||
1409 !coap_session_refresh_psk_key(session, &new_entry->key))
1410 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1411 if (new_entry->hint.s && new_entry->hint.length > 0 &&
1412 new_entry->hint.length <= UINT32_MAX &&
1413 HITLS_SetPskIdentityHint(ctx, new_entry->hint.s,
1414 (uint32_t)new_entry->hint.length) != HITLS_SUCCESS)
1415 return HITLS_ACCEPT_SNI_ERR_ALERT_FATAL;
1416 accepted = 1;
1417 }
1418
1419 return accepted ? HITLS_ACCEPT_SNI_ERR_OK : HITLS_ACCEPT_SNI_ERR_NOACK;
1420}
1421
1422static uint32_t
1423coap_hitls_psk_server_cb(HITLS_Ctx *ctx, const uint8_t *identity,
1424 uint8_t *psk, uint32_t max_psk_len) {
1425 coap_session_t *session = (coap_session_t *)HITLS_GetUserData(ctx);
1426 coap_dtls_spsk_t *setup_data;
1427 coap_bin_const_t lidentity;
1428 const coap_bin_const_t *psk_key;
1429
1430 if (!session || !session->context)
1431 return 0;
1432
1433 setup_data = &session->context->spsk_setup_data;
1434 lidentity.s = identity ? identity : (const uint8_t *)"";
1435 lidentity.length = coap_hitls_strnlen(lidentity.s,
1437 coap_session_refresh_psk_identity(session, &lidentity);
1438
1439 if (setup_data->validate_id_call_back) {
1440 coap_lock_callback_ret(psk_key,
1441 setup_data->validate_id_call_back(&lidentity,
1442 session,
1443 setup_data->id_call_back_arg));
1444 coap_session_refresh_psk_key(session, psk_key);
1445 } else {
1446 psk_key = coap_get_session_server_psk_key(session);
1447 }
1448
1449 if (coap_hitls_copy_bin(psk, max_psk_len, psk_key, 0) == 0)
1450 return 0;
1451 return (uint32_t)psk_key->length;
1452}
1453#endif /* COAP_SERVER_SUPPORT */
1454
1455static int32_t
1456coap_hitls_alpn_select_cb(HITLS_Ctx *ctx COAP_UNUSED,
1457 uint8_t **selected_proto,
1458 uint8_t *selected_proto_len,
1459 uint8_t *client_alpn_list,
1460 uint32_t client_alpn_list_size,
1461 void *user_data COAP_UNUSED) {
1462 if (HITLS_SelectAlpnProtocol(selected_proto, selected_proto_len,
1463 coap_hitls_alpn, sizeof(coap_hitls_alpn),
1464 client_alpn_list,
1465 client_alpn_list_size) != HITLS_SUCCESS ||
1466 !selected_proto || !*selected_proto ||
1467 !selected_proto_len || *selected_proto_len != 4)
1468 return HITLS_ALPN_ERR_ALERT_FATAL;
1469 return HITLS_ALPN_ERR_OK;
1470}
1471
1472static int
1473coap_hitls_load_ca(HITLS_Config *config, coap_dtls_key_t *key,
1474 coap_dtls_role_t role) {
1475 coap_pki_key_define_t *define = &key->key.define;
1476 uint32_t len;
1477 uint8_t *buf;
1478 int32_t ret;
1479
1480 switch (define->ca_def) {
1482 if (!define->ca.s_byte || !define->ca.s_byte[0])
1483 return 1;
1484 if (HITLS_CFG_LoadVerifyFile(config, define->ca.s_byte) == HITLS_SUCCESS)
1485 return 1;
1487 COAP_DEFINE_FAIL_BAD, key, role, 0);
1489 if (!define->ca.u_byte || !define->ca_len)
1490 return 1;
1491 if (!coap_hitls_pki_len(define->ca.u_byte, define->ca_len,
1492 TLS_PARSE_FORMAT_PEM, &len))
1494 COAP_DEFINE_FAIL_BAD, key, role, 0);
1495 if (HITLS_CFG_LoadVerifyBuffer(config, define->ca.u_byte, len,
1496 TLS_PARSE_FORMAT_PEM) == HITLS_SUCCESS)
1497 return 1;
1499 COAP_DEFINE_FAIL_BAD, key, role, 0);
1501 if (!define->ca.u_byte || !define->ca_len)
1502 return 1;
1503 if (!coap_hitls_pki_len(define->ca.u_byte, define->ca_len,
1504 TLS_PARSE_FORMAT_ASN1, &len))
1506 COAP_DEFINE_FAIL_BAD, key, role, 0);
1507 if (HITLS_CFG_LoadVerifyBuffer(config, define->ca.u_byte, len,
1508 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1509 return 1;
1511 COAP_DEFINE_FAIL_BAD, key, role, 0);
1513 if (!define->ca.s_byte || !define->ca.s_byte[0])
1514 return 1;
1515 buf = coap_hitls_read_file(define->ca.s_byte, &len);
1516 if (!buf)
1518 COAP_DEFINE_FAIL_BAD, key, role, 0);
1519 ret = HITLS_CFG_LoadVerifyBuffer(config, buf, len, TLS_PARSE_FORMAT_ASN1);
1521 if (ret == HITLS_SUCCESS)
1522 return 1;
1524 COAP_DEFINE_FAIL_BAD, key, role, ret);
1529 if (define->ca.u_byte && define->ca.u_byte[0])
1532 role, 0);
1533 return 1;
1534 default:
1535 return 1;
1536 }
1537}
1538
1539static int
1540coap_hitls_load_public_cert(HITLS_Config *config, coap_dtls_key_t *key,
1541 coap_dtls_role_t role) {
1542 coap_pki_key_define_t *define = &key->key.define;
1543 uint32_t len;
1544
1545 switch (define->public_cert_def) {
1547 if (!define->public_cert.s_byte || !define->public_cert.s_byte[0])
1548 return 1;
1549 /* A PEM buffer may hold leaf + intermediate CAs; load the whole chain. */
1550 if (HITLS_CFG_UseCertificateChainFile(config,
1551 define->public_cert.s_byte) == HITLS_SUCCESS)
1552 return 1;
1554 COAP_DEFINE_FAIL_BAD, key, role, 0);
1556 if (!define->public_cert.s_byte || !define->public_cert.s_byte[0])
1557 return 1;
1558 if (HITLS_CFG_LoadCertFile(config, define->public_cert.s_byte,
1559 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1560 return 1;
1562 COAP_DEFINE_FAIL_BAD, key, role, 0);
1564 if (!define->public_cert.u_byte || !define->public_cert_len)
1565 return 1;
1566 if (!coap_hitls_pki_len(define->public_cert.u_byte,
1567 define->public_cert_len, TLS_PARSE_FORMAT_PEM,
1568 &len))
1570 COAP_DEFINE_FAIL_BAD, key, role, 0);
1571 /* A PEM buffer may hold leaf + intermediate CAs; load the whole chain. */
1572 if (HITLS_CFG_UseCertificateChainBuffer(config, define->public_cert.u_byte,
1573 len, TLS_PARSE_FORMAT_PEM) == HITLS_SUCCESS)
1574 return 1;
1576 COAP_DEFINE_FAIL_BAD, key, role, 0);
1578 if (!define->public_cert.u_byte || !define->public_cert_len)
1579 return 1;
1580 if (!coap_hitls_pki_len(define->public_cert.u_byte,
1581 define->public_cert_len, TLS_PARSE_FORMAT_ASN1,
1582 &len))
1584 COAP_DEFINE_FAIL_BAD, key, role, 0);
1585 if (HITLS_CFG_LoadCertBuffer(config, define->public_cert.u_byte, len,
1586 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1587 return 1;
1589 COAP_DEFINE_FAIL_BAD, key, role, 0);
1594 if (define->public_cert.u_byte && define->public_cert.u_byte[0])
1597 role, 0);
1598 return 1;
1599 default:
1600 return 1;
1601 }
1602}
1603
1604static int
1605coap_hitls_load_private_key(HITLS_Config *config, coap_dtls_key_t *key,
1606 coap_dtls_role_t role) {
1607 coap_pki_key_define_t *define = &key->key.define;
1608 uint32_t len;
1609
1610 switch (define->private_key_def) {
1612 if (!define->private_key.s_byte || !define->private_key.s_byte[0])
1613 return 1;
1614 if (HITLS_CFG_LoadKeyFile(config, define->private_key.s_byte,
1615 TLS_PARSE_FORMAT_PEM) == HITLS_SUCCESS)
1616 return 1;
1618 COAP_DEFINE_FAIL_BAD, key, role, 0);
1620 if (!define->private_key.s_byte || !define->private_key.s_byte[0])
1621 return 1;
1622 if (HITLS_CFG_LoadKeyFile(config, define->private_key.s_byte,
1623 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1624 return 1;
1626 COAP_DEFINE_FAIL_BAD, key, role, 0);
1628 if (!define->private_key.u_byte || !define->private_key_len)
1629 return 1;
1630 if (!coap_hitls_pki_len(define->private_key.u_byte,
1631 define->private_key_len, TLS_PARSE_FORMAT_PEM,
1632 &len))
1634 COAP_DEFINE_FAIL_BAD, key, role, 0);
1635 if (HITLS_CFG_LoadKeyBuffer(config, define->private_key.u_byte, len,
1636 TLS_PARSE_FORMAT_PEM) == HITLS_SUCCESS)
1637 return 1;
1639 COAP_DEFINE_FAIL_BAD, key, role, 0);
1641 if (!define->private_key.u_byte || !define->private_key_len)
1642 return 1;
1643 if (!coap_hitls_pki_len(define->private_key.u_byte,
1644 define->private_key_len, TLS_PARSE_FORMAT_ASN1,
1645 &len))
1647 COAP_DEFINE_FAIL_BAD, key, role, 0);
1648 if (HITLS_CFG_LoadKeyBuffer(config, define->private_key.u_byte, len,
1649 TLS_PARSE_FORMAT_ASN1) == HITLS_SUCCESS)
1650 return 1;
1652 COAP_DEFINE_FAIL_BAD, key, role, 0);
1657 if (define->private_key.u_byte && define->private_key.u_byte[0])
1660 role, 0);
1661 return 1;
1662 default:
1663 return 1;
1664 }
1665}
1666
1667static int
1668coap_hitls_load_root_cas(HITLS_Config *config, coap_hitls_context_t *context) {
1669 if (context->root_ca_file &&
1670 HITLS_CFG_LoadVerifyFile(config, context->root_ca_file) != HITLS_SUCCESS) {
1671 coap_log_warn("Unable to install root CA file '%s'\n",
1672 context->root_ca_file);
1673 return 0;
1674 }
1675 if (context->root_ca_dir &&
1676 HITLS_CFG_LoadVerifyDir(config, context->root_ca_dir) != HITLS_SUCCESS) {
1677 coap_log_warn("Unable to install root CA directory '%s'\n",
1678 context->root_ca_dir);
1679 return 0;
1680 }
1681 if (context->trust_store_defined &&
1682 HITLS_CFG_LoadDefaultCAPath(config) != HITLS_SUCCESS) {
1683 coap_log_warn("Unable to load trusted root CAs\n");
1684 return 0;
1685 }
1686 return 1;
1687}
1688
1689static int
1690coap_hitls_configure_pki(HITLS_Config *config, coap_session_t *session,
1691 coap_dtls_role_t role,
1692 const coap_dtls_pki_t *pki_setup_data) {
1693 coap_hitls_context_t *context =
1694 session && session->context ?
1695 (coap_hitls_context_t *)session->context->dtls_context : NULL;
1696 coap_dtls_pki_t setup_data_copy;
1697 coap_dtls_pki_t *setup_data = context ? &context->setup_data : NULL;
1698 coap_dtls_key_t key;
1699
1700 if (pki_setup_data) {
1701 setup_data_copy = *pki_setup_data;
1702 setup_data = &setup_data_copy;
1703 }
1704 if (!context || !setup_data)
1705 return 0;
1706 if (!coap_hitls_check_pki_key_supported(setup_data, role))
1707 return 0;
1708
1709 coap_dtls_map_key_type_to_define(setup_data, &key);
1710 if (key.key_type != COAP_PKI_KEY_DEFINE)
1711 return 0;
1712
1713 if (!coap_hitls_load_root_cas(config, context) ||
1714 !coap_hitls_load_ca(config, &key, role) ||
1715 !coap_hitls_load_public_cert(config, &key, role) ||
1716 !coap_hitls_load_private_key(config, &key, role))
1717 return 0;
1718
1719 if (setup_data->cert_chain_validation &&
1720 HITLS_CFG_SetVerifyDepth(config,
1721 COAP_HITLS_VERIFY_DEPTH_TO_MAX_CHAIN_DEPTH(
1722 setup_data->cert_chain_verify_depth)) !=
1723 HITLS_SUCCESS)
1724 return 0;
1725 if (setup_data->check_cert_revocation &&
1726 HITLS_CFG_SetVerifyFlags(config,
1727 HITLS_X509_VFY_FLAG_CRL_ALL) != HITLS_SUCCESS)
1728 return 0;
1729 if (HITLS_CFG_SetVerifyCb(config, coap_hitls_verify_cb) != HITLS_SUCCESS)
1730 return 0;
1731 if (HITLS_CFG_SetCertVerifyCb(config, coap_hitls_app_verify_cb,
1732 NULL) != HITLS_SUCCESS)
1733 return 0;
1734
1735 if (role == COAP_DTLS_ROLE_CLIENT) {
1736 if (setup_data->client_sni && setup_data->client_sni[0] &&
1737 HITLS_CFG_SetServerName(config,
1738 (uint8_t *)setup_data->client_sni,
1739 (uint32_t)strlen(setup_data->client_sni)) != HITLS_SUCCESS)
1740 return 0;
1741 } else {
1742 if (HITLS_CFG_SetClientVerifySupport(config,
1743 setup_data->verify_peer_cert ? true : false) != HITLS_SUCCESS)
1744 return 0;
1745 if (setup_data->verify_peer_cert &&
1746 HITLS_CFG_SetNoClientCertSupport(config, false) != HITLS_SUCCESS)
1747 return 0;
1748 }
1749
1750 if (HITLS_CFG_SetVerifyNoneSupport(config,
1751 setup_data->verify_peer_cert ? false : true) != HITLS_SUCCESS)
1752 return 0;
1753 return 1;
1754}
1755
1756#if COAP_SERVER_SUPPORT
1757static HITLS_Config *
1758coap_hitls_new_server_sni_config(coap_session_t *session, coap_proto_t proto,
1759 const coap_dtls_key_t *new_key) {
1760 coap_hitls_context_t *context =
1761 session && session->context ?
1762 (coap_hitls_context_t *)session->context->dtls_context : NULL;
1763 const uint16_t *cipher_suites;
1764 uint32_t cipher_suites_count;
1765 int enabled = context && context->psk_pki_enabled ?
1766 context->psk_pki_enabled : IS_PKI;
1767 coap_dtls_pki_t pki_setup_data;
1768 HITLS_Config *config;
1769
1770 if (!context || !new_key)
1771 return NULL;
1772
1773 config = proto == COAP_PROTO_DTLS ? HITLS_CFG_NewDTLS12Config() :
1774 HITLS_CFG_NewTLS12Config();
1775 if (!config)
1776 return NULL;
1777
1778 coap_hitls_get_cipher_suites(enabled, &cipher_suites, &cipher_suites_count);
1779 if (HITLS_CFG_SetCipherSuites(config, cipher_suites,
1780 cipher_suites_count) != HITLS_SUCCESS) {
1781 HITLS_CFG_FreeConfig(config);
1782 return NULL;
1783 }
1784 if (proto == COAP_PROTO_DTLS &&
1785 (HITLS_CFG_SetFlightTransmitSwitch(config, true) != HITLS_SUCCESS ||
1786 HITLS_CFG_SetDtlsCookieExchangeSupport(config, true) != HITLS_SUCCESS ||
1787 HITLS_CFG_SetCookieGenCb(config,
1788 coap_hitls_cookie_gen_cb) != HITLS_SUCCESS ||
1789 HITLS_CFG_SetCookieVerifyCb(config,
1790 coap_hitls_cookie_verify_cb) != HITLS_SUCCESS)) {
1791 HITLS_CFG_FreeConfig(config);
1792 return NULL;
1793 }
1794 if (proto == COAP_PROTO_TLS &&
1795 HITLS_CFG_SetAlpnProtosSelectCb(config, coap_hitls_alpn_select_cb,
1796 NULL) != HITLS_SUCCESS) {
1797 HITLS_CFG_FreeConfig(config);
1798 return NULL;
1799 }
1800 if (enabled & IS_PSK) {
1802
1803 if (hint && hint->s && hint->length <= UINT32_MAX &&
1804 HITLS_CFG_SetPskIdentityHint(config, hint->s,
1805 (uint32_t)hint->length) != HITLS_SUCCESS) {
1806 HITLS_CFG_FreeConfig(config);
1807 return NULL;
1808 }
1809 if (HITLS_CFG_SetPskServerCallback(config,
1810 coap_hitls_psk_server_cb) != HITLS_SUCCESS) {
1811 HITLS_CFG_FreeConfig(config);
1812 return NULL;
1813 }
1814 }
1815
1816 pki_setup_data = context->setup_data;
1817 pki_setup_data.pki_key = *new_key;
1818 if (!coap_hitls_configure_pki(config, session, COAP_DTLS_ROLE_SERVER,
1819 &pki_setup_data)) {
1820 HITLS_CFG_FreeConfig(config);
1821 return NULL;
1822 }
1823
1824 (void)HITLS_CFG_SetInfoCb(config, coap_hitls_info_cb);
1825 return config;
1826}
1827#endif /* COAP_SERVER_SUPPORT */
1828
1829static HITLS_Config *
1830coap_hitls_new_config(coap_session_t *session, coap_dtls_role_t role,
1831 coap_proto_t proto) {
1832 coap_hitls_context_t *hitls_context =
1833 session && session->context ?
1834 (coap_hitls_context_t *)session->context->dtls_context : NULL;
1835 const uint16_t *cipher_suites;
1836 uint32_t cipher_suites_count;
1837 int enabled = hitls_context && hitls_context->psk_pki_enabled ?
1838 hitls_context->psk_pki_enabled : IS_PSK;
1839 HITLS_Config *config = proto == COAP_PROTO_DTLS ?
1840 HITLS_CFG_NewDTLS12Config() :
1841 HITLS_CFG_NewTLS12Config();
1842
1843 if (!config)
1844 return NULL;
1845
1846 coap_hitls_get_cipher_suites(enabled, &cipher_suites, &cipher_suites_count);
1847
1848 if (HITLS_CFG_SetCipherSuites(config, cipher_suites,
1849 cipher_suites_count) != HITLS_SUCCESS) {
1850 HITLS_CFG_FreeConfig(config);
1851 return NULL;
1852 }
1853 if (proto == COAP_PROTO_DTLS &&
1854 (HITLS_CFG_SetFlightTransmitSwitch(config, true) != HITLS_SUCCESS ||
1855 HITLS_CFG_SetDtlsCookieExchangeSupport(config,
1856 role == COAP_DTLS_ROLE_SERVER) != HITLS_SUCCESS)) {
1857 HITLS_CFG_FreeConfig(config);
1858 return NULL;
1859 }
1860#if COAP_SERVER_SUPPORT
1861 if (proto == COAP_PROTO_DTLS && role == COAP_DTLS_ROLE_SERVER &&
1862 (HITLS_CFG_SetCookieGenCb(config,
1863 coap_hitls_cookie_gen_cb) != HITLS_SUCCESS ||
1864 HITLS_CFG_SetCookieVerifyCb(config,
1865 coap_hitls_cookie_verify_cb) != HITLS_SUCCESS)) {
1866 HITLS_CFG_FreeConfig(config);
1867 return NULL;
1868 }
1869#endif /* COAP_SERVER_SUPPORT */
1870 if (proto == COAP_PROTO_TLS &&
1871 ((role == COAP_DTLS_ROLE_CLIENT &&
1872 HITLS_CFG_SetAlpnProtos(config, coap_hitls_alpn,
1873 sizeof(coap_hitls_alpn)) != HITLS_SUCCESS) ||
1874 (role == COAP_DTLS_ROLE_SERVER &&
1875 HITLS_CFG_SetAlpnProtosSelectCb(config,
1876 coap_hitls_alpn_select_cb,
1877 NULL) != HITLS_SUCCESS))) {
1878 HITLS_CFG_FreeConfig(config);
1879 return NULL;
1880 }
1881
1882 if (role == COAP_DTLS_ROLE_CLIENT && (enabled & IS_PSK)) {
1883#if COAP_CLIENT_SUPPORT
1884 coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
1885
1886 if (setup_data->client_sni && setup_data->client_sni[0] &&
1887 HITLS_CFG_SetServerName(config,
1888 (uint8_t *)setup_data->client_sni,
1889 (uint32_t)strlen(setup_data->client_sni)) != HITLS_SUCCESS) {
1890 HITLS_CFG_FreeConfig(config);
1891 return NULL;
1892 }
1893 if (HITLS_CFG_SetPskClientCallback(config,
1894 coap_hitls_psk_client_cb) != HITLS_SUCCESS) {
1895 HITLS_CFG_FreeConfig(config);
1896 return NULL;
1897 }
1898#else /* ! COAP_CLIENT_SUPPORT */
1899 (void)session;
1900 HITLS_CFG_FreeConfig(config);
1901 return NULL;
1902#endif /* ! COAP_CLIENT_SUPPORT */
1903 } else if (role == COAP_DTLS_ROLE_SERVER && (enabled & IS_PSK)) {
1904#if COAP_SERVER_SUPPORT
1906
1907 if (hint && hint->s && hint->length <= UINT32_MAX &&
1908 HITLS_CFG_SetPskIdentityHint(config, hint->s,
1909 (uint32_t)hint->length) != HITLS_SUCCESS) {
1910 HITLS_CFG_FreeConfig(config);
1911 return NULL;
1912 }
1913 if (HITLS_CFG_SetPskServerCallback(config,
1914 coap_hitls_psk_server_cb) != HITLS_SUCCESS) {
1915 HITLS_CFG_FreeConfig(config);
1916 return NULL;
1917 }
1918#else /* ! COAP_SERVER_SUPPORT */
1919 (void)session;
1920 HITLS_CFG_FreeConfig(config);
1921 return NULL;
1922#endif /* ! COAP_SERVER_SUPPORT */
1923 }
1924
1925#if COAP_SERVER_SUPPORT
1926 if (role == COAP_DTLS_ROLE_SERVER) {
1927 int needs_sni = 0;
1928
1929 if ((enabled & IS_PSK) && session && session->context &&
1930 session->context->spsk_setup_data.validate_sni_call_back)
1931 needs_sni = 1;
1932 if ((enabled & IS_PKI) && hitls_context &&
1933 hitls_context->setup_data.validate_sni_call_back)
1934 needs_sni = 1;
1935 if (needs_sni &&
1936 (HITLS_CFG_SetServerNameCb(config,
1937 coap_hitls_sni_cb) != HITLS_SUCCESS ||
1938 HITLS_CFG_SetServerNameArg(config, NULL) != HITLS_SUCCESS)) {
1939 HITLS_CFG_FreeConfig(config);
1940 return NULL;
1941 }
1942 }
1943#endif /* COAP_SERVER_SUPPORT */
1944
1945 if ((enabled & IS_PKI) &&
1946 !coap_hitls_configure_pki(config, session, role, NULL)) {
1947 HITLS_CFG_FreeConfig(config);
1948 return NULL;
1949 }
1950
1951 (void)HITLS_CFG_SetInfoCb(config, coap_hitls_info_cb);
1952 return config;
1953}
1954
1955static void
1956coap_hitls_free_env(coap_hitls_env_t *env) {
1957 if (!env)
1958 return;
1959 if (env->ctx) {
1960 if (env->established && !env->had_fatal)
1961 (void)HITLS_Close(env->ctx);
1962 if (env->uio)
1963 BSL_UIO_SetUserData(env->uio, NULL);
1964 HITLS_Free(env->ctx);
1965 } else if (env->uio) {
1966 BSL_UIO_SetUserData(env->uio, NULL);
1967 }
1968 if (env->method)
1969 BSL_UIO_FreeMethod(env->method);
1971}
1972
1973static coap_hitls_env_t *
1974coap_hitls_live_env(coap_session_t *session, coap_hitls_env_t *env) {
1975 return session && session->tls == (void *)env ? env : NULL;
1976}
1977
1978static void
1979coap_hitls_clear_pdu(coap_hitls_env_t *env) {
1980 if (env) {
1981 env->pdu = NULL;
1982 env->pdu_len = 0;
1983 }
1984}
1985
1986static coap_hitls_env_t *
1987coap_hitls_new_env(coap_session_t *session, coap_dtls_role_t role,
1988 coap_proto_t proto) {
1989 coap_hitls_env_t *env =
1990 (coap_hitls_env_t *)coap_malloc_type(COAP_STRING, sizeof(*env));
1991 coap_hitls_context_t *hitls_context =
1992 session && session->context ?
1993 (coap_hitls_context_t *)session->context->dtls_context : NULL;
1994 HITLS_Config *config;
1995
1996 if (!env)
1997 return NULL;
1998 memset(env, 0, sizeof(*env));
1999 env->session = session;
2000 env->role = role;
2001 env->proto = proto;
2002
2003 config = coap_hitls_new_config(session, role, proto);
2004 if (!config) {
2006 return NULL;
2007 }
2008
2009 env->ctx = HITLS_New(config);
2010 HITLS_CFG_FreeConfig(config);
2011 if (!env->ctx) {
2013 return NULL;
2014 }
2015 if (HITLS_SetUserData(env->ctx, session) != HITLS_SUCCESS ||
2016 !coap_hitls_setup_uio(env)) {
2017 coap_hitls_free_env(env);
2018 return NULL;
2019 }
2020 coap_hitls_update_mtu(env);
2021 if (hitls_context && (hitls_context->psk_pki_enabled & IS_PKI) &&
2022 hitls_context->setup_data.additional_tls_setup_call_back &&
2023 !hitls_context->setup_data.additional_tls_setup_call_back(env->ctx,
2024 &hitls_context->setup_data)) {
2025 coap_hitls_free_env(env);
2026 return NULL;
2027 }
2028
2029 return env;
2030}
2031
2032int
2034 return 1;
2035}
2036
2037int
2039#if !COAP_DISABLE_TCP
2040 return 1;
2041#else /* COAP_DISABLE_TCP */
2042 return 0;
2043#endif /* COAP_DISABLE_TCP */
2044}
2045
2046int
2048 return 1;
2049}
2050
2051int
2053 return 1;
2054}
2055
2056int
2058 return 0;
2059}
2060
2061int
2063 return 0;
2064}
2065
2066int
2068 return 0;
2069}
2070
2071#if COAP_CLIENT_SUPPORT
2072int
2074 uint8_t every COAP_UNUSED) {
2075 return 0;
2076}
2077#endif /* COAP_CLIENT_SUPPORT */
2078
2079void
2081 dtls_log_level = level;
2082}
2083
2086 return dtls_log_level;
2087}
2088#endif /* COAP_WITH_LIBOPENHITLS */
2089
2092 static coap_tls_version_t version;
2093
2094 version.version = HITLS_VersionNum();
2095 version.built_version = OPENHITLS_VERSION_I;
2097 return &version;
2098}
2099
2100void
2101coap_dtls_startup(void) {
2102 (void)coap_hitls_startup();
2103}
2104
2105void
2106coap_dtls_shutdown(void) {
2107 if (coap_hitls_started) {
2108#if COAP_WITH_LIBOPENHITLS
2109 HITLS_CertMethodDeinit();
2110#endif /* COAP_WITH_LIBOPENHITLS */
2111 CRYPT_EAL_Cleanup(CRYPT_EAL_INIT_ALL);
2112 coap_hitls_started = 0;
2113 }
2115}
2116
2117void
2119 BSL_ERR_RemoveErrorStack(false);
2120}
2121
2122#if COAP_WITH_LIBOPENHITLS
2123void *
2124coap_dtls_get_tls(const coap_session_t *session, coap_tls_library_t *tls_lib) {
2125 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
2126
2127 if (tls_lib)
2128 *tls_lib = COAP_TLS_LIBRARY_OPENHITLS;
2129 return env ? env->ctx : NULL;
2130}
2131
2132void *
2134 coap_hitls_context_t *context =
2135 (coap_hitls_context_t *)coap_malloc_type(COAP_STRING, sizeof(*context));
2136
2137 if (!context)
2138 return NULL;
2139 memset(context, 0, sizeof(*context));
2140 context->coap_context = coap_context;
2141 if (!coap_prng_lkd(context->cookie_secret,
2142 sizeof(context->cookie_secret))) {
2143 coap_free_type(COAP_STRING, context);
2144 return NULL;
2145 }
2146 context->cookie_secret_set = 1;
2147 return context;
2148}
2149
2150void
2151coap_dtls_free_context(void *dtls_context) {
2152 coap_hitls_context_t *context = (coap_hitls_context_t *)dtls_context;
2153
2154 if (context) {
2155 if (context->root_ca_file)
2156 coap_free_type(COAP_STRING, context->root_ca_file);
2157 if (context->root_ca_dir)
2158 coap_free_type(COAP_STRING, context->root_ca_dir);
2159 memset(context->cookie_secret, 0, sizeof(context->cookie_secret));
2160 context->cookie_secret_set = 0;
2161 coap_free_type(COAP_STRING, context);
2162 }
2163}
2164
2165#if COAP_SERVER_SUPPORT
2166int
2167coap_dtls_context_set_spsk(coap_context_t *coap_context,
2168 coap_dtls_spsk_t *setup_data) {
2169 coap_hitls_context_t *context;
2170
2171 if (!coap_context || !setup_data)
2172 return 0;
2173 context = (coap_hitls_context_t *)coap_context->dtls_context;
2174 if (!context)
2175 return 0;
2176 context->psk_pki_enabled |= IS_PSK;
2177 return 1;
2178}
2179#endif /* COAP_SERVER_SUPPORT */
2180
2181#if COAP_CLIENT_SUPPORT
2182int
2183coap_dtls_context_set_cpsk(coap_context_t *coap_context,
2184 coap_dtls_cpsk_t *setup_data) {
2185 coap_hitls_context_t *context;
2186
2187 if (!coap_context || !setup_data)
2188 return 0;
2189 context = (coap_hitls_context_t *)coap_context->dtls_context;
2190 if (!context)
2191 return 0;
2192 context->psk_pki_enabled |= IS_PSK;
2193 return 1;
2194}
2195#endif /* COAP_CLIENT_SUPPORT */
2196
2197int
2199 const coap_dtls_pki_t *setup_data,
2200 const coap_dtls_role_t role) {
2201 coap_hitls_context_t *context;
2202
2203 if (!coap_context || !setup_data)
2204 return 0;
2205 context = (coap_hitls_context_t *)coap_context->dtls_context;
2206 if (!context)
2207 return 0;
2208 if (!coap_hitls_check_pki_key_supported(setup_data, role))
2209 return 0;
2210 context->setup_data = *setup_data;
2211 if (!context->setup_data.verify_peer_cert) {
2212 /* Needs to be clear so that no CA DNs are transmitted */
2213 context->setup_data.check_common_ca = 0;
2214 /* Allow all of these but warn if issue */
2215 context->setup_data.allow_self_signed = 1;
2216 context->setup_data.allow_expired_certs = 1;
2217 context->setup_data.cert_chain_validation = 1;
2218 context->setup_data.cert_chain_verify_depth = 10;
2219 context->setup_data.check_cert_revocation = 1;
2220 context->setup_data.allow_no_crl = 1;
2221 context->setup_data.allow_expired_crl = 1;
2222 context->setup_data.allow_bad_md_hash = 1;
2223 context->setup_data.allow_short_rsa_length = 1;
2224 }
2225#if COAP_CLIENT_SUPPORT
2226 if (role == COAP_DTLS_ROLE_CLIENT)
2227 context->psk_pki_enabled &= ~IS_PSK;
2228#else /* ! COAP_CLIENT_SUPPORT */
2229 (void)role;
2230#endif /* ! COAP_CLIENT_SUPPORT */
2231 context->psk_pki_enabled |= IS_PKI;
2232 if (setup_data->use_cid)
2233 coap_log_warn("openHiTLS backend has no Connection-ID support\n");
2234 return 1;
2235}
2236
2237int
2239 const char *ca_file,
2240 const char *ca_dir) {
2241 coap_hitls_context_t *context;
2242 char *new_ca_file = NULL;
2243 char *new_ca_dir = NULL;
2244
2245 if (!coap_context || (!ca_file && !ca_dir))
2246 return 0;
2247 context = (coap_hitls_context_t *)coap_context->dtls_context;
2248 if (!context)
2249 return 0;
2250 if (ca_file) {
2251 new_ca_file = coap_hitls_strdup(ca_file);
2252 if (!new_ca_file)
2253 return 0;
2254 }
2255 if (ca_dir) {
2256 new_ca_dir = coap_hitls_strdup(ca_dir);
2257 if (!new_ca_dir) {
2258 if (new_ca_file)
2259 coap_free_type(COAP_STRING, new_ca_file);
2260 return 0;
2261 }
2262 }
2263 if (context->root_ca_file)
2264 coap_free_type(COAP_STRING, context->root_ca_file);
2265 if (context->root_ca_dir)
2266 coap_free_type(COAP_STRING, context->root_ca_dir);
2267 context->root_ca_file = new_ca_file;
2268 context->root_ca_dir = new_ca_dir;
2269 return 1;
2270}
2271
2272int
2274 coap_hitls_context_t *context =
2275 coap_context ? (coap_hitls_context_t *)coap_context->dtls_context : NULL;
2276
2277 if (!context)
2278 return 0;
2279 context->trust_store_defined = 1;
2280 return 1;
2281}
2282
2283int
2285 coap_hitls_context_t *context =
2286 coap_context ? (coap_hitls_context_t *)coap_context->dtls_context : NULL;
2287
2288 return context && context->psk_pki_enabled;
2289}
2290#endif /* COAP_WITH_LIBOPENHITLS */
2291
2292#if COAP_SERVER_SUPPORT
2293coap_digest_ctx_t *
2294coap_digest_setup(void) {
2295 CRYPT_EAL_MdCtx *digest_ctx;
2296
2297 if (!coap_hitls_startup())
2298 return NULL;
2299 digest_ctx = CRYPT_EAL_MdNewCtx(CRYPT_MD_SHA256);
2300 if (!digest_ctx)
2301 return NULL;
2302 if (CRYPT_EAL_MdInit(digest_ctx) != CRYPT_SUCCESS) {
2303 CRYPT_EAL_MdFreeCtx(digest_ctx);
2304 return NULL;
2305 }
2306 return digest_ctx;
2307}
2308
2309void
2310coap_digest_free(coap_digest_ctx_t *digest_ctx) {
2311 if (digest_ctx)
2312 CRYPT_EAL_MdFreeCtx((CRYPT_EAL_MdCtx *)digest_ctx);
2313}
2314
2315int
2316coap_digest_update(coap_digest_ctx_t *digest_ctx,
2317 const uint8_t *data,
2318 size_t data_len) {
2319 CRYPT_EAL_MdCtx *ctx = (CRYPT_EAL_MdCtx *)digest_ctx;
2320
2321 if (!ctx || (!data && data_len))
2322 return 0;
2323 while (data_len) {
2324 uint32_t chunk = data_len > UINT32_MAX ? UINT32_MAX : (uint32_t)data_len;
2325
2326 if (CRYPT_EAL_MdUpdate(ctx, data, chunk) != CRYPT_SUCCESS)
2327 return 0;
2328 data += chunk;
2329 data_len -= chunk;
2330 }
2331 return 1;
2332}
2333
2334int
2335coap_digest_final(coap_digest_ctx_t *digest_ctx,
2336 coap_digest_t *digest_buffer) {
2337 CRYPT_EAL_MdCtx *ctx = (CRYPT_EAL_MdCtx *)digest_ctx;
2338 uint32_t len = sizeof(*digest_buffer);
2339 int ret;
2340
2341 if (!ctx || !digest_buffer)
2342 return 0;
2343 ret = CRYPT_EAL_MdFinal(ctx, (uint8_t *)digest_buffer, &len) == CRYPT_SUCCESS &&
2344 len == sizeof(*digest_buffer);
2345 coap_digest_free(digest_ctx);
2346 return ret;
2347}
2348#endif /* COAP_SERVER_SUPPORT */
2349
2350#if COAP_WS_SUPPORT
2351static const struct {
2352 cose_alg_t alg;
2353 CRYPT_MD_AlgId md;
2354 uint32_t length;
2355} coap_hitls_hashs[] = {
2356 {COSE_ALGORITHM_SHA_1, CRYPT_MD_SHA1, 20},
2357 {COSE_ALGORITHM_SHA_256_64, CRYPT_MD_SHA256, 8},
2358 {COSE_ALGORITHM_SHA_256_256, CRYPT_MD_SHA256, 32},
2359 {COSE_ALGORITHM_SHA_512, CRYPT_MD_SHA512, 64},
2360};
2361
2362int
2364 const coap_bin_const_t *data,
2365 coap_bin_const_t **hash) {
2366 coap_binary_t *digest;
2367 uint32_t len;
2368 size_t i;
2369 CRYPT_MD_AlgId md = CRYPT_MD_SHA1;
2370 uint32_t out_len = 0;
2371
2372 if (!data || !hash || data->length > UINT32_MAX || !coap_hitls_startup())
2373 return 0;
2374 for (i = 0; i < sizeof(coap_hitls_hashs) / sizeof(coap_hitls_hashs[0]); i++) {
2375 if (coap_hitls_hashs[i].alg == alg) {
2376 md = coap_hitls_hashs[i].md;
2377 out_len = coap_hitls_hashs[i].length;
2378 break;
2379 }
2380 }
2381 if (out_len == 0) {
2382 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
2383 return 0;
2384 }
2385
2386 len = CRYPT_EAL_MdGetDigestSize(md);
2387 digest = coap_new_binary(len);
2388 if (!digest)
2389 return 0;
2390
2391 if (CRYPT_EAL_Md(md, data->s, (uint32_t)data->length,
2392 digest->s, &len) != CRYPT_SUCCESS ||
2393 len != digest->length) {
2394 coap_delete_binary(digest);
2395 return 0;
2396 }
2397 if (out_len < digest->length)
2398 digest->length = out_len;
2399
2400 *hash = (coap_bin_const_t *)digest;
2401 return 1;
2402}
2403#endif /* COAP_WS_SUPPORT */
2404
2405#if COAP_OSCORE_SUPPORT
2406
2407int
2409 return 1;
2410}
2411
2412static int
2413coap_hitls_get_cipher_alg(cose_alg_t alg, CRYPT_CIPHER_AlgId *cipher_alg,
2414 size_t *key_len) {
2415 switch ((int)alg) {
2417 if (cipher_alg)
2418 *cipher_alg = CRYPT_CIPHER_AES128_CCM;
2419 if (key_len)
2420 *key_len = 16;
2421 return 1;
2423 if (cipher_alg)
2424 *cipher_alg = CRYPT_CIPHER_AES256_CCM;
2425 if (key_len)
2426 *key_len = 32;
2427 return 1;
2428 default:
2429 coap_log_debug("coap_hitls_get_cipher_alg: COSE cipher %d not supported\n",
2430 alg);
2431 return 0;
2432 }
2433}
2434
2435static int
2436coap_hitls_get_hmac_alg(cose_hmac_alg_t hmac_alg, CRYPT_MAC_AlgId *mac_alg,
2437 size_t *mac_len) {
2438 switch ((int)hmac_alg) {
2440 if (mac_alg)
2441 *mac_alg = CRYPT_MAC_HMAC_SHA256;
2442 if (mac_len)
2444 return 1;
2446 if (mac_alg)
2447 *mac_alg = CRYPT_MAC_HMAC_SHA384;
2448 if (mac_len)
2450 return 1;
2452 if (mac_alg)
2453 *mac_alg = CRYPT_MAC_HMAC_SHA512;
2454 if (mac_len)
2456 return 1;
2457 default:
2458 coap_log_debug("coap_hitls_get_hmac_alg: COSE HMAC %d not supported\n",
2459 hmac_alg);
2460 return 0;
2461 }
2462}
2463
2464int
2466 return coap_hitls_get_cipher_alg(alg, NULL, NULL);
2467}
2468
2469int
2471 cose_hmac_alg_t hmac_alg;
2472
2473 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
2474 return 0;
2475 return coap_hitls_get_hmac_alg(hmac_alg, NULL, NULL);
2476}
2477
2478static int
2479coap_hitls_check_ccm_params(const coap_crypto_aes_ccm_t *ccm, size_t key_len) {
2480 if (!ccm || !ccm->key.s || !ccm->nonce || ccm->key.length != key_len)
2481 return 0;
2482 if (ccm->l == 0 || ccm->l > 8)
2483 return 0;
2484 if (ccm->tag_len == 0 || ccm->tag_len > UINT32_MAX)
2485 return 0;
2486 return 1;
2487}
2488
2489static int
2490coap_hitls_aead_set_common(CRYPT_EAL_CipherCtx *ctx,
2491 const coap_crypto_aes_ccm_t *ccm,
2492 const coap_bin_const_t *aad, uint64_t msg_len) {
2493 uint32_t tag_len = (uint32_t)ccm->tag_len;
2494 uint32_t aad_len = 0;
2495
2496 if (CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_TAGLEN,
2497 &tag_len, sizeof(tag_len)) != CRYPT_SUCCESS)
2498 return 0;
2499 if (CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_MSGLEN,
2500 &msg_len, sizeof(msg_len)) != CRYPT_SUCCESS)
2501 return 0;
2502 if (aad && aad->length) {
2503 if (aad->length > UINT32_MAX)
2504 return 0;
2505 aad_len = (uint32_t)aad->length;
2506 }
2507 return CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_AAD,
2508 aad_len ? (void *)(uintptr_t)aad->s : NULL,
2509 aad_len) == CRYPT_SUCCESS;
2510}
2511
2512int
2514 coap_bin_const_t *data,
2515 coap_bin_const_t *aad,
2516 uint8_t *result,
2517 size_t *max_result_len) {
2518 CRYPT_CIPHER_AlgId cipher_alg;
2519 CRYPT_EAL_CipherCtx *ctx = NULL;
2520 const coap_crypto_aes_ccm_t *ccm;
2521 size_t key_len;
2522 uint32_t out_len;
2523 uint32_t tag_len;
2524 uint64_t msg_len;
2525 int ret = 0;
2526
2527 if (!params || !data || !result || !max_result_len)
2528 return 0;
2529 if (!coap_hitls_get_cipher_alg(params->alg, &cipher_alg, &key_len))
2530 return 0;
2531
2532 ccm = &params->params.aes;
2533 if (!coap_hitls_check_ccm_params(ccm, key_len) ||
2534 data->length > UINT32_MAX ||
2535 ccm->tag_len > *max_result_len ||
2536 data->length > *max_result_len - ccm->tag_len ||
2537 !coap_hitls_startup())
2538 return 0;
2539
2540 ctx = CRYPT_EAL_CipherNewCtx(cipher_alg);
2541 if (!ctx)
2542 return 0;
2543
2544 out_len = (uint32_t)data->length;
2545 tag_len = (uint32_t)ccm->tag_len;
2546 msg_len = data->length;
2547 if (CRYPT_EAL_CipherInit(ctx, ccm->key.s, (uint32_t)ccm->key.length,
2548 ccm->nonce, (uint32_t)(15 - ccm->l),
2549 true) != CRYPT_SUCCESS)
2550 goto finish;
2551 if (!coap_hitls_aead_set_common(ctx, ccm, aad, msg_len))
2552 goto finish;
2553 if (CRYPT_EAL_CipherUpdate(ctx, data->s, (uint32_t)data->length,
2554 result, &out_len) != CRYPT_SUCCESS)
2555 goto finish;
2556 if (out_len != data->length)
2557 goto finish;
2558 if (CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_GET_TAG,
2559 result + out_len, tag_len) != CRYPT_SUCCESS)
2560 goto finish;
2561
2562 *max_result_len = (size_t)out_len + ccm->tag_len;
2563 ret = 1;
2564
2565finish:
2566 CRYPT_EAL_CipherFreeCtx(ctx);
2567 return ret;
2568}
2569
2570int
2572 coap_bin_const_t *data,
2573 coap_bin_const_t *aad,
2574 uint8_t *result,
2575 size_t *max_result_len) {
2576 CRYPT_CIPHER_AlgId cipher_alg;
2577 CRYPT_EAL_CipherCtx *ctx = NULL;
2578 const coap_crypto_aes_ccm_t *ccm;
2579 const uint8_t *tag;
2580 size_t key_len;
2581 size_t cipher_len;
2582 uint32_t out_len;
2583 uint32_t final_len;
2584 uint32_t tag_len;
2585 uint64_t msg_len;
2586 int ret = 0;
2587
2588 if (!params || !data || !result || !max_result_len)
2589 return 0;
2590 if (!coap_hitls_get_cipher_alg(params->alg, &cipher_alg, &key_len))
2591 return 0;
2592
2593 ccm = &params->params.aes;
2594 if (!coap_hitls_check_ccm_params(ccm, key_len) ||
2595 data->length < ccm->tag_len ||
2596 data->length > UINT32_MAX ||
2597 !coap_hitls_startup())
2598 return 0;
2599
2600 cipher_len = data->length - ccm->tag_len;
2601 if (*max_result_len < cipher_len)
2602 return 0;
2603
2604 ctx = CRYPT_EAL_CipherNewCtx(cipher_alg);
2605 if (!ctx)
2606 return 0;
2607
2608 tag = data->s + cipher_len;
2609 out_len = (uint32_t)cipher_len;
2610 final_len = 0;
2611 tag_len = (uint32_t)ccm->tag_len;
2612 msg_len = cipher_len;
2613 if (CRYPT_EAL_CipherInit(ctx, ccm->key.s, (uint32_t)ccm->key.length,
2614 ccm->nonce, (uint32_t)(15 - ccm->l),
2615 false) != CRYPT_SUCCESS)
2616 goto finish;
2617 if (!coap_hitls_aead_set_common(ctx, ccm, aad, msg_len))
2618 goto finish;
2619 if (CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_TAG,
2620 (void *)(uintptr_t)tag, tag_len) != CRYPT_SUCCESS)
2621 goto finish;
2622 if (CRYPT_EAL_CipherUpdate(ctx, data->s, (uint32_t)cipher_len,
2623 result, &out_len) != CRYPT_SUCCESS)
2624 goto finish;
2625 if (out_len != cipher_len)
2626 goto finish;
2627 if (CRYPT_EAL_CipherFinal(ctx, result, &final_len) != CRYPT_SUCCESS)
2628 goto finish;
2629 if (final_len != 0)
2630 goto finish;
2631
2632 *max_result_len = out_len;
2633 ret = 1;
2634
2635finish:
2636 CRYPT_EAL_CipherFreeCtx(ctx);
2637 return ret;
2638}
2639
2640int
2642 coap_bin_const_t *key,
2643 coap_bin_const_t *data,
2644 coap_bin_const_t **hmac) {
2645 CRYPT_MAC_AlgId mac_alg;
2646 CRYPT_EAL_MacCtx *ctx = NULL;
2648 size_t mac_len;
2649 uint32_t out_len;
2650 int ret = 0;
2651
2652 if (!key || !data || !hmac ||
2653 key->length > UINT32_MAX || data->length > UINT32_MAX ||
2654 !coap_hitls_get_hmac_alg(hmac_alg, &mac_alg, &mac_len) ||
2655 !coap_hitls_startup())
2656 return 0;
2657
2658 dummy = coap_new_binary(mac_len);
2659 if (!dummy)
2660 return 0;
2661
2662 ctx = CRYPT_EAL_MacNewCtx(mac_alg);
2663 if (!ctx)
2664 goto finish;
2665
2666 out_len = (uint32_t)dummy->length;
2667 if (CRYPT_EAL_MacInit(ctx, key->s, (uint32_t)key->length) != CRYPT_SUCCESS)
2668 goto finish;
2669 if (CRYPT_EAL_MacUpdate(ctx, data->s, (uint32_t)data->length) != CRYPT_SUCCESS)
2670 goto finish;
2671 if (CRYPT_EAL_MacFinal(ctx, dummy->s, &out_len) != CRYPT_SUCCESS ||
2672 out_len != dummy->length)
2673 goto finish;
2674
2675 *hmac = (coap_bin_const_t *)dummy;
2676 dummy = NULL;
2677 ret = 1;
2678
2679finish:
2680 CRYPT_EAL_MacFreeCtx(ctx);
2682 return ret;
2683}
2684
2685#endif /* COAP_OSCORE_SUPPORT */
2686
2687#if COAP_WITH_LIBOPENHITLS
2688#if COAP_CLIENT_SUPPORT
2689void *
2690coap_dtls_new_client_session(coap_session_t *session) {
2691 coap_hitls_env_t *env =
2692 coap_hitls_new_env(session, COAP_DTLS_ROLE_CLIENT, COAP_PROTO_DTLS);
2693
2694 session->tls = env;
2695 if (env && coap_hitls_handshake(session, env) < 0) {
2696 coap_hitls_free_env(env);
2697 session->tls = NULL;
2698 return NULL;
2699 }
2700 return env;
2701}
2702#endif /* COAP_CLIENT_SUPPORT */
2703
2704#if COAP_SERVER_SUPPORT
2705void *
2706coap_dtls_new_server_session(coap_session_t *session) {
2707 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
2708
2709 if (!env)
2710 return NULL;
2711 if (coap_hitls_handshake(session, env) < 0) {
2712 coap_hitls_free_env(env);
2713 session->tls = NULL;
2714 return NULL;
2715 }
2716 return env;
2717}
2718#endif /* COAP_SERVER_SUPPORT */
2719
2720void
2722 if (session && session->context && session->tls) {
2723 coap_hitls_free_env((coap_hitls_env_t *)session->tls);
2724 session->tls = NULL;
2726 }
2727}
2728
2729void
2731 if (session)
2732 coap_hitls_update_mtu((coap_hitls_env_t *)session->tls);
2733}
2734
2735ssize_t
2736coap_dtls_send(coap_session_t *session, const uint8_t *data, size_t data_len) {
2737 coap_hitls_env_t *env = (coap_hitls_env_t *)session->tls;
2738 uint32_t written = 0;
2739 int32_t ret;
2740
2741 if (!env || data_len > UINT32_MAX)
2742 return -1;
2743
2744 session->dtls_event = -1;
2745 coap_log_debug("* %s: dtls: sent %4d bytes\n",
2746 coap_session_str(session), (int)data_len);
2747 if (!env->established) {
2748 ret = coap_hitls_handshake(session, env);
2749 if (ret == 1)
2750 return coap_dtls_send(session, data, data_len);
2751 return ret == 0 ? 0 : -1;
2752 }
2753
2754 BSL_ERR_ClearError();
2755 ret = HITLS_Write(env->ctx, data, (uint32_t)data_len, &written);
2756 if (ret == HITLS_SUCCESS) {
2757 if (written == 0)
2758 return 0;
2759 return (ssize_t)written;
2760 }
2761 if (coap_hitls_is_retry(ret))
2762 return 0;
2763
2764 session->dtls_event = coap_hitls_is_closed(ret) ?
2766 if (session->dtls_event == COAP_EVENT_DTLS_ERROR) {
2767 coap_log_warn("coap_dtls_send: returned 0x%x\n", (unsigned int)ret);
2768 coap_hitls_log_fatal_err_stack(session);
2769 }
2770 coap_handle_event_lkd(session->context, session->dtls_event, session);
2771 return -1;
2772}
2773
2774int
2776 return 0;
2777}
2778
2780coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED) {
2781 return 0;
2782}
2783
2786 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
2787 uint64_t timeout_us = 0;
2788 int32_t ret;
2789
2790 if (!env)
2791 return 0;
2792 ret = HITLS_DtlsGetTimeout(env->ctx, &timeout_us);
2793 if (ret == HITLS_MSG_HANDLE_ERR_WITHOUT_TIMEOUT_ACTION)
2794 return 0;
2795 if (ret != HITLS_SUCCESS) {
2796 coap_log_warn("HITLS_DtlsGetTimeout() returned 0x%x\n",
2797 (unsigned int)ret);
2798 return 0;
2799 }
2800 if (timeout_us == 0) {
2801 /*
2802 * Timer already due: pace it so one I/O cycle does not fire DTLS timeouts
2803 * back-to-back and exhaust dtls_timeout_count prematurely.
2804 */
2805 if (env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS > now)
2806 return env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS;
2807 env->last_timeout = now;
2808 return now;
2809 }
2810 return now + (coap_tick_t)((timeout_us * COAP_TICKS_PER_SECOND + 999999) /
2811 1000000);
2812}
2813
2814int
2816 coap_hitls_env_t *env = (coap_hitls_env_t *)session->tls;
2817 int32_t ret;
2818
2819 if (!env)
2820 return 1;
2821 if (++session->dtls_timeout_count > session->max_retransmit) {
2823 return 1;
2824 }
2825
2826 BSL_ERR_ClearError();
2827 ret = HITLS_DtlsProcessTimeout(env->ctx);
2828 if (ret == HITLS_SUCCESS ||
2829 ret == HITLS_MSG_HANDLE_DTLS_RETRANSMIT_NOT_TIMEOUT ||
2830 coap_hitls_is_retry(ret))
2831 return 0;
2832
2833 coap_log_warn("HITLS_DtlsProcessTimeout() returned 0x%x\n",
2834 (unsigned int)ret);
2835 coap_hitls_log_fatal_err_stack(session);
2837 return 1;
2838}
2839
2840int
2841coap_dtls_receive(coap_session_t *session, const uint8_t *data,
2842 size_t data_len) {
2843 coap_hitls_env_t *env = (coap_hitls_env_t *)session->tls;
2844 int ret = -1;
2845
2846 if (!env)
2847 return -1;
2848 if (env->pdu_len)
2849 coap_log_err("** %s: Previous data not read %" PRIuS " bytes\n",
2850 coap_session_str(session), env->pdu_len);
2851
2852 session->dtls_event = -1;
2853 env->pdu = data;
2854 env->pdu_len = data_len;
2855
2856 if (env->established) {
2857#if COAP_CONSTRAINED_STACK
2858 static uint8_t pdu[COAP_RXBUFFER_SIZE];
2859#else /* ! COAP_CONSTRAINED_STACK */
2860 uint8_t pdu[COAP_RXBUFFER_SIZE];
2861#endif /* ! COAP_CONSTRAINED_STACK */
2862 uint32_t read_len = 0;
2863 int32_t hret;
2864
2865 BSL_ERR_ClearError();
2866 hret = HITLS_Read(env->ctx, pdu, sizeof(pdu), &read_len);
2867
2868 if (hret == HITLS_SUCCESS && read_len > 0) {
2869 coap_log_debug("* %s: dtls: recv %4d bytes\n",
2870 coap_session_str(session), (int)read_len);
2871 ret = coap_handle_dgram(session->context, session, pdu, read_len);
2872 goto finish;
2873 }
2874 if (hret == HITLS_SUCCESS || coap_hitls_is_retry(hret)) {
2875 ret = -1;
2876 goto finish;
2877 }
2878 session->dtls_event = coap_hitls_is_closed(hret) ?
2880 if (session->dtls_event == COAP_EVENT_DTLS_ERROR) {
2881 coap_log_warn("coap_dtls_receive: returned 0x%x (length %" PRIdS ")\n",
2882 (unsigned int)hret, data_len);
2883 coap_hitls_log_fatal_err_stack(session);
2884 }
2885 } else {
2886 /*
2887 * On completion coap_hitls_set_connected() drives l_establish(); on error
2888 * session->dtls_event is set and handled below, so the handshake return
2889 * value is not needed here.
2890 */
2891 (void)coap_hitls_handshake(session, env);
2892 ret = -1;
2893 }
2894
2895 if (session->dtls_event >= 0) {
2896 coap_handle_event_lkd(session->context, session->dtls_event, session);
2897 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2898 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2900 ret = -1;
2901 }
2902 }
2903
2904finish:
2905 coap_hitls_clear_pdu(coap_hitls_live_env(session, env));
2906 return ret;
2907}
2908
2909#if COAP_SERVER_SUPPORT
2910int
2911coap_dtls_hello(coap_session_t *session, const uint8_t *data,
2912 size_t data_len) {
2913 coap_hitls_env_t *env = (coap_hitls_env_t *)session->tls;
2914 int32_t ret;
2915 int cookie_valid = 0;
2916
2917 if (!env) {
2918 env = coap_hitls_new_env(session, COAP_DTLS_ROLE_SERVER, COAP_PROTO_DTLS);
2919 if (!env)
2920 return -1;
2921 session->tls = env;
2922 }
2923
2924 env->pdu = data;
2925 env->pdu_len = data_len;
2926
2927 if (!env->hello_verify_sent) {
2928 BSL_ERR_ClearError();
2929 ret = HITLS_Listen(env->ctx, &session->addr_info.remote.addr.sa);
2930 if (env->pdu_len) {
2931 coap_log_debug("coap_dtls_hello: ret 0x%x: remaining data %" PRIuS "\n",
2932 (unsigned int)ret, env->pdu_len);
2933 }
2934 coap_hitls_clear_pdu(env);
2935
2936 if (ret == HITLS_SUCCESS)
2937 return 1;
2938 if (coap_hitls_is_retry(ret)) {
2939 /* HITLS_Listen emits HelloVerifyRequest; Accept flushes it. */
2940 ret = coap_hitls_handshake(session, env);
2941 if (ret < 0)
2942 return -1;
2943 env = coap_hitls_live_env(session, env);
2944 if (!env)
2945 return -1;
2946 env->hello_verify_sent = 1;
2947 return 0;
2948 }
2949
2950 coap_log_warn("coap_dtls_hello: returned 0x%x\n", (unsigned int)ret);
2951 coap_hitls_log_fatal_err_stack(session);
2953 return -1;
2954 }
2955
2956 cookie_valid = coap_hitls_client_hello_cookie_valid(session, data, data_len);
2957 ret = coap_hitls_handshake(session, env);
2958 env = coap_hitls_live_env(session, env);
2959 coap_hitls_clear_pdu(env);
2960
2961 if (ret < 0 || !env)
2962 return -1;
2963 return cookie_valid == 1 ? 1 : 0;
2964}
2965#endif /* COAP_SERVER_SUPPORT */
2966
2967unsigned int
2969 return COAP_HITLS_DTLS_OVERHEAD;
2970}
2971
2972#if !COAP_DISABLE_TCP
2973#if COAP_CLIENT_SUPPORT
2974void *
2975coap_tls_new_client_session(coap_session_t *session) {
2976 coap_hitls_env_t *env =
2977 coap_hitls_new_env(session, COAP_DTLS_ROLE_CLIENT, COAP_PROTO_TLS);
2978
2979 session->tls = env;
2980 if (env && coap_hitls_handshake(session, env) < 0) {
2981 coap_hitls_free_env(env);
2982 session->tls = NULL;
2983 return NULL;
2984 }
2985 return env;
2986}
2987#endif /* COAP_CLIENT_SUPPORT */
2988
2989#if COAP_SERVER_SUPPORT
2990void *
2991coap_tls_new_server_session(coap_session_t *session) {
2992 coap_hitls_env_t *env =
2993 coap_hitls_new_env(session, COAP_DTLS_ROLE_SERVER, COAP_PROTO_TLS);
2994
2995 session->tls = env;
2996 if (env && coap_hitls_handshake(session, env) < 0) {
2997 coap_hitls_free_env(env);
2998 session->tls = NULL;
2999 return NULL;
3000 }
3001 return env;
3002}
3003#endif /* COAP_SERVER_SUPPORT */
3004
3005void
3007 coap_dtls_free_session(session);
3008}
3009
3010static void
3011coap_hitls_tcp_want(coap_session_t *session, HITLS_Ctx *ctx) {
3012 uint8_t rwstate = HITLS_NOTHING;
3013
3014 (void)HITLS_GetRwstate(ctx, &rwstate);
3015 if (rwstate == HITLS_WRITING) {
3016 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3017#ifdef COAP_EPOLL_SUPPORT
3018 coap_epoll_ctl_mod(&session->sock,
3019 EPOLLOUT |
3020 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3021 EPOLLIN : 0),
3022 __func__);
3023#endif /* COAP_EPOLL_SUPPORT */
3024 } else {
3025 session->sock.flags |= COAP_SOCKET_WANT_READ;
3026 }
3027}
3028
3029ssize_t
3031 const uint8_t *data,
3032 size_t data_len) {
3033 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
3034 uint32_t written = 0;
3035 int32_t ret;
3036
3037 if (!env || data_len > UINT32_MAX) {
3038 errno = ENXIO;
3039 return -1;
3040 }
3041
3042 session->dtls_event = -1;
3043 if (!env->established) {
3044 ret = coap_hitls_handshake(session, env);
3045 if (ret < 0)
3046 return -1;
3047 if (ret == 0)
3048 coap_hitls_tcp_want(session, env->ctx);
3049 return 0;
3050 }
3051
3052 BSL_ERR_ClearError();
3053 ret = HITLS_Write(env->ctx, data, (uint32_t)data_len, &written);
3054 if (ret == HITLS_SUCCESS) {
3055 if (written > 0) {
3056 if (written == data_len)
3057 coap_log_debug("* %s: tls: sent %4d bytes\n",
3058 coap_session_str(session), (int)written);
3059 else
3060 coap_log_debug("* %s: tls: sent %4d of %4" PRIdS " bytes\n",
3061 coap_session_str(session), (int)written, data_len);
3062 }
3063 return (ssize_t)written;
3064 }
3065 if (coap_hitls_is_retry(ret)) {
3066 coap_hitls_tcp_want(session, env->ctx);
3067 return 0;
3068 }
3069
3070 session->dtls_event = coap_hitls_is_closed(ret) ?
3072 if (session->dtls_event == COAP_EVENT_DTLS_ERROR) {
3073 coap_log_warn("coap_tls_write: returned 0x%x\n", (unsigned int)ret);
3074 coap_hitls_log_fatal_err_stack(session);
3075 }
3076 coap_handle_event_lkd(session->context, session->dtls_event, session);
3077 return -1;
3078}
3079
3080ssize_t
3082 uint8_t *data,
3083 size_t data_len) {
3084 coap_hitls_env_t *env = session ? (coap_hitls_env_t *)session->tls : NULL;
3085 uint32_t read_len = 0;
3086 int32_t ret;
3087
3088 if (!env || data_len > UINT32_MAX) {
3089 errno = ENXIO;
3090 return -1;
3091 }
3092
3093 session->dtls_event = -1;
3094 if (!env->established) {
3095 ret = coap_hitls_handshake(session, env);
3096 if (ret < 0)
3097 return -1;
3098 if (ret == 0)
3099 coap_hitls_tcp_want(session, env->ctx);
3100 return 0;
3101 }
3102
3103 BSL_ERR_ClearError();
3104 ret = HITLS_Read(env->ctx, data, (uint32_t)data_len, &read_len);
3105 if (ret == HITLS_SUCCESS) {
3106 if (read_len > 0)
3107 coap_log_debug("* %s: tls: recv %4d bytes\n",
3108 coap_session_str(session), (int)read_len);
3109 return (ssize_t)read_len;
3110 }
3111 if (coap_hitls_is_retry(ret)) {
3112 coap_hitls_tcp_want(session, env->ctx);
3113 errno = EAGAIN;
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_read: returned 0x%x (length %" PRIdS ")\n",
3121 (unsigned int)ret, data_len);
3122 coap_hitls_log_fatal_err_stack(session);
3123 }
3124 coap_handle_event_lkd(session->context, session->dtls_event, session);
3125 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3128 return -1;
3129}
3130#endif /* !COAP_DISABLE_TCP */
3131#endif /* COAP_WITH_LIBOPENHITLS */
3132
3133#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:190
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:5279
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:3136
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:165
coap_define_issue_key_t
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
union coap_address_t::@241131003127110116114041001244025354034075356365 addr
socklen_t size
size of addr
struct sockaddr sa
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::@376202006114157036213053136012210003017006234156 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
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:285
union coap_dtls_key_t::@003017313271040156213200302176016051164315363211 key
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