tls_mbed_funcs.c (48978B)
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 return MHD_SC_OK; 449 } 450 451 452 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 453 /** 454 * Set daemon TLS credentials. 455 * This function puts error messages to the log if needed. 456 * @param d the daemon handle 457 * @param d_tls the daemon TLS settings 458 * @param s the application-provided settings 459 * @param rng_func the random generator function 460 * @param rng_ctx the random generator function context 461 * @return #MHD_SC_OK on success, 462 * error code otherwise 463 */ 464 #else /* ! 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 * @return #MHD_SC_OK on success, 472 * error code otherwise 473 */ 474 #endif /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 475 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 476 MHD_FN_PAR_NONNULL_ (3) MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 477 daemon_init_credentials ( 478 struct MHD_Daemon *restrict d, 479 struct mhd_TlsMbedDaemonData *restrict d_tls, 480 struct DaemonOptions *restrict s 481 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 482 , 483 int (*rng_func)(void *ctx, unsigned char *out, size_t out_size), 484 void *rng_ctx 485 #endif /* mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 486 ) 487 { 488 enum MHD_StatusCode ret; 489 size_t cert_len; 490 size_t key_len; 491 size_t pwd_len; 492 int res; 493 494 ret = MHD_SC_OK; 495 496 // TODO: Support multiple certificates 497 cert_len = strlen (s->tls_cert_key.v_mem_cert); // TODO: Reuse calculated length 498 key_len = strlen (s->tls_cert_key.v_mem_key); // TODO: Reuse calculated length 499 pwd_len = (NULL == s->tls_cert_key.v_mem_pass) ? 500 0u : strlen (s->tls_cert_key.v_mem_pass); // TODO: Reuse calculated length 501 502 mhd_assert (0 != cert_len); 503 mhd_assert (0 != key_len); 504 505 mbedtls_x509_crt_init (&(d_tls->cert_chain)); 506 507 res = mbedtls_x509_crt_parse (&(d_tls->cert_chain), 508 (const unsigned char *) 509 s->tls_cert_key.v_mem_cert, 510 cert_len + 1u /* Include terminating zero */); 511 if (0 == res) 512 { 513 mbedtls_pk_init (&(d_tls->prv_key)); 514 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 515 if (0 != mbedtls_pk_parse_key (&(d_tls->prv_key), 516 (const unsigned char *) 517 s->tls_cert_key.v_mem_key, 518 key_len + 1u, 519 (const unsigned char *) 520 s->tls_cert_key.v_mem_pass, 521 pwd_len, 522 rng_func, 523 rng_ctx)) 524 ret = MHD_SC_TLS_CONF_BAD_CERT; 525 #else /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 526 if (0 != mbedtls_pk_parse_key (&(d_tls->prv_key), 527 (const unsigned char *) 528 s->tls_cert_key.v_mem_key, 529 key_len + 1u, 530 (const unsigned char *) 531 s->tls_cert_key.v_mem_pass, 532 pwd_len)) 533 ret = MHD_SC_TLS_CONF_BAD_CERT; 534 #endif /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 535 536 if (MHD_SC_OK == ret) 537 { 538 /* The next macro can be defined at MHD build-time to skip potentially 539 expensive check */ 540 #ifdef MHD_TLS_MBED_SKIP_CERT_KEY_MATCH_CHECK 541 return MHD_SC_OK; /* Success exit point */ 542 #else /* ! MHD_TLS_MBED_SKIP_CERT_KEY_MATCH_CHECK */ 543 # if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 544 res = mbedtls_pk_check_pair (&(d_tls->cert_chain.pk), 545 &(d_tls->prv_key), 546 rng_func, 547 rng_ctx); 548 # else /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 549 res = mbedtls_pk_check_pair (&(d_tls->cert_chain.pk), 550 &(d_tls->prv_key)); 551 # endif /* ! mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 552 if ((0 == res) || 553 (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE == res)) 554 return MHD_SC_OK; /* Success exit point */ 555 556 mhd_LOG_MSG (d, MHD_SC_TLS_CONF_BAD_CERT, \ 557 "The private key data does not match the certificate"); 558 ret = MHD_SC_TLS_CONF_BAD_CERT; 559 #endif /* ! MHD_TLS_MBED_SKIP_CERT_KEY_MATCH_CHECK */ 560 } 561 else 562 { 563 mhd_LOG_MSG (d, MHD_SC_TLS_CONF_BAD_CERT, \ 564 "The private key data cannot be decoded"); 565 ret = MHD_SC_TLS_CONF_BAD_CERT; 566 } 567 568 mbedtls_pk_free (&(d_tls->prv_key)); 569 } 570 else 571 { 572 mhd_LOG_PRINT (d, 573 MHD_SC_TLS_CONF_BAD_CERT, 574 mhd_LOG_FMT ("Failed to parse certificates chain. " 575 "Number of failed certificates: %i"), 576 res); 577 ret = MHD_SC_TLS_CONF_BAD_CERT; 578 } 579 mbedtls_x509_crt_free (&(d_tls->cert_chain)); 580 581 mhd_assert (MHD_SC_OK != ret); 582 return ret; /* Failure exit point */ 583 } 584 585 586 /** 587 * De-initialise daemon TLS credentials. 588 * @param d_tls the daemon TLS settings 589 */ 590 static MHD_FN_PAR_NONNULL_ALL_ void 591 daemon_deinit_credentials (struct mhd_TlsMbedDaemonData *restrict d_tls) 592 { 593 mbedtls_pk_free (&(d_tls->prv_key)); 594 595 mbedtls_x509_crt_free (&(d_tls->cert_chain)); 596 } 597 598 599 #ifdef MBEDTLS_SSL_ALPN 600 /** 601 * Initialise daemon ALPN data 602 * This function puts error messages to the log if needed. 603 * @param d the daemon handle 604 * @param d_tls the daemon TLS settings 605 * @param s the application-provided settings 606 * @return #MHD_SC_OK on success, 607 * error code otherwise 608 */ 609 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 610 daemon_set_alpn (struct MHD_Daemon *restrict d, 611 struct mhd_TlsMbedDaemonData *restrict d_tls, 612 struct DaemonOptions *restrict s) 613 { 614 static const char alpn_str_http1_0[] = mhd_ALPN_H1_0; 615 static const char alpn_str_http1_1[] = mhd_ALPN_H1_1; 616 # ifdef MHD_SUPPORT_HTTP2 617 static const char alpn_str_http2[] = mhd_ALPN_H2; 618 # endif 619 size_t i; 620 621 (void) s; /* Unused currently. Implement reading allowed HTTP versions */ 622 623 i = 0u; 624 // TODO: implement reading protocol versions from settings */ 625 #ifdef MHD_SUPPORT_HTTP2 626 if (1 /* enabled HTTP/2 ? */) 627 d_tls->alpn_prots[i++] = alpn_str_http2; 628 #endif /* MHD_SUPPORT_HTTP2 */ 629 630 if (1 /* enabled HTTP/1.x ? */) 631 { 632 d_tls->alpn_prots[i++] = alpn_str_http1_1; 633 d_tls->alpn_prots[i++] = alpn_str_http1_0; 634 } 635 636 d_tls->alpn_prots[i] = NULL; /* NULL termination */ 637 mhd_assert (mhd_ARR_NUM_ELEMS (d_tls->alpn_prots) > i); 638 mhd_assert (0u != i); 639 640 if (0 == mbedtls_ssl_conf_alpn_protocols (&(d_tls->tls_conf), 641 d_tls->alpn_prots)) 642 return MHD_SC_OK; /* Success exit point */ 643 644 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 645 "Failed to set ALPN data"); 646 return MHD_SC_TLS_DAEMON_INIT_FAILED; 647 } 648 649 650 #else /* ! MBEDTLS_SSL_ALPN */ 651 # define daemon_set_alpn(d,d_tls,s) (MHD_SC_OK) 652 #endif /* ! MBEDTLS_SSL_ALPN */ 653 654 /** 655 * Set daemon TLS configuration. 656 * This function puts error messages to the log if needed. 657 * @param d the daemon handle 658 * @param d_tls the daemon TLS settings 659 * @param s the application-provided settings 660 * @return #MHD_SC_OK on success, 661 * error code otherwise 662 */ 663 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 664 daemon_init_config (struct MHD_Daemon *restrict d, 665 struct mhd_TlsMbedDaemonData *restrict d_tls, 666 struct DaemonOptions *restrict s) 667 { 668 enum MHD_StatusCode ret; 669 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 670 int (*rng_func)(void *ctx, unsigned char *out, size_t out_size); 671 void *rng_ctx; 672 673 # if defined(MHD_TLS_MBED_PREF_RNG_CTR) 674 rng_func = &mbedtls_ctr_drbg_random; 675 rng_ctx = &mhd_mbed_ctr_drbg_ctx; 676 # elif defined(MHD_TLS_MBED_PREF_RNG_HMAC) 677 rng_func = &mbedtls_hmac_drbg_random; 678 rng_ctx = &mhd_mbed_hmac_drbg_ctx; 679 # elif defined(MHD_TLS_MBED_PREF_RNG_PSA) 680 rng_func = &mbedtls_psa_get_random; 681 rng_ctx = MBEDTLS_PSA_RANDOM_STATE; 682 # else /* MHD_TLS_MBED_PREF_RNG_PSA */ 683 /* Support for external strong random generator could be added here */ 684 #error No random generator is enabled in MbedTLS 685 return MHD_SC_INTERNAL_ERROR; 686 # endif /* MHD_TLS_MBED_PREF_RNG_PSA */ 687 688 ret = daemon_init_credentials (d, 689 d_tls, 690 s, 691 rng_func, 692 rng_ctx); 693 #else /* mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 694 ret = daemon_init_credentials (d, 695 d_tls, 696 s); 697 #endif /* mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 698 699 if (MHD_SC_OK != ret) 700 return ret; 701 702 mbedtls_ssl_config_init (&(d_tls->tls_conf)); 703 704 #ifdef mhd_TLS_MBED_HAS_DEBUG_PRINT 705 mbedtls_ssl_conf_dbg (&(d_tls->tls_conf), 706 mhd_tls_mbed_debug_print, 707 NULL); 708 mbedtls_debug_set_threshold (mhd_DBG_PRINT_LEVEL); 709 #endif /* mhd_TLS_MBED_HAS_DEBUG_PRINT */ 710 711 if (0 == 712 mbedtls_ssl_config_defaults (&(d_tls->tls_conf), 713 MBEDTLS_SSL_IS_SERVER, 714 MBEDTLS_SSL_TRANSPORT_STREAM, 715 MBEDTLS_SSL_PRESET_DEFAULT)) 716 { 717 #if defined(mhd_TLS_MBED_INIT_TLS_REQ_RNG) 718 mbedtls_ssl_conf_rng (&(d_tls->tls_conf), 719 rng_func, 720 rng_ctx); 721 #endif /* mhd_TLS_MBED_INIT_TLS_REQ_RNG */ 722 723 /* Client certificates are not implemented yet */ 724 mbedtls_ssl_conf_authmode (&(d_tls->tls_conf), 725 MBEDTLS_SSL_VERIFY_NONE); 726 727 if (0 == 728 mbedtls_ssl_conf_own_cert (&(d_tls->tls_conf), 729 &(d_tls->cert_chain), 730 &(d_tls->prv_key))) 731 { 732 ret = daemon_set_alpn (d, 733 d_tls, 734 s); 735 if (MHD_SC_OK == ret) 736 return MHD_SC_OK; /* Success exit point */ 737 738 /* Below is a cleanup path */ 739 } 740 else 741 ret = MHD_SC_DAEMON_MEM_ALLOC_FAILURE; /* Do not waste binary space on the additional message */ 742 } 743 else 744 ret = MHD_SC_DAEMON_MEM_ALLOC_FAILURE; /* Do not waste binary space on the additional message */ 745 746 mbedtls_ssl_config_free (&(d_tls->tls_conf)); 747 748 daemon_deinit_credentials (d_tls); 749 750 mhd_assert (MHD_SC_OK != ret); 751 return ret; /* Failure exit point */ 752 } 753 754 755 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 756 MHD_FN_PAR_OUT_ (3) mhd_StatusCodeInt 757 mhd_tls_mbed_daemon_init3 (struct MHD_Daemon *restrict d, 758 struct DaemonOptions *restrict s, 759 struct mhd_TlsMbedDaemonData **restrict p_d_tls) 760 { 761 mhd_StatusCodeInt res; 762 struct mhd_TlsMbedDaemonData *restrict d_tls; 763 764 /* Successful initialisation must be checked earlier */ 765 mhd_assert (mbedtls_lib_inited_once); 766 mhd_assert (mbedtls_lib_inited_now); 767 768 res = check_app_tls_settings (d, 769 s); 770 if (MHD_SC_OK != res) 771 return res; 772 773 d_tls = (struct mhd_TlsMbedDaemonData *) 774 mhd_calloc (1, sizeof (struct mhd_TlsMbedDaemonData)); 775 *p_d_tls = d_tls; 776 if (NULL == d_tls) 777 return MHD_SC_DAEMON_MEM_ALLOC_FAILURE; 778 779 res = daemon_init_config (d, 780 d_tls, 781 s); 782 if (MHD_SC_OK == res) 783 { 784 return MHD_SC_OK; /* Success exit point */ 785 } 786 /* Below is a clean-up code path */ 787 free (d_tls); 788 *p_d_tls = NULL; 789 mhd_assert (MHD_SC_OK != res); 790 return res; /* Failure exit point */ 791 } 792 793 794 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 795 MHD_FN_PAR_INOUT_ (1) void 796 mhd_tls_mbed_daemon_deinit (struct mhd_TlsMbedDaemonData *restrict d_tls) 797 { 798 mhd_assert (NULL != d_tls); 799 800 mbedtls_ssl_config_free (&(d_tls->tls_conf)); 801 802 daemon_deinit_credentials (d_tls); 803 804 free (d_tls); 805 } 806 807 808 /* ** Connection initialisation / de-initialisation ** */ 809 810 MHD_INTERNAL size_t 811 mhd_tls_mbed_conn_get_tls_size_v (void) 812 { 813 return sizeof (struct mhd_TlsMbedConnData); 814 } 815 816 817 /* Forward declarations of custom transport callbacks */ 818 static int 819 mhd_mbed_cb_recv (void *ctx, 820 unsigned char *buf, 821 size_t size); 822 823 static int 824 mhd_mbed_cb_send (void *ctx, 825 const unsigned char *buf, 826 size_t size); 827 828 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 829 MHD_FN_PAR_OUT_ (3) bool 830 mhd_tls_mbed_conn_init (const struct mhd_TlsMbedDaemonData *restrict d_tls, 831 struct mhd_ConnSocket *sk, 832 struct mhd_TlsMbedConnData *restrict c_tls) 833 { 834 c_tls->tr.sk = sk; 835 836 mbedtls_ssl_init (&(c_tls->sess)); 837 838 if (0 == mbedtls_ssl_setup (&(c_tls->sess), 839 &(d_tls->tls_conf))) 840 { 841 mbedtls_ssl_set_bio (&(c_tls->sess), 842 c_tls, 843 &mhd_mbed_cb_send, 844 &mhd_mbed_cb_recv, 845 NULL /* no recv_timeout callback */); 846 847 #ifndef NDEBUG 848 c_tls->dbg.is_inited = true; 849 #endif 850 return true; /* Success exit point */ 851 } 852 853 mbedtls_ssl_free (&(c_tls->sess)); 854 return false; /* Failure exit point */ 855 } 856 857 858 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void 859 mhd_tls_mbed_conn_deinit (struct mhd_TlsMbedConnData *restrict c_tls) 860 { 861 mhd_assert (c_tls->dbg.is_inited); 862 mbedtls_ssl_free (&(c_tls->sess)); 863 #ifndef NDEBUG 864 c_tls->dbg.is_inited = false; 865 #endif 866 } 867 868 869 /* ** Custom transport functions ** */ 870 871 /** 872 * Prepare for network operation 873 * @param c_tls the connection TLS data 874 */ 875 mhd_static_inline MHD_FN_PAR_NONNULL_ALL_ void 876 mhd_tls_mbed_sckt_comm_prep (struct mhd_TlsMbedConnData *restrict c_tls) 877 { 878 memset (&(c_tls->tr.state), 879 0, 880 sizeof(c_tls->tr.state)); 881 } 882 883 884 /** 885 * Prepare for send() network operation 886 * @param c_tls the connection TLS data 887 * @param unencr_size the size of the data to send before encryption 888 * @param push_data set to 'false' if it is know that the data to be sent 889 * is incomplete (message or chunk), 890 * set to 'true' if the data is complete or the final part 891 */ 892 mhd_static_inline MHD_FN_PAR_NONNULL_ALL_ void 893 mhd_tls_mbed_sckt_comm_prep_send (struct mhd_TlsMbedConnData *restrict c_tls, 894 size_t unencr_size, 895 bool push_data) 896 { 897 mhd_tls_mbed_sckt_comm_prep (c_tls); 898 899 if (push_data) 900 c_tls->tr.state.send_unenc_size = unencr_size; 901 else 902 c_tls->tr.state.send_unenc_size = (size_t) (~((size_t) 0)); 903 } 904 905 906 /** 907 * The callback which called by MbedTLS to receive the data 908 * @param ctx the context for the send callback 909 * @param buf the buffer to put received data 910 * @param size the size of the @a buf 911 * @return the positive number of bytes received on success, 912 * 0 if EOF received (peer closed write/send), 913 * #MBEDTLS_ERR_SSL_WANT_READ if receiving would block OR 914 * receiving was interrupted, 915 * #MBEDTLS_ERR_NET_CONN_RESET if connection was broken 916 * or #MBEDTLS_ERR_NET_RECV_FAILED in case of other errors 917 */ 918 static int 919 mhd_mbed_cb_recv (void *ctx, 920 unsigned char *buf, 921 size_t size) 922 { 923 struct mhd_TlsMbedConnData *const c_tls = (struct mhd_TlsMbedConnData *) ctx; 924 struct mhd_TlsMbedConnCstmTrtState *const state = &(c_tls->tr.state); 925 size_t received; 926 927 /* MbedTLS may call recv() several times. 928 This may result in unwanted extra syscalls, unfair connections 929 processing or even blocking if socket is blocking. 930 MHD limits to single send() syscall per operation to evenly distribute 931 workload to all connections. */ 932 if (state->recv_called) 933 return MBEDTLS_ERR_SSL_WANT_READ; 934 935 /* MbedTLS may call blindly recv() after calling send() first. 936 If send() was the first socket operation then the socket has been 937 checked by MHD for 'send-ready' as receiving operation was expected. 938 Do not use recv() if 'recv-ready' is not known and the socket is blocking. 939 */ 940 if (state->send_called && ! c_tls->tr.sk->props.is_nonblck) 941 return MBEDTLS_ERR_SSL_WANT_READ; 942 943 if (1) 944 { 945 const int size_i = (int) size; 946 947 if ((0 > size_i) || 948 (size != (size_t) size_i)) 949 { 950 /* Return value limitation */ 951 size = (size_t) (((unsigned int) ~((unsigned int) 0)) >> 1u); 952 } 953 } 954 955 state->recv_res = mhd_sckt_recv (c_tls->tr.sk, 956 size, 957 (char *) buf, 958 &received); 959 state->recv_called = true; 960 961 if (mhd_SOCKET_ERR_NO_ERROR == state->recv_res) 962 { 963 mhd_ASSUME (size >= received); 964 mhd_assert (0 <= (int) received); 965 return (int) received; 966 } 967 968 if (mhd_SOCKET_ERR_INTR >= state->recv_res) 969 { 970 mhd_assert ((mhd_SOCKET_ERR_INTR == state->recv_res) || 971 (mhd_SOCKET_ERR_AGAIN == state->recv_res)); 972 return MBEDTLS_ERR_SSL_WANT_READ; 973 } 974 975 if (mhd_SOCKET_ERR_IS_HARD (state->recv_res)) 976 { 977 c_tls->tr.sk->state.discnt_err = state->recv_res; 978 return MBEDTLS_ERR_NET_CONN_RESET; 979 } 980 981 return MBEDTLS_ERR_NET_RECV_FAILED; 982 } 983 984 985 /** 986 * The callback called by MbedTLS to send the data 987 * @param ctx the context for the send callback 988 * @param buf the buffer with the data to send 989 * @param size the size of the data in the @a buf 990 * @return the positive number of bytes sent on success, 991 * #MBEDTLS_ERR_SSL_WANT_WRITE if sending would block OR 992 * sending was interrupted, 993 * #MBEDTLS_ERR_NET_CONN_RESET if connection was broken 994 * or #MBEDTLS_ERR_NET_SEND_FAILED in case of other errors 995 */ 996 static int 997 mhd_mbed_cb_send (void *ctx, 998 const unsigned char *buf, 999 size_t size) 1000 { 1001 struct mhd_TlsMbedConnData *const c_tls = (struct mhd_TlsMbedConnData *) ctx; 1002 struct mhd_TlsMbedConnCstmTrtState *const state = &(c_tls->tr.state); 1003 /* Check whether the complete data is sending. 1004 The compression is not used so the data after the encryption must not 1005 be smaller than before the encryption. 1006 The check may result in false-positive (unlikely in practice), but 1007 this should not hurt the performance. */ 1008 bool push_data = (size >= state->send_unenc_size); 1009 size_t sent; 1010 1011 /* MbedTLS may call send() several times in a loop, until all data is sent. 1012 This may result in unwanted extra syscalls, unfair connections processing 1013 or even blocking if socket is blocking. 1014 MHD limits to single send() syscall per operation to evenly distribute 1015 workload to all connections. */ 1016 if (state->send_called) 1017 return MBEDTLS_ERR_SSL_WANT_WRITE; 1018 1019 /* MbedTLS may call blindly send() after calling recv() first. 1020 If recv() was the first socket operation then the socket has been 1021 checked by MHD for 'recv-ready' as receiving operation was expected. 1022 Do not use send() if 'send-ready' is not known and the socket is blocking. 1023 */ 1024 if (state->recv_called && ! c_tls->tr.sk->props.is_nonblck) 1025 return MBEDTLS_ERR_SSL_WANT_WRITE; 1026 1027 if (1) 1028 { 1029 const int size_i = (int) size; 1030 1031 if ((0 > size_i) || 1032 (size != (size_t) size_i)) 1033 { 1034 /* Return value limitation */ 1035 size = (size_t) (((unsigned int) ~((unsigned int) 0)) >> 1u); 1036 push_data = false; 1037 } 1038 } 1039 1040 state->send_res = mhd_sckt_send (c_tls->tr.sk, 1041 size, 1042 (const char *) buf, 1043 push_data, 1044 &sent); 1045 state->send_called = true; 1046 1047 if (mhd_SOCKET_ERR_NO_ERROR == state->send_res) 1048 { 1049 mhd_ASSUME (size >= sent); 1050 mhd_assert (0 < (int) sent); 1051 return (int) sent; 1052 } 1053 1054 if (mhd_SOCKET_ERR_INTR >= state->send_res) 1055 { 1056 mhd_assert ((mhd_SOCKET_ERR_INTR == state->send_res) || 1057 (mhd_SOCKET_ERR_AGAIN == state->send_res)); 1058 return MBEDTLS_ERR_SSL_WANT_WRITE; 1059 } 1060 1061 if (mhd_SOCKET_ERR_IS_HARD (state->send_res)) 1062 { 1063 c_tls->tr.sk->state.discnt_err = state->send_res; 1064 return MBEDTLS_ERR_NET_CONN_RESET; 1065 } 1066 1067 return MBEDTLS_ERR_NET_SEND_FAILED; 1068 } 1069 1070 1071 /* ** TLS connection establishing ** */ 1072 1073 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 1074 enum mhd_TlsProcedureResult 1075 mhd_tls_mbed_conn_handshake (struct mhd_TlsMbedConnData *c_tls) 1076 { 1077 int res; 1078 1079 mhd_assert (c_tls->dbg.is_inited); 1080 mhd_assert (! c_tls->dbg.is_tls_handshake_completed); 1081 mhd_assert (! c_tls->shut_tls_wr_sent); 1082 mhd_assert (! c_tls->shut_tls_wr_received); 1083 mhd_assert (! c_tls->dbg.is_failed); 1084 1085 mhd_tls_mbed_sckt_comm_prep (c_tls); 1086 1087 res = mbedtls_ssl_handshake (&(c_tls->sess)); 1088 1089 mhd_assert ((c_tls->tr.state.recv_called) || 1090 (mhd_SOCKET_ERR_NO_ERROR == c_tls->tr.state.recv_res)); 1091 mhd_assert ((c_tls->tr.state.send_called) || 1092 (mhd_SOCKET_ERR_NO_ERROR == c_tls->tr.state.send_res)); 1093 1094 switch (res) 1095 { 1096 case 0: 1097 #ifndef NDEBUG 1098 c_tls->dbg.is_tls_handshake_completed = true; 1099 #endif /* ! NDEBUG */ 1100 return mhd_TLS_PROCED_SUCCESS; /* Success exit point */ 1101 1102 case MBEDTLS_ERR_SSL_WANT_READ: 1103 mhd_assert (! mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1104 mhd_assert (! mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1105 1106 if (! c_tls->tr.state.recv_called) 1107 return mhd_TLS_PROCED_RECV_INTERRUPTED; /* Do not clear 'recv-ready' flag */ 1108 1109 if (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.recv_res) 1110 return mhd_TLS_PROCED_RECV_MORE_NEEDED; /* Clear 'recv-ready' flag */ 1111 1112 return mhd_TLS_PROCED_RECV_INTERRUPTED; /* Do not clear 'recv-ready' flag */ 1113 1114 case MBEDTLS_ERR_SSL_WANT_WRITE: 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.send_called) 1119 return mhd_TLS_PROCED_SEND_INTERRUPTED; /* Do not clear 'send-ready' flag */ 1120 1121 if (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.send_res) 1122 return mhd_TLS_PROCED_SEND_MORE_NEEDED; /* Clear 'send-ready' flag */ 1123 1124 return mhd_TLS_PROCED_SEND_INTERRUPTED; /* Do not clear 'send-ready' flag */ 1125 1126 case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: 1127 mhd_assert (0 && "MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS must not be returned"); 1128 break; 1129 1130 case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: 1131 /* The result means that mbedtls_ssl_handshake() must be called again 1132 later. 1133 As this result does not map directly to any of available flags, 1134 so map it to "waiting for send-ready" as the socket should be already 1135 'send-ready'. */ 1136 1137 return (c_tls->tr.state.send_called && 1138 (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.send_res)) ? 1139 mhd_TLS_PROCED_SEND_MORE_NEEDED : mhd_TLS_PROCED_SEND_INTERRUPTED; 1140 1141 case MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA: 1142 #ifdef MBEDTLS_SSL_EARLY_DATA 1143 /* Could be replaced with early data support is implemented */ 1144 #endif /* MBEDTLS_SSL_EARLY_DATA */ 1145 mhd_assert (0 && 1146 "MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA must not be returned"); 1147 break; 1148 1149 default: 1150 break; /* Handle other values below */ 1151 } 1152 1153 /* All other result codes must be interpreted as a hard error */ 1154 #ifndef NDEBUG 1155 c_tls->dbg.is_failed = true; 1156 #endif /* ! NDEBUG */ 1157 1158 return mhd_TLS_PROCED_FAILED; 1159 } 1160 1161 1162 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 1163 enum mhd_TlsProcedureResult 1164 mhd_tls_mbed_conn_shutdown (struct mhd_TlsMbedConnData *c_tls) 1165 { 1166 int res; 1167 1168 mhd_assert (c_tls->dbg.is_inited); 1169 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1170 mhd_assert (! c_tls->dbg.is_failed); 1171 1172 mhd_tls_mbed_sckt_comm_prep (c_tls); 1173 1174 res = mbedtls_ssl_close_notify (&(c_tls->sess)); 1175 1176 switch (res) 1177 { 1178 case 0: 1179 c_tls->shut_tls_wr_sent = true; 1180 c_tls->shut_tls_wr_received = true; 1181 return mhd_TLS_PROCED_SUCCESS; /* Success exit point */ 1182 1183 case MBEDTLS_ERR_SSL_WANT_READ: 1184 mhd_assert (! mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1185 mhd_assert (! mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1186 1187 if (! c_tls->tr.state.recv_called) 1188 return mhd_TLS_PROCED_RECV_INTERRUPTED; /* Do not clear 'recv-ready' flag */ 1189 1190 if (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.recv_res) 1191 return mhd_TLS_PROCED_RECV_MORE_NEEDED; /* Clear 'recv-ready' flag */ 1192 1193 return mhd_TLS_PROCED_RECV_INTERRUPTED; /* Do not clear 'recv-ready' flag */ 1194 1195 case MBEDTLS_ERR_SSL_WANT_WRITE: 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.send_called) 1200 return mhd_TLS_PROCED_SEND_INTERRUPTED; /* Do not clear 'send-ready' flag */ 1201 1202 if (mhd_SOCKET_ERR_AGAIN == c_tls->tr.state.send_res) 1203 return mhd_TLS_PROCED_SEND_MORE_NEEDED; /* Clear 'send-ready' flag */ 1204 1205 return mhd_TLS_PROCED_SEND_INTERRUPTED; /* Do not clear 'send-ready' flag */ 1206 1207 default: 1208 break; /* Handle other values below */ 1209 } 1210 1211 /* All other result codes must be interpreted as a hard error */ 1212 #ifndef NDEBUG 1213 c_tls->dbg.is_failed = true; 1214 #endif /* ! NDEBUG */ 1215 1216 return mhd_TLS_PROCED_FAILED; 1217 } 1218 1219 1220 /* ** Data receiving and sending ** */ 1221 1222 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1223 MHD_FN_PAR_OUT_SIZE_ (3,2) 1224 MHD_FN_PAR_OUT_ (4) enum mhd_SocketError 1225 mhd_tls_mbed_conn_recv (struct mhd_TlsMbedConnData *c_tls, 1226 size_t buf_size, 1227 char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)], 1228 size_t *restrict received) 1229 { 1230 int res; 1231 1232 mhd_assert (0 != buf_size); 1233 1234 mhd_assert (c_tls->dbg.is_inited); 1235 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1236 mhd_assert (! c_tls->shut_tls_wr_sent); 1237 mhd_assert (! c_tls->dbg.is_failed); 1238 1239 if (1) 1240 { 1241 const int buf_size_i = (int) buf_size; 1242 if ((0 > buf_size_i) || 1243 (buf_size != (size_t) buf_size_i)) 1244 { 1245 /* Called function return value limitation */ 1246 buf_size = (size_t) (((unsigned int) ~((unsigned int) 0)) >> 1u); 1247 } 1248 } 1249 1250 c_tls->recv_data_in_buff = false; 1251 mhd_tls_mbed_sckt_comm_prep (c_tls); 1252 1253 res = mbedtls_ssl_read (&(c_tls->sess), 1254 (unsigned char *) buf, 1255 buf_size); 1256 1257 if (0 <= res) 1258 { 1259 mhd_ASSUME (buf_size >= (size_t) res); 1260 *received = (size_t) res; 1261 1262 return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */ 1263 } 1264 1265 switch (res) 1266 { 1267 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: 1268 c_tls->shut_tls_wr_received = true; 1269 *received = 0u; 1270 1271 return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */ 1272 1273 case MBEDTLS_ERR_SSL_WANT_READ: 1274 mhd_assert (! mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1275 mhd_assert (! mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1276 1277 if (! c_tls->tr.state.recv_called) 1278 return mhd_SOCKET_ERR_INTR; /* Do not clear 'recv-ready' flag */ 1279 1280 if (mhd_SOCKET_ERR_NO_ERROR == c_tls->tr.state.recv_res) 1281 { 1282 /* recv() succeed for the first time and then called again */ 1283 return c_tls->tr.sk->props.is_nonblck ? 1284 mhd_SOCKET_ERR_INTR : mhd_SOCKET_ERR_AGAIN; 1285 } 1286 1287 return c_tls->tr.state.recv_res; 1288 1289 case MBEDTLS_ERR_SSL_WANT_WRITE: 1290 mhd_assert (0 && 1291 "The handshake must be fully completed earlier"); 1292 break; 1293 1294 case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: 1295 mhd_assert (0 && "MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS must not be returned"); 1296 break; 1297 1298 case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: 1299 /* MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS means that recv() should be called 1300 again later. Pretend that data is already pending to not block on 1301 waiting for the new incoming data. */ 1302 c_tls->recv_data_in_buff = true; 1303 return mhd_SOCKET_ERR_INTR; /* Do not clear 'recv-ready' flag */ 1304 1305 case MBEDTLS_ERR_SSL_CLIENT_RECONNECT: 1306 mhd_assert (0 && 1307 "MBEDTLS_ERR_SSL_CLIENT_RECONNECT must not be " 1308 "returned for non-DTLS"); 1309 break; 1310 1311 case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET: 1312 mhd_assert (0 && 1313 "MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET must not be " 1314 "returned on the server side"); 1315 break; 1316 1317 case MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA: 1318 #ifdef MBEDTLS_SSL_EARLY_DATA 1319 /* Could be replaced with early data support is implemented */ 1320 #endif /* MBEDTLS_SSL_EARLY_DATA */ 1321 mhd_assert (0 && 1322 "MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA must not be returned"); 1323 break; 1324 1325 default: 1326 break; /* Handle other values below */ 1327 } 1328 1329 /* Treat all other kinds of errors as hard errors */ 1330 #ifndef NDEBUG 1331 c_tls->dbg.is_failed = true; 1332 #endif /* ! NDEBUG */ 1333 return mhd_SOCKET_ERR_TLS; 1334 } 1335 1336 1337 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool 1338 mhd_tls_mbed_conn_has_data_in (struct mhd_TlsMbedConnData *restrict c_tls) 1339 { 1340 return c_tls->recv_data_in_buff || 1341 (0 != mbedtls_ssl_check_pending (&(c_tls->sess))); 1342 } 1343 1344 1345 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1346 MHD_FN_PAR_IN_SIZE_ (3,2) 1347 MHD_FN_PAR_OUT_ (5) enum mhd_SocketError 1348 mhd_tls_mbed_conn_send (struct mhd_TlsMbedConnData *c_tls, 1349 size_t buf_size, 1350 const char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)], 1351 bool push_data, 1352 size_t *restrict sent) 1353 { 1354 int res; 1355 1356 mhd_assert (0 != buf_size); 1357 1358 mhd_assert (c_tls->dbg.is_inited); 1359 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1360 mhd_assert (! c_tls->shut_tls_wr_sent); 1361 mhd_assert (! c_tls->dbg.is_failed); 1362 1363 if (1) 1364 { 1365 const int buf_size_i = (int) buf_size; 1366 if ((0 > buf_size_i) || 1367 (buf_size != (size_t) buf_size_i)) 1368 { 1369 /* Called function return value limitation */ 1370 buf_size = (size_t) (((unsigned int) ~((unsigned int) 0)) >> 1u); 1371 push_data = false; 1372 } 1373 } 1374 1375 mhd_tls_mbed_sckt_comm_prep_send (c_tls, 1376 buf_size, 1377 push_data); 1378 1379 res = mbedtls_ssl_write (&(c_tls->sess), 1380 (const unsigned char *) buf, 1381 buf_size); 1382 1383 if (0 < res) 1384 { 1385 mhd_ASSUME (buf_size >= (size_t) res); 1386 *sent = (size_t) res; 1387 1388 return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */ 1389 } 1390 1391 switch (res) 1392 { 1393 case 0: 1394 mhd_assert (0 && 1395 "Zero must not be returned when sending non-zero size"); 1396 break; 1397 1398 case MBEDTLS_ERR_SSL_WANT_WRITE: 1399 mhd_assert (! mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.send_res)); 1400 mhd_assert (! mhd_SOCKET_ERR_IS_HARD (c_tls->tr.state.recv_res)); 1401 1402 if (! c_tls->tr.state.send_called) 1403 return mhd_SOCKET_ERR_INTR; /* Do not clear 'recv-ready' flag */ 1404 1405 if (mhd_SOCKET_ERR_NO_ERROR == c_tls->tr.state.send_res) 1406 { 1407 /* send() succeed for the first time and then called again */ 1408 return c_tls->tr.sk->props.is_nonblck ? 1409 mhd_SOCKET_ERR_INTR : mhd_SOCKET_ERR_AGAIN; 1410 } 1411 1412 return c_tls->tr.state.send_res; 1413 1414 case MBEDTLS_ERR_SSL_WANT_READ: 1415 mhd_assert (0 && 1416 "The handshake must be fully completed earlier"); 1417 break; 1418 1419 case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: 1420 mhd_assert (0 && "MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS must not be returned"); 1421 break; 1422 1423 case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: 1424 /* MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS means that send() should be called 1425 again later. Wait for 'send-ready' which should be already set or 1426 will be set later, when OS pushed the data to the network. */ 1427 return mhd_SOCKET_ERR_INTR; /* Do not clear 'recv-ready' flag */ 1428 1429 case MBEDTLS_ERR_SSL_CLIENT_RECONNECT: 1430 mhd_assert (0 && 1431 "MBEDTLS_ERR_SSL_CLIENT_RECONNECT must not be " 1432 "returned for non-DTLS"); 1433 break; 1434 1435 case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET: 1436 mhd_assert (0 && 1437 "MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET must not be " 1438 "returned on the server side"); 1439 break; 1440 1441 case MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA: 1442 #ifdef MBEDTLS_SSL_EARLY_DATA 1443 /* Could be replaced with early data support is implemented */ 1444 #endif /* MBEDTLS_SSL_EARLY_DATA */ 1445 mhd_assert (0 && 1446 "MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA must not be returned"); 1447 break; 1448 1449 default: 1450 break; /* Handle other values below */ 1451 } 1452 1453 /* Treat all other kinds of errors as hard errors */ 1454 #ifndef NDEBUG 1455 c_tls->dbg.is_failed = true; 1456 #endif /* ! NDEBUG */ 1457 return mhd_SOCKET_ERR_TLS; 1458 } 1459 1460 1461 /* ** TLS connection information ** */ 1462 1463 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1464 MHD_FN_PAR_OUT_ (2) void 1465 mhd_tls_mbed_conn_get_tls_sess ( 1466 struct mhd_TlsMbedConnData *restrict c_tls, 1467 union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out) 1468 { 1469 tls_sess_out->v_mbedtls_session = &(c_tls->sess); 1470 } 1471 1472 1473 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1474 MHD_FN_PAR_OUT_ (2) bool 1475 mhd_tls_mbed_conn_get_tls_ver (struct mhd_TlsMbedConnData *restrict c_tls, 1476 struct mhd_StctTlsVersion *restrict tls_ver_out) 1477 { 1478 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1479 1480 #ifndef MBEDTLS_VERSION_NUMBER 1481 if (1) 1482 return false; /* Need MbedTLS version number to implement */ 1483 #else /* MBEDTLS_VERSION_NUMBER */ 1484 if (1) 1485 { 1486 uint_fast16_t tls_ver_num; 1487 #if ((MBEDTLS_VERSION_NUMBER + 0) >= 0x03020000) 1488 mbedtls_ssl_protocol_version mbedtls_tls_ver; 1489 1490 mbedtls_tls_ver = mbedtls_ssl_get_version_number (&(c_tls->sess)); 1491 1492 tls_ver_num = (uint_fast16_t) mbedtls_tls_ver; 1493 #else /* MBEDTLS_VERSION_NUMBER < 0x03020000 */ 1494 tls_ver_num = (uint_fast16_t) c_tls->sess.MBEDTLS_PRIVATE (major_ver); 1495 tls_ver_num <<= 8u; 1496 tls_ver_num |= (uint_fast16_t) c_tls->sess.MBEDTLS_PRIVATE (minor_ver); 1497 #endif /* MBEDTLS_VERSION_NUMBER < 0x03020000 */ 1498 /* Avoid MbedTLS helper macros and enum values in switch() as they are 1499 unstable in MbedTLS. */ 1500 switch (tls_ver_num) 1501 { 1502 case 0u: 1503 return false; 1504 1505 case 0x0301u: /* Not really supported by MbedTLS >=3.0 */ 1506 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_0; 1507 break; 1508 1509 case 0x0302u: /* Not really supported by MbedTLS >=3.0 */ 1510 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_1; 1511 break; 1512 1513 case 0x0303u: 1514 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_2; 1515 break; 1516 1517 case 0x0304u: 1518 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_3; 1519 break; 1520 1521 default: 1522 tls_ver_out->tls_ver = MHD_TLS_VERSION_UNKNOWN; 1523 break; 1524 } 1525 } 1526 #endif /* MBEDTLS_VERSION_NUMBER */ 1527 1528 return true; 1529 } 1530 1531 1532 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ enum mhd_TlsAlpnProt 1533 mhd_tls_mbed_conn_get_alpn_prot (struct mhd_TlsMbedConnData *restrict c_tls) 1534 { 1535 #ifdef MBEDTLS_SSL_ALPN 1536 const char *alpn_str; 1537 1538 alpn_str = mbedtls_ssl_get_alpn_protocol (&(c_tls->sess)); 1539 if (NULL == alpn_str) 1540 return mhd_TLS_ALPN_PROT_NOT_SELECTED; 1541 1542 return mhd_tls_alpn_decode_n (strlen (alpn_str), 1543 (const unsigned char *) alpn_str); 1544 #else /* ! MBEDTLS_SSL_ALPN */ 1545 return mhd_TLS_ALPN_PROT_NOT_SELECTED; 1546 #endif /* ! MBEDTLS_SSL_ALPN */ 1547 }