tls_mbed_funcs.c (49365B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2025 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file src/mhd2/tls_mbed_funcs.c 41 * @brief The implementation of MbedTLS wrapper functions 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 /* A few macros can be defined at MHD build-time to adjust code interfacing 46 with MbedTLS library: 47 - MHD_TLS_MBED_USE_PSA_FREE 48 - MHD_TLS_MBED_PREF_RNG_PSA 49 - MHD_TLS_MBED_PREF_RNG_HMAC 50 - MHD_TLS_MBED_PREF_RNG_CTR 51 - MHD_TLS_MBED_SKIP_PLATFORM_SETUP 52 - MHD_TLS_MBED_USE_PLATFORM_TEARDOWN 53 - MHD_TLS_MBED_SKIP_CERT_KEY_MATCH_CHECK 54 - MHD_TLS_MBED_DBG_PRINT_LEVEL 55 See macros use in this file and in tls_mbed_tls_lib.h. 56 Macros can be defined, for example, by CPPFLAGS before run of the configure. 57 */ 58 59 #include "mhd_sys_options.h" 60 61 #include "sys_bool_type.h" 62 #include "sys_base_types.h" 63 64 #include "compat_calloc.h" 65 #include "sys_malloc.h" 66 #include <string.h> 67 68 #ifdef mhd_USE_TLS_DEBUG_MESSAGES 69 # include <stdio.h> /* For TLS debug printing */ 70 #endif 71 72 #include "mhd_assert.h" 73 #include "mhd_unreachable.h" 74 #include "mhd_assume.h" 75 76 #include "mhd_constexpr.h" 77 #include "mhd_arr_num_elems.h" 78 79 #include "mhd_conn_socket.h" 80 81 #include "mhd_tls_internal.h" 82 83 #include "tls_mbed_tls_lib.h" 84 85 #include "mhd_public_api.h" 86 87 #include "mhd_tls_ver_stct.h" 88 89 #include "daemon_logger.h" 90 91 #include "daemon_options.h" 92 93 #include "sckt_recv.h" 94 #include "sckt_send.h" 95 96 #include "tls_mbed_daemon_data.h" 97 #include "tls_mbed_conn_data.h" 98 #include "tls_mbed_funcs.h" 99 100 #if defined(mhd_USE_TLS_DEBUG_MESSAGES) && defined(MBEDTLS_DEBUG_C) 101 # define mhd_TLS_MBED_HAS_DEBUG_PRINT 1 102 103 /* MHD_TLS_MBED_DBG_PRINT_LEVEL can be defined to number in range 0..5, 104 where 5 is the most detailed log */ 105 # ifdef MHD_TLS_MBED_DBG_PRINT_LEVEL 106 # define mhd_DBG_PRINT_LEVEL (MHD_TLS_MBED_DBG_PRINT_LEVEL + 0) 107 # else 108 # define mhd_DBG_PRINT_LEVEL (2) 109 # endif 110 111 static void 112 mhd_tls_mbed_debug_print (void *ctx, 113 int level, 114 const char *filename, 115 int line_num, 116 const char *msg) 117 { 118 (void)ctx; /* Unused */ 119 /* The level should be pre-filtred by MbedTLS, but it is filtered again 120 here in case if something else changed it. */ 121 if (mhd_DBG_PRINT_LEVEL < level) 122 return; 123 (void)fprintf (stderr, "## MbedTLS %02i [%s:%d]: %s", 124 level, 125 filename, 126 line_num, 127 msg); 128 (void)fflush (stderr); 129 } 130 131 132 #endif /* mhd_USE_TLS_DEBUG_MESSAGES && MBEDTLS_DEBUG_C */ 133 134 135 /* ** Global initialisation / de-initialisation ** */ 136 137 #ifdef MHD_TLS_MBED_PREF_RNG_HMAC 138 static const mbedtls_md_info_t * 139 mbed_get_md_for_drbg (void) 140 { 141 mhd_constexpr mbedtls_md_type_t mds[] = { 142 # ifdef mhd_TLS_MBED_HAS_SHA3_IDS 143 MBEDTLS_MD_SHA3_256 144 , 145 # endif /* mhd_TLS_MBED_HAS_SHA3_IDS */ 146 MBEDTLS_MD_SHA256 147 # ifdef mhd_TLS_MBED_HAS_SHA3_IDS 148 , 149 MBEDTLS_MD_SHA3_512 150 # endif /* mhd_TLS_MBED_HAS_SHA3_IDS */ 151 , 152 MBEDTLS_MD_SHA512 153 # ifdef mhd_TLS_MBED_HAS_SHA3_IDS 154 , 155 MBEDTLS_MD_SHA3_384 156 # endif /* mhd_TLS_MBED_HAS_SHA3_IDS */ 157 , 158 MBEDTLS_MD_SHA384 159 # ifdef mhd_TLS_MBED_HAS_SHA3_IDS 160 , 161 MBEDTLS_MD_SHA3_224 162 # endif /* mhd_TLS_MBED_HAS_SHA3_IDS */ 163 , 164 MBEDTLS_MD_SHA224 165 }; 166 size_t i; 167 168 for (i = 0; i < mhd_ARR_NUM_ELEMS (mds); ++i) 169 { 170 const mbedtls_md_info_t *const ret = 171 mbedtls_md_info_from_type (mds[i]); 172 if (NULL != ret) 173 return ret; 174 } 175 176 return (const mbedtls_md_info_t *)NULL; 177 } 178 179 180 #endif /* MHD_TLS_MBED_PREF_RNG_HMAC */ 181 182 static bool mbedtls_lib_inited_now = false; 183 /* Must be checked when MHD-internal random generator is used */ 184 static bool mbedtls_rng_inited_now = false; 185 static bool mbedtls_lib_inited_once = false; 186 187 #ifdef mhd_TLS_MBED_HAS_PLATFORM_SETUP 188 static mbedtls_platform_context mhd_mbed_plat_ctx; 189 #endif /* mhd_TLS_MBED_HAS_PLATFORM_SETUP */ 190 191 #if defined(mhd_TLS_MBED_USE_LIB_ENTROPY) 192 static mbedtls_entropy_context mhd_mbed_entr_ctx; 193 #endif /* mhd_TLS_MBED_USE_LIB_ENTROPY */ 194 195 #if defined(MHD_TLS_MBED_PREF_RNG_CTR) 196 static mbedtls_ctr_drbg_context mhd_mbed_ctr_drbg_ctx; 197 #elif defined(MHD_TLS_MBED_PREF_RNG_HMAC) 198 static mbedtls_hmac_drbg_context mhd_mbed_hmac_drbg_ctx; 199 #endif /* MHD_TLS_MBED_PREF_RNG_HMAC */ 200 201 static bool 202 mbed_rng_init (void) 203 { 204 #ifdef mhd_TLS_MBED_RNG_PREF_NEEDS_ENTROPY 205 int (*entropy_cb)(void *ctx, unsigned char *out, size_t out_size); 206 void *entropy_cb_ctx; 207 208 # ifdef mhd_TLS_MBED_USE_LIB_ENTROPY 209 mbedtls_entropy_init (&mhd_mbed_entr_ctx); 210 entropy_cb = &mbedtls_entropy_func; 211 entropy_cb_ctx = &mhd_mbed_entr_ctx; 212 # else /* ! mhd_TLS_MBED_USE_LIB_ENTROPY */ 213 /* Seeding with system's entropy sources could be implemented here */ 214 # error MbedTLS random generator needs entropy sources 215 # endif /* ! mhd_TLS_MBED_USE_LIB_ENTROPY */ 216 #endif /* mhd_TLS_MBED_RNG_PREF_NEEDS_ENTROPY */ 217 218 mhd_assert (!mbedtls_rng_inited_now); 219 220 if (1) /* For local scope only */ 221 { 222 #ifdef mhd_TLS_MBED_RNG_PREF_NEEDS_ENTROPY 223 static const char id_str[] = "libmicrohttpd2"; 224 static uint_fast64_t init_cntr = 0u; 225 static void *uniq_ptr1 = &init_cntr; /* Any address should be unique in the same address space */ 226 void *uniq_ptr2 = &uniq_ptr2; /* Any address should be unique in the same address space */ 227 unsigned char pers[sizeof(id_str) 228 + sizeof(uniq_ptr1) 229 + sizeof(uniq_ptr2) 230 + sizeof(init_cntr)]; 231 232 memcpy (pers, 233 id_str, 234 sizeof(id_str)); 235 memcpy (pers + sizeof(id_str), 236 &uniq_ptr1, 237 sizeof(uniq_ptr1)); 238 memcpy (pers + sizeof(id_str) + sizeof(uniq_ptr1), 239 &uniq_ptr2, 240 sizeof(uniq_ptr2)); 241 memcpy (pers + sizeof(id_str) + sizeof(uniq_ptr1) + sizeof(uniq_ptr2), 242 &init_cntr, 243 sizeof(init_cntr)); 244 ++init_cntr; 245 #endif /* mhd_TLS_MBED_RNG_PREF_NEEDS_ENTROPY */ 246 247 #if defined(MHD_TLS_MBED_PREF_RNG_CTR) 248 mbedtls_ctr_drbg_init (&mhd_mbed_ctr_drbg_ctx); 249 mbedtls_rng_inited_now = 250 (0 == mbedtls_ctr_drbg_seed (&mhd_mbed_ctr_drbg_ctx, 251 entropy_cb, 252 entropy_cb_ctx, 253 pers, 254 sizeof(pers))); 255 if (!mbedtls_rng_inited_now) 256 mbedtls_ctr_drbg_free (&mhd_mbed_ctr_drbg_ctx); 257 #elif defined(MHD_TLS_MBED_PREF_RNG_HMAC) 258 mbedtls_hmac_drbg_init (&mhd_mbed_hmac_drbg_ctx); 259 mbedtls_rng_inited_now = 260 (0 == mbedtls_hmac_drbg_seed (&mhd_mbed_hmac_drbg_ctx, 261 mbed_get_md_for_drbg (), /* NULL is handled by mbedtls_hmac_drbg_seed() */ 262 entropy_cb, 263 entropy_cb_ctx, 264 pers, 265 sizeof(pers))); 266 if (!mbedtls_rng_inited_now) 267 mbedtls_hmac_drbg_free (&mhd_mbed_hmac_drbg_ctx); 268 #elif defined(MHD_TLS_MBED_PREF_RNG_PSA) 269 mbedtls_rng_inited_now = true; /* No additional initialisation needed */ 270 #elif !defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 271 mbedtls_rng_inited_now = false; 272 #else /* mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 273 # error MbedTLS backend requires random generator 274 /* Support for external strong random generator could be added */ 275 mbedtls_rng_inited_now = false; 276 #endif 277 if (mbedtls_rng_inited_now) 278 return true; /* Success exit point */ 279 } 280 281 #ifdef mhd_TLS_MBED_USE_LIB_ENTROPY 282 mbedtls_entropy_free (&mhd_mbed_entr_ctx); 283 #endif /* mhd_TLS_MBED_USE_LIB_ENTROPY */ 284 285 return false; /* Failure exit point */ 286 } 287 288 289 static void 290 mbed_rng_deinit (void) 291 { 292 if (!mbedtls_rng_inited_now) 293 return; 294 295 #if defined(MHD_TLS_MBED_PREF_RNG_CTR) 296 mbedtls_ctr_drbg_free (&mhd_mbed_ctr_drbg_ctx); 297 #elif defined(MHD_TLS_MBED_PREF_RNG_HMAC) 298 mbedtls_hmac_drbg_free (&mhd_mbed_hmac_drbg_ctx); 299 #endif 300 301 #ifdef mhd_TLS_MBED_USE_LIB_ENTROPY 302 mbedtls_entropy_free (&mhd_mbed_entr_ctx); 303 #endif /* mhd_TLS_MBED_USE_LIB_ENTROPY */ 304 305 mbedtls_rng_inited_now = false; 306 } 307 308 309 MHD_INTERNAL void 310 mhd_tls_mbed_global_init (void) 311 { 312 #ifdef MBEDTLS_VERSION_C 313 if (1) 314 { 315 const unsigned int ver = mbedtls_version_get_number (); 316 if (MBEDTLS_VERSION_NUMBER > ver) 317 return; /* Run-time version is lower than build-time version */ 318 if (((MBEDTLS_VERSION_NUMBER) >> 24u) != (ver >> 24u)) 319 return; /* Run-time major version does not match build-time major version */ 320 } 321 #endif /* MBEDTLS_VERSION_C */ 322 323 #ifdef mhd_TLS_MBED_HAS_PLATFORM_SETUP 324 # ifdef mhd_TLS_MBED_USE_PLATFORM_TEARDOWN 325 /* 'setup' platform repeatedly only only if 'teardown' is called */ 326 if (mbedtls_lib_inited_once) 327 (void)0; /* Do not repeat 'setup' */ 328 else /* combined with tne next 'if()' */ 329 # endif /* mhd_TLS_MBED_USE_PLATFORM_TEARDOWN */ 330 if (0 != mbedtls_platform_setup (&mhd_mbed_plat_ctx)) 331 return; /* Error platform initialising */ 332 #endif /* mhd_TLS_MBED_HAS_PLATFORM_SETUP */ 333 334 #ifdef mhd_TLS_MBED_USE_PSA 335 /* It is safe to call psa_crypto_init() several times */ 336 if (PSA_SUCCESS != psa_crypto_init ()) 337 { 338 # ifdef mhd_TLS_MBED_USE_PLATFORM_TEARDOWN 339 mbedtls_platform_teardown (&mhd_mbed_plat_ctx); 340 # endif /* mhd_TLS_MBED_USE_PLATFORM_TEARDOWN */ 341 return; 342 } 343 #endif /* mhd_TLS_MBED_USE_PSA */ 344 mbedtls_lib_inited_once = true; 345 346 #if mhd_TLS_MBED_INIT_TLS_REQ_RNG 347 mbedtls_lib_inited_now = mbed_rng_init (); 348 #else /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 349 (void)mbed_rng_init (); 350 mbedtls_lib_inited_now = true; /* MbedTLS could be used even without random generator */ 351 #endif /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 352 353 if (!mbedtls_lib_inited_now) 354 { 355 #ifdef mhd_TLS_MBED_USE_PLATFORM_TEARDOWN 356 mbedtls_platform_teardown (&mhd_mbed_plat_ctx); 357 #endif /* mhd_TLS_MBED_USE_PLATFORM_TEARDOWN */ 358 359 #ifdef mhd_TLS_MBED_USE_PSA_FREE 360 mbedtls_psa_crypto_free (); 361 #endif /* mhd_TLS_MBED_USE_PLATFORM_TEARDOWN */ 362 (void)0; 363 } 364 } 365 366 367 MHD_INTERNAL void 368 mhd_tls_mbed_global_deinit (void) 369 { 370 if (!mbedtls_lib_inited_now) 371 return; 372 373 mbed_rng_deinit (); 374 375 #ifdef mhd_TLS_MBED_USE_PSA_FREE 376 /* Not used by default as it will break all calls to PSA performed 377 directly by the application after closing all active MHD daemons */ 378 mbedtls_psa_crypto_free (); 379 #endif /* mhd_TLS_MBED_USE_PLATFORM_TEARDOWN */ 380 381 #ifdef mhd_TLS_MBED_USE_PLATFORM_TEARDOWN 382 /* Not used by default as it will break all calls to MbedTLS performed 383 directly by the application after closing all active MHD daemons */ 384 mbedtls_platform_teardown (&mhd_mbed_plat_ctx); 385 #endif /* mhd_TLS_MBED_USE_PLATFORM_TEARDOWN */ 386 387 mbedtls_lib_inited_now = false; 388 } 389 390 391 MHD_INTERNAL MHD_FN_PURE_ bool 392 mhd_tls_mbed_is_inited_fine (void) 393 { 394 mhd_assert (!mbedtls_lib_inited_now || mbedtls_lib_inited_once); 395 return mbedtls_lib_inited_now; 396 } 397 398 399 /* ** Daemon initialisation / de-initialisation ** */ 400 401 /** 402 * Check application-provided daemon TLS settings 403 * @param d the daemon handle 404 * @param s the application-provided settings 405 * @return #MHD_SC_OK on success, 406 * error code otherwise 407 */ 408 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 409 check_app_tls_settings (struct MHD_Daemon *restrict d, 410 struct DaemonOptions *restrict s) 411 { 412 mhd_assert (MHD_TLS_BACKEND_NONE != s->tls); 413 mhd_assert ((MHD_TLS_BACKEND_MBEDTLS == s->tls) \ 414 || (MHD_TLS_BACKEND_ANY == s->tls)); 415 416 if (NULL == s->tls_cert_key.v_mem_cert) 417 { 418 mhd_LOG_MSG (d, MHD_SC_TLS_CONF_BAD_CERT, \ 419 "No valid TLS certificate is provided"); 420 return MHD_SC_TLS_CONF_BAD_CERT; 421 } 422 mhd_assert (NULL != s->tls_cert_key.v_mem_key); 423 424 if ((MHD_WM_THREAD_PER_CONNECTION == s->work_mode.mode) 425 || ((MHD_WM_WORKER_THREADS == s->work_mode.mode) 426 && (1u < s->work_mode.params.num_worker_threads))) 427 { 428 bool threads_supported; 429 #if !defined(MBEDTLS_THREADING_C) 430 threads_supported = false; 431 #else /* MBEDTLS_THREADING_C */ 432 # if defined(MBEDTLS_VERSION_FEATURES) 433 threads_supported = 434 (0 == mbedtls_version_check_feature ("MBEDTLS_THREADING_C")); 435 # else /* ! MBEDTLS_VERSION_FEATURES */ 436 threads_supported = true; 437 # endif /* ! MBEDTLS_VERSION_FEATURES */ 438 #endif /* MBEDTLS_THREADING_C */ 439 if (!threads_supported) 440 { 441 mhd_LOG_MSG (d, MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS, \ 442 "MbedTLS built without threading support and cannot " 443 "be used in multi-threaded modes"); 444 return MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS; 445 } 446 } 447 448 #ifdef mhd_HAVE_TLS_ACME 449 if (!mhd_tls_mbed_is_acme_alpn_supported (s) 450 && s->acme_alpn_required) 451 { 452 mhd_LOG_MSG (d, MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS, 453 "This build of MbedTLS backend does not support " 454 "ACME ALPN challenge protocol, but daemon settings " 455 "require it"); 456 return MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS; 457 } 458 #endif 459 460 return MHD_SC_OK; 461 } 462 463 464 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 465 /** 466 * Set daemon TLS credentials. 467 * This function puts error messages to the log if needed. 468 * @param d the daemon handle 469 * @param d_tls the daemon TLS settings 470 * @param s the application-provided settings 471 * @param rng_func the random generator function 472 * @param rng_ctx the random generator function context 473 * @return #MHD_SC_OK on success, 474 * error code otherwise 475 */ 476 #else /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 477 /** 478 * Set daemon TLS credentials. 479 * This function puts error messages to the log if needed. 480 * @param d the daemon handle 481 * @param d_tls the daemon TLS settings 482 * @param s the application-provided settings 483 * @return #MHD_SC_OK on success, 484 * error code otherwise 485 */ 486 #endif /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 487 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 488 MHD_FN_PAR_NONNULL_ (3) MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 489 daemon_init_credentials ( 490 struct MHD_Daemon *restrict d, 491 struct mhd_TlsMbedDaemonData *restrict d_tls, 492 struct DaemonOptions *restrict s 493 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 494 , 495 int (*rng_func)(void *ctx, unsigned char *out, size_t out_size), 496 void *rng_ctx 497 #endif /* mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 498 ) 499 { 500 enum MHD_StatusCode ret; 501 size_t cert_len; 502 size_t key_len; 503 size_t pwd_len; 504 int res; 505 506 ret = MHD_SC_OK; 507 508 // TODO: Support multiple certificates 509 cert_len = strlen (s->tls_cert_key.v_mem_cert); // TODO: Reuse calculated length 510 key_len = strlen (s->tls_cert_key.v_mem_key); // TODO: Reuse calculated length 511 pwd_len = (NULL == s->tls_cert_key.v_mem_pass) ? 512 0u : strlen (s->tls_cert_key.v_mem_pass); // TODO: Reuse calculated length 513 514 mhd_assert (0 != cert_len); 515 mhd_assert (0 != key_len); 516 517 mbedtls_x509_crt_init (&(d_tls->cert_chain)); 518 519 res = mbedtls_x509_crt_parse (&(d_tls->cert_chain), 520 (const unsigned char *) 521 s->tls_cert_key.v_mem_cert, 522 cert_len + 1u /* Include terminating zero */); 523 if (0 == res) 524 { 525 mbedtls_pk_init (&(d_tls->prv_key)); 526 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 527 if (0 != mbedtls_pk_parse_key (&(d_tls->prv_key), 528 (const unsigned char *) 529 s->tls_cert_key.v_mem_key, 530 key_len + 1u, 531 (const unsigned char *) 532 s->tls_cert_key.v_mem_pass, 533 pwd_len, 534 rng_func, 535 rng_ctx)) 536 ret = MHD_SC_TLS_CONF_BAD_CERT; 537 #else /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 538 if (0 != mbedtls_pk_parse_key (&(d_tls->prv_key), 539 (const unsigned char *) 540 s->tls_cert_key.v_mem_key, 541 key_len + 1u, 542 (const unsigned char *) 543 s->tls_cert_key.v_mem_pass, 544 pwd_len)) 545 ret = MHD_SC_TLS_CONF_BAD_CERT; 546 #endif /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 547 548 if (MHD_SC_OK == ret) 549 { 550 /* The next macro can be defined at MHD build-time to skip potentially 551 expensive check */ 552 #ifdef MHD_TLS_MBED_SKIP_CERT_KEY_MATCH_CHECK 553 return MHD_SC_OK; /* Success exit point */ 554 #else /* ! MHD_TLS_MBED_SKIP_CERT_KEY_MATCH_CHECK */ 555 # if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 556 res = mbedtls_pk_check_pair (&(d_tls->cert_chain.pk), 557 &(d_tls->prv_key), 558 rng_func, 559 rng_ctx); 560 # else /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 561 res = mbedtls_pk_check_pair (&(d_tls->cert_chain.pk), 562 &(d_tls->prv_key)); 563 # endif /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 564 if ((0 == res) 565 || (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE == res)) 566 return MHD_SC_OK; /* Success exit point */ 567 568 mhd_LOG_MSG (d, MHD_SC_TLS_CONF_BAD_CERT, \ 569 "The private key data does not match the certificate"); 570 ret = MHD_SC_TLS_CONF_BAD_CERT; 571 #endif /* ! MHD_TLS_MBED_SKIP_CERT_KEY_MATCH_CHECK */ 572 } 573 else 574 { 575 mhd_LOG_MSG (d, MHD_SC_TLS_CONF_BAD_CERT, \ 576 "The private key data cannot be decoded"); 577 ret = MHD_SC_TLS_CONF_BAD_CERT; 578 } 579 580 mbedtls_pk_free (&(d_tls->prv_key)); 581 } 582 else 583 { 584 mhd_LOG_PRINT (d, 585 MHD_SC_TLS_CONF_BAD_CERT, 586 mhd_LOG_FMT ("Failed to parse certificates chain. " 587 "Number of failed certificates: %i"), 588 res); 589 ret = MHD_SC_TLS_CONF_BAD_CERT; 590 } 591 mbedtls_x509_crt_free (&(d_tls->cert_chain)); 592 593 mhd_assert (MHD_SC_OK != ret); 594 return ret; /* Failure exit point */ 595 } 596 597 598 /** 599 * De-initialise daemon TLS credentials. 600 * @param d_tls the daemon TLS settings 601 */ 602 static MHD_FN_PAR_NONNULL_ALL_ void 603 daemon_deinit_credentials (struct mhd_TlsMbedDaemonData *restrict d_tls) 604 { 605 mbedtls_pk_free (&(d_tls->prv_key)); 606 607 mbedtls_x509_crt_free (&(d_tls->cert_chain)); 608 } 609 610 611 #ifdef MBEDTLS_SSL_ALPN 612 /** 613 * Initialise daemon ALPN data 614 * This function puts error messages to the log if needed. 615 * @param d the daemon handle 616 * @param d_tls the daemon TLS settings 617 * @param s the application-provided settings 618 * @return #MHD_SC_OK on success, 619 * error code otherwise 620 */ 621 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 622 daemon_set_alpn (struct MHD_Daemon *restrict d, 623 struct mhd_TlsMbedDaemonData *restrict d_tls, 624 struct DaemonOptions *restrict s) 625 { 626 static const char alpn_str_http1_0[] = mhd_ALPN_H1_0; 627 static const char alpn_str_http1_1[] = mhd_ALPN_H1_1; 628 # ifdef MHD_SUPPORT_HTTP2 629 static const char alpn_str_http2[] = mhd_ALPN_H2; 630 # endif 631 size_t i; 632 633 (void)s; /* Unused currently. Implement reading allowed HTTP versions */ 634 635 i = 0u; 636 // TODO: implement reading protocol versions from settings */ 637 # ifdef MHD_SUPPORT_HTTP2 638 if (1 /* enabled HTTP/2 ? */) 639 d_tls->alpn_prots[i++] = alpn_str_http2; 640 # endif /* MHD_SUPPORT_HTTP2 */ 641 642 if (1 /* enabled HTTP/1.x ? */) 643 { 644 d_tls->alpn_prots[i++] = alpn_str_http1_1; 645 d_tls->alpn_prots[i++] = alpn_str_http1_0; 646 } 647 648 d_tls->alpn_prots[i] = NULL; /* NULL termination */ 649 mhd_assert (mhd_ARR_NUM_ELEMS (d_tls->alpn_prots) > i); 650 mhd_assert (0u != i); 651 652 if (0 == mbedtls_ssl_conf_alpn_protocols (&(d_tls->tls_conf), 653 d_tls->alpn_prots)) 654 return MHD_SC_OK; /* Success exit point */ 655 656 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 657 "Failed to set ALPN data"); 658 return MHD_SC_TLS_DAEMON_INIT_FAILED; 659 } 660 661 662 #else /* ! MBEDTLS_SSL_ALPN */ 663 # define daemon_set_alpn(d, d_tls, s) (MHD_SC_OK) 664 #endif /* ! MBEDTLS_SSL_ALPN */ 665 666 /** 667 * Set daemon TLS configuration. 668 * This function puts error messages to the log if needed. 669 * @param d the daemon handle 670 * @param d_tls the daemon TLS settings 671 * @param s the application-provided settings 672 * @return #MHD_SC_OK on success, 673 * error code otherwise 674 */ 675 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 676 daemon_init_config (struct MHD_Daemon *restrict d, 677 struct mhd_TlsMbedDaemonData *restrict d_tls, 678 struct DaemonOptions *restrict s) 679 { 680 enum MHD_StatusCode ret; 681 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 682 int (*rng_func)(void *ctx, unsigned char *out, size_t out_size); 683 void *rng_ctx; 684 685 # if defined(MHD_TLS_MBED_PREF_RNG_CTR) 686 rng_func = &mbedtls_ctr_drbg_random; 687 rng_ctx = &mhd_mbed_ctr_drbg_ctx; 688 # elif defined(MHD_TLS_MBED_PREF_RNG_HMAC) 689 rng_func = &mbedtls_hmac_drbg_random; 690 rng_ctx = &mhd_mbed_hmac_drbg_ctx; 691 # elif defined(MHD_TLS_MBED_PREF_RNG_PSA) 692 rng_func = &mbedtls_psa_get_random; 693 rng_ctx = MBEDTLS_PSA_RANDOM_STATE; 694 # else /* MHD_TLS_MBED_PREF_RNG_PSA */ 695 /* Support for external strong random generator could be added here */ 696 # error No random generator is enabled in MbedTLS 697 return MHD_SC_INTERNAL_ERROR; 698 # endif /* MHD_TLS_MBED_PREF_RNG_PSA */ 699 700 ret = daemon_init_credentials (d, 701 d_tls, 702 s, 703 rng_func, 704 rng_ctx); 705 #else /* mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 706 ret = daemon_init_credentials (d, 707 d_tls, 708 s); 709 #endif /* mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 710 711 if (MHD_SC_OK != ret) 712 return ret; 713 714 mbedtls_ssl_config_init (&(d_tls->tls_conf)); 715 716 #ifdef mhd_TLS_MBED_HAS_DEBUG_PRINT 717 mbedtls_ssl_conf_dbg (&(d_tls->tls_conf), 718 mhd_tls_mbed_debug_print, 719 NULL); 720 mbedtls_debug_set_threshold (mhd_DBG_PRINT_LEVEL); 721 #endif /* mhd_TLS_MBED_HAS_DEBUG_PRINT */ 722 723 if (0 == 724 mbedtls_ssl_config_defaults (&(d_tls->tls_conf), 725 MBEDTLS_SSL_IS_SERVER, 726 MBEDTLS_SSL_TRANSPORT_STREAM, 727 MBEDTLS_SSL_PRESET_DEFAULT)) 728 { 729 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 730 mbedtls_ssl_conf_rng (&(d_tls->tls_conf), 731 rng_func, 732 rng_ctx); 733 #endif /* mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 734 735 /* Client certificates are not implemented yet */ 736 mbedtls_ssl_conf_authmode (&(d_tls->tls_conf), 737 MBEDTLS_SSL_VERIFY_NONE); 738 739 if (0 == 740 mbedtls_ssl_conf_own_cert (&(d_tls->tls_conf), 741 &(d_tls->cert_chain), 742 &(d_tls->prv_key))) 743 { 744 ret = daemon_set_alpn (d, 745 d_tls, 746 s); 747 if (MHD_SC_OK == ret) 748 return MHD_SC_OK; /* Success exit point */ 749 750 /* Below is a cleanup path */ 751 } 752 else 753 ret = MHD_SC_DAEMON_MEM_ALLOC_FAILURE; /* Do not waste binary space on the additional message */ 754 } 755 else 756 ret = MHD_SC_DAEMON_MEM_ALLOC_FAILURE; /* Do not waste binary space on the additional message */ 757 758 mbedtls_ssl_config_free (&(d_tls->tls_conf)); 759 760 daemon_deinit_credentials (d_tls); 761 762 mhd_assert (MHD_SC_OK != ret); 763 return ret; /* Failure exit point */ 764 } 765 766 767 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 768 MHD_FN_PAR_OUT_ (3) mhd_StatusCodeInt 769 mhd_tls_mbed_daemon_init3 (struct MHD_Daemon *restrict d, 770 struct DaemonOptions *restrict s, 771 struct mhd_TlsMbedDaemonData **restrict p_d_tls) 772 { 773 mhd_StatusCodeInt res; 774 struct mhd_TlsMbedDaemonData *restrict d_tls; 775 776 /* Successful initialisation must be checked earlier */ 777 mhd_assert (mbedtls_lib_inited_once); 778 mhd_assert (mbedtls_lib_inited_now); 779 780 res = check_app_tls_settings (d, 781 s); 782 if (MHD_SC_OK != res) 783 return res; 784 785 d_tls = (struct mhd_TlsMbedDaemonData *) 786 mhd_calloc (1, sizeof (struct mhd_TlsMbedDaemonData)); 787 *p_d_tls = d_tls; 788 if (NULL == d_tls) 789 return MHD_SC_DAEMON_MEM_ALLOC_FAILURE; 790 791 res = daemon_init_config (d, 792 d_tls, 793 s); 794 if (MHD_SC_OK == res) 795 { 796 return MHD_SC_OK; /* Success exit point */ 797 } 798 /* Below is a clean-up code path */ 799 free (d_tls); 800 *p_d_tls = NULL; 801 mhd_assert (MHD_SC_OK != res); 802 return res; /* Failure exit point */ 803 } 804 805 806 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 807 MHD_FN_PAR_INOUT_ (1) void 808 mhd_tls_mbed_daemon_deinit (struct mhd_TlsMbedDaemonData *restrict d_tls) 809 { 810 mhd_assert (NULL != d_tls); 811 812 mbedtls_ssl_config_free (&(d_tls->tls_conf)); 813 814 daemon_deinit_credentials (d_tls); 815 816 free (d_tls); 817 } 818 819 820 /* ** Connection initialisation / de-initialisation ** */ 821 822 MHD_INTERNAL size_t 823 mhd_tls_mbed_conn_get_tls_size_v (void) 824 { 825 return sizeof (struct mhd_TlsMbedConnData); 826 } 827 828 829 /* Forward declarations of custom transport callbacks */ 830 static int 831 mhd_mbed_cb_recv (void *ctx, 832 unsigned char *buf, 833 size_t size); 834 835 static int 836 mhd_mbed_cb_send (void *ctx, 837 const unsigned char *buf, 838 size_t size); 839 840 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 841 MHD_FN_PAR_OUT_ (3) bool 842 mhd_tls_mbed_conn_init (const struct mhd_TlsMbedDaemonData *restrict d_tls, 843 struct mhd_ConnSocket *sk, 844 struct mhd_TlsMbedConnData *restrict c_tls) 845 { 846 c_tls->tr.sk = sk; 847 848 mbedtls_ssl_init (&(c_tls->sess)); 849 850 if (0 == mbedtls_ssl_setup (&(c_tls->sess), 851 &(d_tls->tls_conf))) 852 { 853 mbedtls_ssl_set_bio (&(c_tls->sess), 854 c_tls, 855 &mhd_mbed_cb_send, 856 &mhd_mbed_cb_recv, 857 NULL /* no recv_timeout callback */); 858 859 #ifndef NDEBUG 860 c_tls->dbg.is_inited = true; 861 #endif 862 return true; /* Success exit point */ 863 } 864 865 mbedtls_ssl_free (&(c_tls->sess)); 866 return false; /* Failure exit point */ 867 } 868 869 870 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void 871 mhd_tls_mbed_conn_deinit (struct mhd_TlsMbedConnData *restrict c_tls) 872 { 873 mhd_assert (c_tls->dbg.is_inited); 874 mbedtls_ssl_free (&(c_tls->sess)); 875 #ifndef NDEBUG 876 c_tls->dbg.is_inited = false; 877 #endif 878 } 879 880 881 /* ** Custom transport functions ** */ 882 883 /** 884 * Prepare for network operation 885 * @param c_tls the connection TLS data 886 */ 887 mhd_static_inline MHD_FN_PAR_NONNULL_ALL_ void 888 mhd_tls_mbed_sckt_comm_prep (struct mhd_TlsMbedConnData *restrict c_tls) 889 { 890 memset (&(c_tls->tr.state), 891 0, 892 sizeof(c_tls->tr.state)); 893 } 894 895 896 /** 897 * Prepare for send() network operation 898 * @param c_tls the connection TLS data 899 * @param unencr_size the size of the data to send before encryption 900 * @param push_data set to 'false' if it is know that the data to be sent 901 * is incomplete (message or chunk), 902 * set to 'true' if the data is complete or the final part 903 */ 904 mhd_static_inline MHD_FN_PAR_NONNULL_ALL_ void 905 mhd_tls_mbed_sckt_comm_prep_send (struct mhd_TlsMbedConnData *restrict c_tls, 906 size_t unencr_size, 907 bool push_data) 908 { 909 mhd_tls_mbed_sckt_comm_prep (c_tls); 910 911 if (push_data) 912 c_tls->tr.state.send_unenc_size = unencr_size; 913 else 914 c_tls->tr.state.send_unenc_size = (size_t)(~((size_t)0)); 915 } 916 917 918 /** 919 * The callback which called by MbedTLS to receive the data 920 * @param ctx the context for the send callback 921 * @param buf the buffer to put received data 922 * @param size the size of the @a buf 923 * @return the positive number of bytes received on success, 924 * 0 if EOF received (peer closed write/send), 925 * #MBEDTLS_ERR_SSL_WANT_READ if receiving would block OR 926 * receiving was interrupted, 927 * #MBEDTLS_ERR_NET_CONN_RESET if connection was broken 928 * or #MBEDTLS_ERR_NET_RECV_FAILED in case of other errors 929 */ 930 static int 931 mhd_mbed_cb_recv (void *ctx, 932 unsigned char *buf, 933 size_t size) 934 { 935 struct mhd_TlsMbedConnData *const c_tls = (struct mhd_TlsMbedConnData *)ctx; 936 struct mhd_TlsMbedConnCstmTrtState *const state = &(c_tls->tr.state); 937 size_t received; 938 939 /* MbedTLS may call recv() several times. 940 This may result in unwanted extra syscalls, unfair connections 941 processing or even blocking if socket is blocking. 942 MHD limits to single send() syscall per operation to evenly distribute 943 workload to all connections. */ 944 if (state->recv_called) 945 return MBEDTLS_ERR_SSL_WANT_READ; 946 947 /* MbedTLS may call blindly recv() after calling send() first. 948 If send() was the first socket operation then the socket has been 949 checked by MHD for 'send-ready' as receiving operation was expected. 950 Do not use recv() if 'recv-ready' is not known and the socket is blocking. 951 */ 952 if (state->send_called && !c_tls->tr.sk->props.is_nonblck) 953 return MBEDTLS_ERR_SSL_WANT_READ; 954 955 if (1) 956 { 957 const int size_i = (int)size; 958 959 if ((0 > size_i) 960 || (size != (size_t)size_i)) 961 { 962 /* Return value limitation */ 963 size = (size_t)(((unsigned int)~((unsigned int)0)) >> 1u); 964 } 965 } 966 967 state->recv_res = mhd_sckt_recv (c_tls->tr.sk, 968 size, 969 (char *)buf, 970 &received); 971 state->recv_called = true; 972 973 if (mhd_SOCKET_ERR_NO_ERROR == state->recv_res) 974 { 975 mhd_ASSUME (size >= received); 976 mhd_assert (0 <= (int)received); 977 return (int)received; 978 } 979 980 if (mhd_SOCKET_ERR_INTR >= state->recv_res) 981 { 982 mhd_assert ((mhd_SOCKET_ERR_INTR == state->recv_res) 983 || (mhd_SOCKET_ERR_AGAIN == state->recv_res)); 984 return MBEDTLS_ERR_SSL_WANT_READ; 985 } 986 987 if (mhd_SOCKET_ERR_IS_HARD (state->recv_res)) 988 { 989 c_tls->tr.sk->state.discnt_err = state->recv_res; 990 return MBEDTLS_ERR_NET_CONN_RESET; 991 } 992 993 return MBEDTLS_ERR_NET_RECV_FAILED; 994 } 995 996 997 /** 998 * The callback called by MbedTLS to send the data 999 * @param ctx the context for the send callback 1000 * @param buf the buffer with the data to send 1001 * @param size the size of the data in the @a buf 1002 * @return the positive number of bytes sent on success, 1003 * #MBEDTLS_ERR_SSL_WANT_WRITE if sending would block OR 1004 * sending was interrupted, 1005 * #MBEDTLS_ERR_NET_CONN_RESET if connection was broken 1006 * or #MBEDTLS_ERR_NET_SEND_FAILED in case of other errors 1007 */ 1008 static int 1009 mhd_mbed_cb_send (void *ctx, 1010 const unsigned char *buf, 1011 size_t size) 1012 { 1013 struct mhd_TlsMbedConnData *const c_tls = (struct mhd_TlsMbedConnData *)ctx; 1014 struct mhd_TlsMbedConnCstmTrtState *const state = &(c_tls->tr.state); 1015 /* Check whether the complete data is sending. 1016 The compression is not used so the data after the encryption must not 1017 be smaller than before the encryption. 1018 The check may result in false-positive (unlikely in practice), but 1019 this should not hurt the performance. */ 1020 bool push_data = (size >= state->send_unenc_size); 1021 size_t sent; 1022 1023 /* MbedTLS may call send() several times in a loop, until all data is sent. 1024 This may result in unwanted extra syscalls, unfair connections processing 1025 or even blocking if socket is blocking. 1026 MHD limits to single send() syscall per operation to evenly distribute 1027 workload to all connections. */ 1028 if (state->send_called) 1029 return MBEDTLS_ERR_SSL_WANT_WRITE; 1030 1031 /* MbedTLS may call blindly send() after calling recv() first. 1032 If recv() was the first socket operation then the socket has been 1033 checked by MHD for 'recv-ready' as receiving operation was expected. 1034 Do not use send() if 'send-ready' is not known and the socket is blocking. 1035 */ 1036 if (state->recv_called && !c_tls->tr.sk->props.is_nonblck) 1037 return MBEDTLS_ERR_SSL_WANT_WRITE; 1038 1039 if (1) 1040 { 1041 const int size_i = (int)size; 1042 1043 if ((0 > size_i) 1044 || (size != (size_t)size_i)) 1045 { 1046 /* Return value limitation */ 1047 size = (size_t)(((unsigned int)~((unsigned int)0)) >> 1u); 1048 push_data = false; 1049 } 1050 } 1051 1052 state->send_res = mhd_sckt_send (c_tls->tr.sk, 1053 size, 1054 (const char *)buf, 1055 push_data, 1056 &sent); 1057 state->send_called = true; 1058 1059 if (mhd_SOCKET_ERR_NO_ERROR == state->send_res) 1060 { 1061 mhd_ASSUME (size >= sent); 1062 mhd_assert (0 < (int)sent); 1063 return (int)sent; 1064 } 1065 1066 if (mhd_SOCKET_ERR_INTR >= state->send_res) 1067 { 1068 mhd_assert ((mhd_SOCKET_ERR_INTR == state->send_res) 1069 || (mhd_SOCKET_ERR_AGAIN == state->send_res)); 1070 return MBEDTLS_ERR_SSL_WANT_WRITE; 1071 } 1072 1073 if (mhd_SOCKET_ERR_IS_HARD (state->send_res)) 1074 { 1075 c_tls->tr.sk->state.discnt_err = state->send_res; 1076 return MBEDTLS_ERR_NET_CONN_RESET; 1077 } 1078 1079 return MBEDTLS_ERR_NET_SEND_FAILED; 1080 } 1081 1082 1083 /* ** TLS connection establishing ** */ 1084 1085 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 1086 enum mhd_TlsProcedureResult 1087 mhd_tls_mbed_conn_handshake (struct mhd_TlsMbedConnData *c_tls) 1088 { 1089 int res; 1090 1091 mhd_assert (c_tls->dbg.is_inited); 1092 mhd_assert (!c_tls->dbg.is_tls_handshake_completed); 1093 mhd_assert (!c_tls->shut_tls_wr_sent); 1094 mhd_assert (!c_tls->shut_tls_wr_received); 1095 mhd_assert (!c_tls->dbg.is_failed); 1096 1097 mhd_tls_mbed_sckt_comm_prep (c_tls); 1098 1099 res = mbedtls_ssl_handshake (&(c_tls->sess)); 1100 1101 mhd_assert ((c_tls->tr.state.recv_called) 1102 || (mhd_SOCKET_ERR_NO_ERROR == c_tls->tr.state.recv_res)); 1103 mhd_assert ((c_tls->tr.state.send_called) 1104 || (mhd_SOCKET_ERR_NO_ERROR == c_tls->tr.state.send_res)); 1105 1106 switch (res) 1107 { 1108 case 0: 1109 #ifndef NDEBUG 1110 c_tls->dbg.is_tls_handshake_completed = true; 1111 #endif /* ! NDEBUG */ 1112 return mhd_TLS_PROCED_SUCCESS; /* Success exit point */ 1113 1114 case MBEDTLS_ERR_SSL_WANT_READ: 1115 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1116 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1117 1118 if (!c_tls->tr.state.recv_called) 1119 return mhd_TLS_PROCED_RECV_INTERRUPTED; /* Do not clear 'recv-ready' flag */ 1120 1121 if (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.recv_res) 1122 return mhd_TLS_PROCED_RECV_MORE_NEEDED; /* Clear 'recv-ready' flag */ 1123 1124 return mhd_TLS_PROCED_RECV_INTERRUPTED; /* Do not clear 'recv-ready' flag */ 1125 1126 case MBEDTLS_ERR_SSL_WANT_WRITE: 1127 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1128 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1129 1130 if (!c_tls->tr.state.send_called) 1131 return mhd_TLS_PROCED_SEND_INTERRUPTED; /* Do not clear 'send-ready' flag */ 1132 1133 if (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.send_res) 1134 return mhd_TLS_PROCED_SEND_MORE_NEEDED; /* Clear 'send-ready' flag */ 1135 1136 return mhd_TLS_PROCED_SEND_INTERRUPTED; /* Do not clear 'send-ready' flag */ 1137 1138 case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: 1139 mhd_assert (0 && "MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS must not be returned"); 1140 break; 1141 1142 case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: 1143 /* The result means that mbedtls_ssl_handshake() must be called again 1144 later. 1145 As this result does not map directly to any of available flags, 1146 so map it to "waiting for send-ready" as the socket should be already 1147 'send-ready'. */ 1148 1149 return (c_tls->tr.state.send_called 1150 && (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.send_res)) ? 1151 mhd_TLS_PROCED_SEND_MORE_NEEDED : mhd_TLS_PROCED_SEND_INTERRUPTED; 1152 1153 case MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA: 1154 #ifdef MBEDTLS_SSL_EARLY_DATA 1155 /* Could be replaced with early data support is implemented */ 1156 #endif /* MBEDTLS_SSL_EARLY_DATA */ 1157 mhd_assert (0 1158 && "MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA must not be returned"); 1159 break; 1160 1161 default: 1162 break; /* Handle other values below */ 1163 } 1164 1165 /* All other result codes must be interpreted as a hard error */ 1166 #ifndef NDEBUG 1167 c_tls->dbg.is_failed = true; 1168 #endif /* ! NDEBUG */ 1169 1170 return mhd_TLS_PROCED_FAILED; 1171 } 1172 1173 1174 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 1175 enum mhd_TlsProcedureResult 1176 mhd_tls_mbed_conn_shutdown (struct mhd_TlsMbedConnData *c_tls) 1177 { 1178 int res; 1179 1180 mhd_assert (c_tls->dbg.is_inited); 1181 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1182 mhd_assert (!c_tls->dbg.is_failed); 1183 1184 mhd_tls_mbed_sckt_comm_prep (c_tls); 1185 1186 res = mbedtls_ssl_close_notify (&(c_tls->sess)); 1187 1188 switch (res) 1189 { 1190 case 0: 1191 c_tls->shut_tls_wr_sent = true; 1192 c_tls->shut_tls_wr_received = true; 1193 return mhd_TLS_PROCED_SUCCESS; /* Success exit point */ 1194 1195 case MBEDTLS_ERR_SSL_WANT_READ: 1196 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1197 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1198 1199 if (!c_tls->tr.state.recv_called) 1200 return mhd_TLS_PROCED_RECV_INTERRUPTED; /* Do not clear 'recv-ready' flag */ 1201 1202 if (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.recv_res) 1203 return mhd_TLS_PROCED_RECV_MORE_NEEDED; /* Clear 'recv-ready' flag */ 1204 1205 return mhd_TLS_PROCED_RECV_INTERRUPTED; /* Do not clear 'recv-ready' flag */ 1206 1207 case MBEDTLS_ERR_SSL_WANT_WRITE: 1208 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1209 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1210 1211 if (!c_tls->tr.state.send_called) 1212 return mhd_TLS_PROCED_SEND_INTERRUPTED; /* Do not clear 'send-ready' flag */ 1213 1214 if (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.send_res) 1215 return mhd_TLS_PROCED_SEND_MORE_NEEDED; /* Clear 'send-ready' flag */ 1216 1217 return mhd_TLS_PROCED_SEND_INTERRUPTED; /* Do not clear 'send-ready' flag */ 1218 1219 default: 1220 break; /* Handle other values below */ 1221 } 1222 1223 /* All other result codes must be interpreted as a hard error */ 1224 #ifndef NDEBUG 1225 c_tls->dbg.is_failed = true; 1226 #endif /* ! NDEBUG */ 1227 1228 return mhd_TLS_PROCED_FAILED; 1229 } 1230 1231 1232 /* ** Data receiving and sending ** */ 1233 1234 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1235 MHD_FN_PAR_OUT_SIZE_ (3, 2) 1236 MHD_FN_PAR_OUT_ (4) enum mhd_SocketError 1237 mhd_tls_mbed_conn_recv (struct mhd_TlsMbedConnData *c_tls, 1238 size_t buf_size, 1239 char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)], 1240 size_t *restrict received) 1241 { 1242 int res; 1243 1244 mhd_assert (0 != buf_size); 1245 1246 mhd_assert (c_tls->dbg.is_inited); 1247 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1248 mhd_assert (!c_tls->shut_tls_wr_sent); 1249 mhd_assert (!c_tls->dbg.is_failed); 1250 1251 if (1) 1252 { 1253 const int buf_size_i = (int)buf_size; 1254 if ((0 > buf_size_i) 1255 || (buf_size != (size_t)buf_size_i)) 1256 { 1257 /* Called function return value limitation */ 1258 buf_size = (size_t)(((unsigned int)~((unsigned int)0)) >> 1u); 1259 } 1260 } 1261 1262 c_tls->recv_data_in_buff = false; 1263 mhd_tls_mbed_sckt_comm_prep (c_tls); 1264 1265 res = mbedtls_ssl_read (&(c_tls->sess), 1266 (unsigned char *)buf, 1267 buf_size); 1268 1269 if (0 <= res) 1270 { 1271 mhd_ASSUME (buf_size >= (size_t)res); 1272 *received = (size_t)res; 1273 1274 return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */ 1275 } 1276 1277 switch (res) 1278 { 1279 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: 1280 c_tls->shut_tls_wr_received = true; 1281 *received = 0u; 1282 1283 return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */ 1284 1285 case MBEDTLS_ERR_SSL_WANT_READ: 1286 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1287 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1288 1289 if (!c_tls->tr.state.recv_called) 1290 return mhd_SOCKET_ERR_INTR; /* Do not clear 'recv-ready' flag */ 1291 1292 if (mhd_SOCKET_ERR_NO_ERROR == c_tls->tr.state.recv_res) 1293 { 1294 /* recv() succeed for the first time and then called again */ 1295 return c_tls->tr.sk->props.is_nonblck ? 1296 mhd_SOCKET_ERR_INTR : mhd_SOCKET_ERR_AGAIN; 1297 } 1298 1299 return c_tls->tr.state.recv_res; 1300 1301 case MBEDTLS_ERR_SSL_WANT_WRITE: 1302 mhd_assert (0 1303 && "The handshake must be fully completed earlier"); 1304 break; 1305 1306 case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: 1307 mhd_assert (0 && "MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS must not be returned"); 1308 break; 1309 1310 case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: 1311 /* MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS means that recv() should be called 1312 again later. Pretend that data is already pending to not block on 1313 waiting for the new incoming data. */ 1314 c_tls->recv_data_in_buff = true; 1315 return mhd_SOCKET_ERR_INTR; /* Do not clear 'recv-ready' flag */ 1316 1317 case MBEDTLS_ERR_SSL_CLIENT_RECONNECT: 1318 mhd_assert (0 1319 && "MBEDTLS_ERR_SSL_CLIENT_RECONNECT must not be " 1320 "returned for non-DTLS"); 1321 break; 1322 1323 case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET: 1324 mhd_assert (0 1325 && "MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET must not be " 1326 "returned on the server side"); 1327 break; 1328 1329 case MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA: 1330 #ifdef MBEDTLS_SSL_EARLY_DATA 1331 /* Could be replaced with early data support is implemented */ 1332 #endif /* MBEDTLS_SSL_EARLY_DATA */ 1333 mhd_assert (0 1334 && "MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA must not be returned"); 1335 break; 1336 1337 default: 1338 break; /* Handle other values below */ 1339 } 1340 1341 /* Treat all other kinds of errors as hard errors */ 1342 #ifndef NDEBUG 1343 c_tls->dbg.is_failed = true; 1344 #endif /* ! NDEBUG */ 1345 return mhd_SOCKET_ERR_TLS; 1346 } 1347 1348 1349 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool 1350 mhd_tls_mbed_conn_has_data_in (struct mhd_TlsMbedConnData *restrict c_tls) 1351 { 1352 return c_tls->recv_data_in_buff 1353 || (0 != mbedtls_ssl_check_pending (&(c_tls->sess))); 1354 } 1355 1356 1357 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1358 MHD_FN_PAR_IN_SIZE_ (3, 2) 1359 MHD_FN_PAR_OUT_ (5) enum mhd_SocketError 1360 mhd_tls_mbed_conn_send (struct mhd_TlsMbedConnData *c_tls, 1361 size_t buf_size, 1362 const char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)], 1363 bool push_data, 1364 size_t *restrict sent) 1365 { 1366 int res; 1367 1368 mhd_assert (0 != buf_size); 1369 1370 mhd_assert (c_tls->dbg.is_inited); 1371 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1372 mhd_assert (!c_tls->shut_tls_wr_sent); 1373 mhd_assert (!c_tls->dbg.is_failed); 1374 1375 if (1) 1376 { 1377 const int buf_size_i = (int)buf_size; 1378 if ((0 > buf_size_i) 1379 || (buf_size != (size_t)buf_size_i)) 1380 { 1381 /* Called function return value limitation */ 1382 buf_size = (size_t)(((unsigned int)~((unsigned int)0)) >> 1u); 1383 push_data = false; 1384 } 1385 } 1386 1387 mhd_tls_mbed_sckt_comm_prep_send (c_tls, 1388 buf_size, 1389 push_data); 1390 1391 res = mbedtls_ssl_write (&(c_tls->sess), 1392 (const unsigned char *)buf, 1393 buf_size); 1394 1395 if (0 < res) 1396 { 1397 mhd_ASSUME (buf_size >= (size_t)res); 1398 *sent = (size_t)res; 1399 1400 return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */ 1401 } 1402 1403 switch (res) 1404 { 1405 case 0: 1406 mhd_assert (0 1407 && "Zero must not be returned when sending non-zero size"); 1408 break; 1409 1410 case MBEDTLS_ERR_SSL_WANT_WRITE: 1411 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1412 mhd_assert (!mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1413 1414 if (!c_tls->tr.state.send_called) 1415 return mhd_SOCKET_ERR_INTR; /* Do not clear 'recv-ready' flag */ 1416 1417 if (mhd_SOCKET_ERR_NO_ERROR == c_tls->tr.state.send_res) 1418 { 1419 /* send() succeed for the first time and then called again */ 1420 return c_tls->tr.sk->props.is_nonblck ? 1421 mhd_SOCKET_ERR_INTR : mhd_SOCKET_ERR_AGAIN; 1422 } 1423 1424 return c_tls->tr.state.send_res; 1425 1426 case MBEDTLS_ERR_SSL_WANT_READ: 1427 mhd_assert (0 1428 && "The handshake must be fully completed earlier"); 1429 break; 1430 1431 case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: 1432 mhd_assert (0 && "MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS must not be returned"); 1433 break; 1434 1435 case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: 1436 /* MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS means that send() should be called 1437 again later. Wait for 'send-ready' which should be already set or 1438 will be set later, when OS pushed the data to the network. */ 1439 return mhd_SOCKET_ERR_INTR; /* Do not clear 'recv-ready' flag */ 1440 1441 case MBEDTLS_ERR_SSL_CLIENT_RECONNECT: 1442 mhd_assert (0 1443 && "MBEDTLS_ERR_SSL_CLIENT_RECONNECT must not be " 1444 "returned for non-DTLS"); 1445 break; 1446 1447 case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET: 1448 mhd_assert (0 1449 && "MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET must not be " 1450 "returned on the server side"); 1451 break; 1452 1453 case MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA: 1454 #ifdef MBEDTLS_SSL_EARLY_DATA 1455 /* Could be replaced with early data support is implemented */ 1456 #endif /* MBEDTLS_SSL_EARLY_DATA */ 1457 mhd_assert (0 1458 && "MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA must not be returned"); 1459 break; 1460 1461 default: 1462 break; /* Handle other values below */ 1463 } 1464 1465 /* Treat all other kinds of errors as hard errors */ 1466 #ifndef NDEBUG 1467 c_tls->dbg.is_failed = true; 1468 #endif /* ! NDEBUG */ 1469 return mhd_SOCKET_ERR_TLS; 1470 } 1471 1472 1473 /* ** TLS connection information ** */ 1474 1475 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1476 MHD_FN_PAR_OUT_ (2) void 1477 mhd_tls_mbed_conn_get_tls_sess ( 1478 struct mhd_TlsMbedConnData *restrict c_tls, 1479 union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out) 1480 { 1481 tls_sess_out->v_mbedtls_session = &(c_tls->sess); 1482 } 1483 1484 1485 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1486 MHD_FN_PAR_OUT_ (2) bool 1487 mhd_tls_mbed_conn_get_tls_ver (struct mhd_TlsMbedConnData *restrict c_tls, 1488 struct mhd_StctTlsVersion *restrict tls_ver_out) 1489 { 1490 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1491 1492 #ifndef MBEDTLS_VERSION_NUMBER 1493 if (1) 1494 return false; /* Need MbedTLS version number to implement */ 1495 #else /* MBEDTLS_VERSION_NUMBER */ 1496 if (1) 1497 { 1498 uint_fast16_t tls_ver_num; 1499 # if ((MBEDTLS_VERSION_NUMBER + 0) >= 0x03020000) 1500 mbedtls_ssl_protocol_version mbedtls_tls_ver; 1501 1502 mbedtls_tls_ver = mbedtls_ssl_get_version_number (&(c_tls->sess)); 1503 1504 tls_ver_num = (uint_fast16_t)mbedtls_tls_ver; 1505 # else /* MBEDTLS_VERSION_NUMBER < 0x03020000 */ 1506 tls_ver_num = (uint_fast16_t)c_tls->sess.MBEDTLS_PRIVATE (major_ver); 1507 tls_ver_num <<= 8u; 1508 tls_ver_num |= (uint_fast16_t)c_tls->sess.MBEDTLS_PRIVATE (minor_ver); 1509 # endif /* MBEDTLS_VERSION_NUMBER < 0x03020000 */ 1510 /* Avoid MbedTLS helper macros and enum values in switch() as they are 1511 unstable in MbedTLS. */ 1512 switch (tls_ver_num) 1513 { 1514 case 0u: 1515 return false; 1516 1517 case 0x0301u: /* Not really supported by MbedTLS >=3.0 */ 1518 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_0; 1519 break; 1520 1521 case 0x0302u: /* Not really supported by MbedTLS >=3.0 */ 1522 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_1; 1523 break; 1524 1525 case 0x0303u: 1526 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_2; 1527 break; 1528 1529 case 0x0304u: 1530 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_3; 1531 break; 1532 1533 default: 1534 tls_ver_out->tls_ver = MHD_TLS_VERSION_UNKNOWN; 1535 break; 1536 } 1537 } 1538 #endif /* MBEDTLS_VERSION_NUMBER */ 1539 1540 return true; 1541 } 1542 1543 1544 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ enum mhd_TlsAlpnProt 1545 mhd_tls_mbed_conn_get_alpn_prot (struct mhd_TlsMbedConnData *restrict c_tls) 1546 { 1547 #ifdef MBEDTLS_SSL_ALPN 1548 const char *alpn_str; 1549 1550 alpn_str = mbedtls_ssl_get_alpn_protocol (&(c_tls->sess)); 1551 if (NULL == alpn_str) 1552 return mhd_TLS_ALPN_PROT_NOT_SELECTED; 1553 1554 return mhd_tls_alpn_decode_n (strlen (alpn_str), 1555 (const unsigned char *)alpn_str); 1556 #else /* ! MBEDTLS_SSL_ALPN */ 1557 return mhd_TLS_ALPN_PROT_NOT_SELECTED; 1558 #endif /* ! MBEDTLS_SSL_ALPN */ 1559 }