1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com> 10 * 11 * This software is licensed as described in the file COPYING, which 12 * you should have received as part of this distribution. The terms 13 * are also available at https://curl.se/docs/copyright.html. 14 * 15 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 16 * copies of the Software, and permit persons to whom the Software is 17 * furnished to do so, under the terms of the COPYING file. 18 * 19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20 * KIND, either express or implied. 21 * 22 * SPDX-License-Identifier: curl 23 * 24 ***************************************************************************/ 25 26/* 27 * Source file for all mbedTLS-specific code for the TLS/SSL layer. No code 28 * but vtls.c should ever call or use these functions. 29 * 30 */ 31 32#include "curl_setup.h" 33 34#ifdef USE_MBEDTLS 35 36/* Define this to enable lots of debugging for mbedTLS */ 37/* #define MBEDTLS_DEBUG */ 38 39#ifdef __GNUC__ 40#pragma GCC diagnostic push 41/* mbedTLS (as of v3.5.1) has a duplicate function declaration 42 in its public headers. Disable the warning that detects it. */ 43#pragma GCC diagnostic ignored "-Wredundant-decls" 44#endif 45 46#include <mbedtls/version.h> 47#if MBEDTLS_VERSION_NUMBER >= 0x02040000 48#include <mbedtls/net_sockets.h> 49#else 50#include <mbedtls/net.h> 51#endif 52#include <mbedtls/ssl.h> 53#include <mbedtls/x509.h> 54 55#include <mbedtls/error.h> 56#include <mbedtls/entropy.h> 57#include <mbedtls/ctr_drbg.h> 58#include <mbedtls/sha256.h> 59 60#if MBEDTLS_VERSION_MAJOR >= 2 61# ifdef MBEDTLS_DEBUG 62# include <mbedtls/debug.h> 63# endif 64#endif 65 66#ifdef __GNUC__ 67#pragma GCC diagnostic pop 68#endif 69 70#include "urldata.h" 71#include "sendf.h" 72#include "inet_pton.h" 73#include "mbedtls.h" 74#include "vtls.h" 75#include "vtls_int.h" 76#include "parsedate.h" 77#include "connect.h" /* for the connect timeout */ 78#include "select.h" 79#include "multiif.h" 80#include "mbedtls_threadlock.h" 81#include "strdup.h" 82 83/* The last 3 #include files should be in this order */ 84#include "curl_printf.h" 85#include "curl_memory.h" 86#include "memdebug.h" 87 88/* ALPN for http2 */ 89#ifdef USE_HTTP2 90# undef HAS_ALPN 91# ifdef MBEDTLS_SSL_ALPN 92# define HAS_ALPN 93# endif 94#endif 95 96struct mbed_ssl_backend_data { 97 mbedtls_ctr_drbg_context ctr_drbg; 98 mbedtls_entropy_context entropy; 99 mbedtls_ssl_context ssl; 100 mbedtls_x509_crt cacert; 101 mbedtls_x509_crt clicert; 102#ifdef MBEDTLS_X509_CRL_PARSE_C 103 mbedtls_x509_crl crl; 104#endif 105 mbedtls_pk_context pk; 106 mbedtls_ssl_config config; 107#ifdef HAS_ALPN 108 const char *protocols[3]; 109#endif 110}; 111 112/* apply threading? */ 113#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) 114#define THREADING_SUPPORT 115#endif 116 117#ifndef MBEDTLS_ERROR_C 118#define mbedtls_strerror(a,b,c) b[0] = 0 119#endif 120 121#if defined(THREADING_SUPPORT) 122static mbedtls_entropy_context ts_entropy; 123 124static int entropy_init_initialized = 0; 125 126/* start of entropy_init_mutex() */ 127static void entropy_init_mutex(mbedtls_entropy_context *ctx) 128{ 129 /* lock 0 = entropy_init_mutex() */ 130 Curl_mbedtlsthreadlock_lock_function(0); 131 if(entropy_init_initialized == 0) { 132 mbedtls_entropy_init(ctx); 133 entropy_init_initialized = 1; 134 } 135 Curl_mbedtlsthreadlock_unlock_function(0); 136} 137/* end of entropy_init_mutex() */ 138 139/* start of entropy_func_mutex() */ 140static int entropy_func_mutex(void *data, unsigned char *output, size_t len) 141{ 142 int ret; 143 /* lock 1 = entropy_func_mutex() */ 144 Curl_mbedtlsthreadlock_lock_function(1); 145 ret = mbedtls_entropy_func(data, output, len); 146 Curl_mbedtlsthreadlock_unlock_function(1); 147 148 return ret; 149} 150/* end of entropy_func_mutex() */ 151 152#endif /* THREADING_SUPPORT */ 153 154#ifdef MBEDTLS_DEBUG 155static void mbed_debug(void *context, int level, const char *f_name, 156 int line_nb, const char *line) 157{ 158 struct Curl_easy *data = NULL; 159 160 if(!context) 161 return; 162 163 data = (struct Curl_easy *)context; 164 165 infof(data, "%s", line); 166 (void) level; 167} 168#endif 169 170static int mbedtls_bio_cf_write(void *bio, 171 const unsigned char *buf, size_t blen) 172{ 173 struct Curl_cfilter *cf = bio; 174 struct Curl_easy *data = CF_DATA_CURRENT(cf); 175 ssize_t nwritten; 176 CURLcode result; 177 178 DEBUGASSERT(data); 179 if(!data) 180 return 0; 181 182 nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result); 183 CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %zd, err=%d", 184 blen, nwritten, result); 185 if(nwritten < 0 && CURLE_AGAIN == result) { 186 nwritten = MBEDTLS_ERR_SSL_WANT_WRITE; 187 } 188 return (int)nwritten; 189} 190 191static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen) 192{ 193 struct Curl_cfilter *cf = bio; 194 struct Curl_easy *data = CF_DATA_CURRENT(cf); 195 ssize_t nread; 196 CURLcode result; 197 198 DEBUGASSERT(data); 199 if(!data) 200 return 0; 201 /* OpenSSL catches this case, so should we. */ 202 if(!buf) 203 return 0; 204 205 nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result); 206 CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %zd, err=%d", 207 blen, nread, result); 208 if(nread < 0 && CURLE_AGAIN == result) { 209 nread = MBEDTLS_ERR_SSL_WANT_READ; 210 } 211 return (int)nread; 212} 213 214/* 215 * profile 216 */ 217static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = 218{ 219 /* Hashes from SHA-1 and above */ 220 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | 221 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) | 222 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | 223 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | 224 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | 225 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), 226 0xFFFFFFF, /* Any PK alg */ 227 0xFFFFFFF, /* Any curve */ 228 1024, /* RSA min key len */ 229}; 230 231/* See https://tls.mbed.org/discussions/generic/ 232 howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der 233*/ 234#define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) 235#define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) 236 237#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ 238 RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) 239 240static CURLcode mbedtls_version_from_curl(int *mbedver, long version) 241{ 242#if MBEDTLS_VERSION_NUMBER >= 0x03000000 243 switch(version) { 244 case CURL_SSLVERSION_TLSv1_0: 245 case CURL_SSLVERSION_TLSv1_1: 246 case CURL_SSLVERSION_TLSv1_2: 247 *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; 248 return CURLE_OK; 249 case CURL_SSLVERSION_TLSv1_3: 250 break; 251 } 252#else 253 switch(version) { 254 case CURL_SSLVERSION_TLSv1_0: 255 *mbedver = MBEDTLS_SSL_MINOR_VERSION_1; 256 return CURLE_OK; 257 case CURL_SSLVERSION_TLSv1_1: 258 *mbedver = MBEDTLS_SSL_MINOR_VERSION_2; 259 return CURLE_OK; 260 case CURL_SSLVERSION_TLSv1_2: 261 *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; 262 return CURLE_OK; 263 case CURL_SSLVERSION_TLSv1_3: 264 break; 265 } 266#endif 267 268 return CURLE_SSL_CONNECT_ERROR; 269} 270 271static CURLcode 272set_ssl_version_min_max(struct Curl_cfilter *cf, struct Curl_easy *data) 273{ 274 struct ssl_connect_data *connssl = cf->ctx; 275 struct mbed_ssl_backend_data *backend = 276 (struct mbed_ssl_backend_data *)connssl->backend; 277 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 278#if MBEDTLS_VERSION_NUMBER >= 0x03000000 279 int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3; 280 int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_3; 281#else 282 int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; 283 int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; 284#endif 285 long ssl_version = conn_config->version; 286 long ssl_version_max = conn_config->version_max; 287 CURLcode result = CURLE_OK; 288 289 DEBUGASSERT(backend); 290 291 switch(ssl_version) { 292 case CURL_SSLVERSION_DEFAULT: 293 case CURL_SSLVERSION_TLSv1: 294 ssl_version = CURL_SSLVERSION_TLSv1_0; 295 break; 296 } 297 298 switch(ssl_version_max) { 299 case CURL_SSLVERSION_MAX_NONE: 300 case CURL_SSLVERSION_MAX_DEFAULT: 301 ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; 302 break; 303 } 304 305 result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version); 306 if(result) { 307 failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); 308 return result; 309 } 310 result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16); 311 if(result) { 312 failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); 313 return result; 314 } 315 316 mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, 317 mbedtls_ver_min); 318 mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, 319 mbedtls_ver_max); 320 321 return result; 322} 323 324static CURLcode 325mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) 326{ 327 struct ssl_connect_data *connssl = cf->ctx; 328 struct mbed_ssl_backend_data *backend = 329 (struct mbed_ssl_backend_data *)connssl->backend; 330 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 331 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; 332 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 333 const char * const ssl_cafile = 334 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ 335 (ca_info_blob ? NULL : conn_config->CAfile); 336 const bool verifypeer = conn_config->verifypeer; 337 const char * const ssl_capath = conn_config->CApath; 338 char * const ssl_cert = ssl_config->primary.clientcert; 339 const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; 340 const char * const ssl_crlfile = ssl_config->primary.CRLfile; 341 const char *hostname = connssl->peer.hostname; 342 int ret = -1; 343 char errorbuf[128]; 344 345 DEBUGASSERT(backend); 346 347 if((conn_config->version == CURL_SSLVERSION_SSLv2) || 348 (conn_config->version == CURL_SSLVERSION_SSLv3)) { 349 failf(data, "Not supported SSL version"); 350 return CURLE_NOT_BUILT_IN; 351 } 352 353#ifdef THREADING_SUPPORT 354 entropy_init_mutex(&ts_entropy); 355 mbedtls_ctr_drbg_init(&backend->ctr_drbg); 356 357 ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex, 358 &ts_entropy, NULL, 0); 359 if(ret) { 360 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 361 failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", 362 -ret, errorbuf); 363 return CURLE_FAILED_INIT; 364 } 365#else 366 mbedtls_entropy_init(&backend->entropy); 367 mbedtls_ctr_drbg_init(&backend->ctr_drbg); 368 369 ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func, 370 &backend->entropy, NULL, 0); 371 if(ret) { 372 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 373 failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", 374 -ret, errorbuf); 375 return CURLE_FAILED_INIT; 376 } 377#endif /* THREADING_SUPPORT */ 378 379 /* Load the trusted CA */ 380 mbedtls_x509_crt_init(&backend->cacert); 381 382 if(ca_info_blob && verifypeer) { 383 /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null 384 terminated even when provided the exact length, forcing us to waste 385 extra memory here. */ 386 unsigned char *newblob = Curl_memdup0(ca_info_blob->data, 387 ca_info_blob->len); 388 if(!newblob) 389 return CURLE_OUT_OF_MEMORY; 390 ret = mbedtls_x509_crt_parse(&backend->cacert, newblob, 391 ca_info_blob->len + 1); 392 free(newblob); 393 if(ret<0) { 394 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 395 failf(data, "Error importing ca cert blob - mbedTLS: (-0x%04X) %s", 396 -ret, errorbuf); 397 return CURLE_SSL_CERTPROBLEM; 398 } 399 } 400 401 if(ssl_cafile && verifypeer) { 402#ifdef MBEDTLS_FS_IO 403 ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile); 404 405 if(ret<0) { 406 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 407 failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", 408 ssl_cafile, -ret, errorbuf); 409 return CURLE_SSL_CACERT_BADFILE; 410 } 411#else 412 failf(data, "mbedtls: functions that use the filesystem not built in"); 413 return CURLE_NOT_BUILT_IN; 414#endif 415 } 416 417 if(ssl_capath) { 418#ifdef MBEDTLS_FS_IO 419 ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath); 420 421 if(ret<0) { 422 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 423 failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", 424 ssl_capath, -ret, errorbuf); 425 426 if(verifypeer) 427 return CURLE_SSL_CACERT_BADFILE; 428 } 429#else 430 failf(data, "mbedtls: functions that use the filesystem not built in"); 431 return CURLE_NOT_BUILT_IN; 432#endif 433 } 434 435 /* Load the client certificate */ 436 mbedtls_x509_crt_init(&backend->clicert); 437 438 if(ssl_cert) { 439#ifdef MBEDTLS_FS_IO 440 ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert); 441 442 if(ret) { 443 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 444 failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", 445 ssl_cert, -ret, errorbuf); 446 447 return CURLE_SSL_CERTPROBLEM; 448 } 449#else 450 failf(data, "mbedtls: functions that use the filesystem not built in"); 451 return CURLE_NOT_BUILT_IN; 452#endif 453 } 454 455 if(ssl_cert_blob) { 456 /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null 457 terminated even when provided the exact length, forcing us to waste 458 extra memory here. */ 459 unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data, 460 ssl_cert_blob->len); 461 if(!newblob) 462 return CURLE_OUT_OF_MEMORY; 463 ret = mbedtls_x509_crt_parse(&backend->clicert, newblob, 464 ssl_cert_blob->len + 1); 465 free(newblob); 466 467 if(ret) { 468 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 469 failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", 470 ssl_config->key, -ret, errorbuf); 471 return CURLE_SSL_CERTPROBLEM; 472 } 473 } 474 475 /* Load the client private key */ 476 mbedtls_pk_init(&backend->pk); 477 478 if(ssl_config->key || ssl_config->key_blob) { 479 if(ssl_config->key) { 480#ifdef MBEDTLS_FS_IO 481#if MBEDTLS_VERSION_NUMBER >= 0x03000000 482 ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key, 483 ssl_config->key_passwd, 484 mbedtls_ctr_drbg_random, 485 &backend->ctr_drbg); 486#else 487 ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key, 488 ssl_config->key_passwd); 489#endif 490 491 if(ret) { 492 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 493 failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", 494 ssl_config->key, -ret, errorbuf); 495 return CURLE_SSL_CERTPROBLEM; 496 } 497#else 498 failf(data, "mbedtls: functions that use the filesystem not built in"); 499 return CURLE_NOT_BUILT_IN; 500#endif 501 } 502 else { 503 const struct curl_blob *ssl_key_blob = ssl_config->key_blob; 504 const unsigned char *key_data = 505 (const unsigned char *)ssl_key_blob->data; 506 const char *passwd = ssl_config->key_passwd; 507#if MBEDTLS_VERSION_NUMBER >= 0x03000000 508 ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, 509 (const unsigned char *)passwd, 510 passwd ? strlen(passwd) : 0, 511 mbedtls_ctr_drbg_random, 512 &backend->ctr_drbg); 513#else 514 ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, 515 (const unsigned char *)passwd, 516 passwd ? strlen(passwd) : 0); 517#endif 518 519 if(ret) { 520 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 521 failf(data, "Error parsing private key - mbedTLS: (-0x%04X) %s", 522 -ret, errorbuf); 523 return CURLE_SSL_CERTPROBLEM; 524 } 525 } 526 527 if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) || 528 mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY))) 529 ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; 530 } 531 532 /* Load the CRL */ 533#ifdef MBEDTLS_X509_CRL_PARSE_C 534 mbedtls_x509_crl_init(&backend->crl); 535 536 if(ssl_crlfile) { 537#ifdef MBEDTLS_FS_IO 538 ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile); 539 540 if(ret) { 541 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 542 failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", 543 ssl_crlfile, -ret, errorbuf); 544 545 return CURLE_SSL_CRL_BADFILE; 546 } 547#else 548 failf(data, "mbedtls: functions that use the filesystem not built in"); 549 return CURLE_NOT_BUILT_IN; 550#endif 551 } 552#else 553 if(ssl_crlfile) { 554 failf(data, "mbedtls: crl support not built in"); 555 return CURLE_NOT_BUILT_IN; 556 } 557#endif 558 559 infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->port); 560 561 mbedtls_ssl_config_init(&backend->config); 562 ret = mbedtls_ssl_config_defaults(&backend->config, 563 MBEDTLS_SSL_IS_CLIENT, 564 MBEDTLS_SSL_TRANSPORT_STREAM, 565 MBEDTLS_SSL_PRESET_DEFAULT); 566 if(ret) { 567 failf(data, "mbedTLS: ssl_config failed"); 568 return CURLE_SSL_CONNECT_ERROR; 569 } 570 571 mbedtls_ssl_init(&backend->ssl); 572 if(mbedtls_ssl_setup(&backend->ssl, &backend->config)) { 573 failf(data, "mbedTLS: ssl_init failed"); 574 return CURLE_SSL_CONNECT_ERROR; 575 } 576 577 /* new profile with RSA min key len = 1024 ... */ 578 mbedtls_ssl_conf_cert_profile(&backend->config, 579 &mbedtls_x509_crt_profile_fr); 580 581 switch(conn_config->version) { 582 case CURL_SSLVERSION_DEFAULT: 583 case CURL_SSLVERSION_TLSv1: 584#if MBEDTLS_VERSION_NUMBER < 0x03000000 585 mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, 586 MBEDTLS_SSL_MINOR_VERSION_1); 587 infof(data, "mbedTLS: Set min SSL version to TLS 1.0"); 588 break; 589#endif 590 case CURL_SSLVERSION_TLSv1_0: 591 case CURL_SSLVERSION_TLSv1_1: 592 case CURL_SSLVERSION_TLSv1_2: 593 case CURL_SSLVERSION_TLSv1_3: 594 { 595 CURLcode result = set_ssl_version_min_max(cf, data); 596 if(result != CURLE_OK) 597 return result; 598 break; 599 } 600 default: 601 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); 602 return CURLE_SSL_CONNECT_ERROR; 603 } 604 605 mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL); 606 607 mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random, 608 &backend->ctr_drbg); 609 mbedtls_ssl_set_bio(&backend->ssl, cf, 610 mbedtls_bio_cf_write, 611 mbedtls_bio_cf_read, 612 NULL /* rev_timeout() */); 613 614 mbedtls_ssl_conf_ciphersuites(&backend->config, 615 mbedtls_ssl_list_ciphersuites()); 616 617#if defined(MBEDTLS_SSL_RENEGOTIATION) 618 mbedtls_ssl_conf_renegotiation(&backend->config, 619 MBEDTLS_SSL_RENEGOTIATION_ENABLED); 620#endif 621 622#if defined(MBEDTLS_SSL_SESSION_TICKETS) 623 mbedtls_ssl_conf_session_tickets(&backend->config, 624 MBEDTLS_SSL_SESSION_TICKETS_DISABLED); 625#endif 626 627 /* Check if there's a cached ID we can/should use here! */ 628 if(ssl_config->primary.sessionid) { 629 void *old_session = NULL; 630 631 Curl_ssl_sessionid_lock(data); 632 if(!Curl_ssl_getsessionid(cf, data, &old_session, NULL)) { 633 ret = mbedtls_ssl_set_session(&backend->ssl, old_session); 634 if(ret) { 635 Curl_ssl_sessionid_unlock(data); 636 failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); 637 return CURLE_SSL_CONNECT_ERROR; 638 } 639 infof(data, "mbedTLS reusing session"); 640 } 641 Curl_ssl_sessionid_unlock(data); 642 } 643 644 mbedtls_ssl_conf_ca_chain(&backend->config, 645 &backend->cacert, 646#ifdef MBEDTLS_X509_CRL_PARSE_C 647 &backend->crl); 648#else 649 NULL); 650#endif 651 652 if(ssl_config->key || ssl_config->key_blob) { 653 mbedtls_ssl_conf_own_cert(&backend->config, 654 &backend->clicert, &backend->pk); 655 } 656 657 if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni? 658 connssl->peer.sni : connssl->peer.hostname)) { 659 /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and 660 the name to set in the SNI extension. So even if curl connects to a 661 host specified as an IP address, this function must be used. */ 662 failf(data, "Failed to set SNI"); 663 return CURLE_SSL_CONNECT_ERROR; 664 } 665 666#ifdef HAS_ALPN 667 if(connssl->alpn) { 668 struct alpn_proto_buf proto; 669 size_t i; 670 671 for(i = 0; i < connssl->alpn->count; ++i) { 672 backend->protocols[i] = connssl->alpn->entries[i]; 673 } 674 /* this function doesn't clone the protocols array, which is why we need 675 to keep it around */ 676 if(mbedtls_ssl_conf_alpn_protocols(&backend->config, 677 &backend->protocols[0])) { 678 failf(data, "Failed setting ALPN protocols"); 679 return CURLE_SSL_CONNECT_ERROR; 680 } 681 Curl_alpn_to_proto_str(&proto, connssl->alpn); 682 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); 683 } 684#endif 685 686#ifdef MBEDTLS_DEBUG 687 /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ 688 mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data); 689 /* - 0 No debug 690 * - 1 Error 691 * - 2 State change 692 * - 3 Informational 693 * - 4 Verbose 694 */ 695 mbedtls_debug_set_threshold(4); 696#endif 697 698 /* give application a chance to interfere with mbedTLS set up. */ 699 if(data->set.ssl.fsslctx) { 700 ret = (*data->set.ssl.fsslctx)(data, &backend->config, 701 data->set.ssl.fsslctxp); 702 if(ret) { 703 failf(data, "error signaled by ssl ctx callback"); 704 return ret; 705 } 706 } 707 708 connssl->connecting_state = ssl_connect_2; 709 710 return CURLE_OK; 711} 712 713static CURLcode 714mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) 715{ 716 int ret; 717 struct ssl_connect_data *connssl = cf->ctx; 718 struct mbed_ssl_backend_data *backend = 719 (struct mbed_ssl_backend_data *)connssl->backend; 720 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 721 const mbedtls_x509_crt *peercert; 722 const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)? 723 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]: 724 data->set.str[STRING_SSL_PINNEDPUBLICKEY]; 725 726 DEBUGASSERT(backend); 727 728 ret = mbedtls_ssl_handshake(&backend->ssl); 729 730 if(ret == MBEDTLS_ERR_SSL_WANT_READ) { 731 connssl->connecting_state = ssl_connect_2_reading; 732 return CURLE_OK; 733 } 734 else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) { 735 connssl->connecting_state = ssl_connect_2_writing; 736 return CURLE_OK; 737 } 738 else if(ret) { 739 char errorbuf[128]; 740 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 741 failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s", 742 -ret, errorbuf); 743 return CURLE_SSL_CONNECT_ERROR; 744 } 745 746 infof(data, "mbedTLS: Handshake complete, cipher is %s", 747 mbedtls_ssl_get_ciphersuite(&backend->ssl)); 748 749 ret = mbedtls_ssl_get_verify_result(&backend->ssl); 750 751 if(!conn_config->verifyhost) 752 /* Ignore hostname errors if verifyhost is disabled */ 753 ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; 754 755 if(ret && conn_config->verifypeer) { 756 if(ret & MBEDTLS_X509_BADCERT_EXPIRED) 757 failf(data, "Cert verify failed: BADCERT_EXPIRED"); 758 759 else if(ret & MBEDTLS_X509_BADCERT_REVOKED) 760 failf(data, "Cert verify failed: BADCERT_REVOKED"); 761 762 else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) 763 failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); 764 765 else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) 766 failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); 767 768 else if(ret & MBEDTLS_X509_BADCERT_FUTURE) 769 failf(data, "Cert verify failed: BADCERT_FUTURE"); 770 771 return CURLE_PEER_FAILED_VERIFICATION; 772 } 773 774 peercert = mbedtls_ssl_get_peer_cert(&backend->ssl); 775 776 if(peercert && data->set.verbose) { 777 const size_t bufsize = 16384; 778 char *buffer = malloc(bufsize); 779 780 if(!buffer) 781 return CURLE_OUT_OF_MEMORY; 782 783 if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0) 784 infof(data, "Dumping cert info: %s", buffer); 785 else 786 infof(data, "Unable to dump certificate information"); 787 788 free(buffer); 789 } 790 791 if(pinnedpubkey) { 792 int size; 793 CURLcode result; 794 mbedtls_x509_crt *p = NULL; 795 unsigned char *pubkey = NULL; 796 797#if MBEDTLS_VERSION_NUMBER == 0x03000000 798 if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) || 799 !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) { 800#else 801 if(!peercert || !peercert->raw.p || !peercert->raw.len) { 802#endif 803 failf(data, "Failed due to missing peer certificate"); 804 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 805 } 806 807 p = calloc(1, sizeof(*p)); 808 809 if(!p) 810 return CURLE_OUT_OF_MEMORY; 811 812 pubkey = malloc(PUB_DER_MAX_BYTES); 813 814 if(!pubkey) { 815 result = CURLE_OUT_OF_MEMORY; 816 goto pinnedpubkey_error; 817 } 818 819 mbedtls_x509_crt_init(p); 820 821 /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der 822 needs a non-const key, for now. 823 https://github.com/ARMmbed/mbedtls/issues/396 */ 824#if MBEDTLS_VERSION_NUMBER == 0x03000000 825 if(mbedtls_x509_crt_parse_der(p, 826 peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p), 827 peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) { 828#else 829 if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { 830#endif 831 failf(data, "Failed copying peer certificate"); 832 result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; 833 goto pinnedpubkey_error; 834 } 835 836#if MBEDTLS_VERSION_NUMBER == 0x03000000 837 size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey, 838 PUB_DER_MAX_BYTES); 839#else 840 size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); 841#endif 842 843 if(size <= 0) { 844 failf(data, "Failed copying public key from peer certificate"); 845 result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; 846 goto pinnedpubkey_error; 847 } 848 849 /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ 850 result = Curl_pin_peer_pubkey(data, 851 pinnedpubkey, 852 &pubkey[PUB_DER_MAX_BYTES - size], size); 853pinnedpubkey_error: 854 mbedtls_x509_crt_free(p); 855 free(p); 856 free(pubkey); 857 if(result) { 858 return result; 859 } 860 } 861 862#ifdef HAS_ALPN 863 if(connssl->alpn) { 864 const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl); 865 866 Curl_alpn_set_negotiated(cf, data, (const unsigned char *)proto, 867 proto? strlen(proto) : 0); 868 } 869#endif 870 871 connssl->connecting_state = ssl_connect_3; 872 infof(data, "SSL connected"); 873 874 return CURLE_OK; 875} 876 877static CURLcode 878mbed_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) 879{ 880 CURLcode retcode = CURLE_OK; 881 struct ssl_connect_data *connssl = cf->ctx; 882 struct mbed_ssl_backend_data *backend = 883 (struct mbed_ssl_backend_data *)connssl->backend; 884 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 885 886 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); 887 DEBUGASSERT(backend); 888 889 if(ssl_config->primary.sessionid) { 890 int ret; 891 mbedtls_ssl_session *our_ssl_sessionid; 892 void *old_ssl_sessionid = NULL; 893 bool added = FALSE; 894 895 our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session)); 896 if(!our_ssl_sessionid) 897 return CURLE_OUT_OF_MEMORY; 898 899 mbedtls_ssl_session_init(our_ssl_sessionid); 900 901 ret = mbedtls_ssl_get_session(&backend->ssl, our_ssl_sessionid); 902 if(ret) { 903 if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED) 904 mbedtls_ssl_session_free(our_ssl_sessionid); 905 free(our_ssl_sessionid); 906 failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); 907 return CURLE_SSL_CONNECT_ERROR; 908 } 909 910 /* If there's already a matching session in the cache, delete it */ 911 Curl_ssl_sessionid_lock(data); 912 if(!Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL)) 913 Curl_ssl_delsessionid(data, old_ssl_sessionid); 914 915 retcode = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid, 916 0, &added); 917 Curl_ssl_sessionid_unlock(data); 918 if(!added) { 919 mbedtls_ssl_session_free(our_ssl_sessionid); 920 free(our_ssl_sessionid); 921 } 922 if(retcode) { 923 failf(data, "failed to store ssl session"); 924 return retcode; 925 } 926 } 927 928 connssl->connecting_state = ssl_connect_done; 929 930 return CURLE_OK; 931} 932 933static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data, 934 const void *mem, size_t len, 935 CURLcode *curlcode) 936{ 937 struct ssl_connect_data *connssl = cf->ctx; 938 struct mbed_ssl_backend_data *backend = 939 (struct mbed_ssl_backend_data *)connssl->backend; 940 int ret = -1; 941 942 (void)data; 943 DEBUGASSERT(backend); 944 ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len); 945 946 if(ret < 0) { 947 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ? 948 CURLE_AGAIN : CURLE_SEND_ERROR; 949 ret = -1; 950 } 951 952 return ret; 953} 954 955static void mbedtls_close_all(struct Curl_easy *data) 956{ 957 (void)data; 958} 959 960static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data) 961{ 962 struct ssl_connect_data *connssl = cf->ctx; 963 struct mbed_ssl_backend_data *backend = 964 (struct mbed_ssl_backend_data *)connssl->backend; 965 char buf[32]; 966 967 (void)data; 968 DEBUGASSERT(backend); 969 970 /* Maybe the server has already sent a close notify alert. 971 Read it to avoid an RST on the TCP connection. */ 972 (void)mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, sizeof(buf)); 973 974 mbedtls_pk_free(&backend->pk); 975 mbedtls_x509_crt_free(&backend->clicert); 976 mbedtls_x509_crt_free(&backend->cacert); 977#ifdef MBEDTLS_X509_CRL_PARSE_C 978 mbedtls_x509_crl_free(&backend->crl); 979#endif 980 mbedtls_ssl_config_free(&backend->config); 981 mbedtls_ssl_free(&backend->ssl); 982 mbedtls_ctr_drbg_free(&backend->ctr_drbg); 983#ifndef THREADING_SUPPORT 984 mbedtls_entropy_free(&backend->entropy); 985#endif /* THREADING_SUPPORT */ 986} 987 988static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data, 989 char *buf, size_t buffersize, 990 CURLcode *curlcode) 991{ 992 struct ssl_connect_data *connssl = cf->ctx; 993 struct mbed_ssl_backend_data *backend = 994 (struct mbed_ssl_backend_data *)connssl->backend; 995 int ret = -1; 996 ssize_t len = -1; 997 998 (void)data; 999 DEBUGASSERT(backend); 1000 1001 ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, 1002 buffersize); 1003 1004 if(ret <= 0) { 1005 if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) 1006 return 0; 1007 1008 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ? 1009 CURLE_AGAIN : CURLE_RECV_ERROR; 1010 return -1; 1011 } 1012 1013 len = ret; 1014 1015 return len; 1016} 1017 1018static void mbedtls_session_free(void *ptr) 1019{ 1020 mbedtls_ssl_session_free(ptr); 1021 free(ptr); 1022} 1023 1024static size_t mbedtls_version(char *buffer, size_t size) 1025{ 1026#ifdef MBEDTLS_VERSION_C 1027 /* if mbedtls_version_get_number() is available it is better */ 1028 unsigned int version = mbedtls_version_get_number(); 1029 return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24, 1030 (version>>16)&0xff, (version>>8)&0xff); 1031#else 1032 return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING); 1033#endif 1034} 1035 1036static CURLcode mbedtls_random(struct Curl_easy *data, 1037 unsigned char *entropy, size_t length) 1038{ 1039#if defined(MBEDTLS_CTR_DRBG_C) 1040 int ret = -1; 1041 char errorbuf[128]; 1042 mbedtls_entropy_context ctr_entropy; 1043 mbedtls_ctr_drbg_context ctr_drbg; 1044 mbedtls_entropy_init(&ctr_entropy); 1045 mbedtls_ctr_drbg_init(&ctr_drbg); 1046 1047 ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, 1048 &ctr_entropy, NULL, 0); 1049 1050 if(ret) { 1051 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 1052 failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", 1053 -ret, errorbuf); 1054 } 1055 else { 1056 ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length); 1057 1058 if(ret) { 1059 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 1060 failf(data, "mbedtls_ctr_drbg_random returned (-0x%04X) %s", 1061 -ret, errorbuf); 1062 } 1063 } 1064 1065 mbedtls_ctr_drbg_free(&ctr_drbg); 1066 mbedtls_entropy_free(&ctr_entropy); 1067 1068 return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT; 1069#elif defined(MBEDTLS_HAVEGE_C) 1070 mbedtls_havege_state hs; 1071 mbedtls_havege_init(&hs); 1072 mbedtls_havege_random(&hs, entropy, length); 1073 mbedtls_havege_free(&hs); 1074 return CURLE_OK; 1075#else 1076 return CURLE_NOT_BUILT_IN; 1077#endif 1078} 1079 1080static CURLcode 1081mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data, 1082 bool nonblocking, 1083 bool *done) 1084{ 1085 CURLcode retcode; 1086 struct ssl_connect_data *connssl = cf->ctx; 1087 curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); 1088 timediff_t timeout_ms; 1089 int what; 1090 1091 /* check if the connection has already been established */ 1092 if(ssl_connection_complete == connssl->state) { 1093 *done = TRUE; 1094 return CURLE_OK; 1095 } 1096 1097 if(ssl_connect_1 == connssl->connecting_state) { 1098 /* Find out how much more time we're allowed */ 1099 timeout_ms = Curl_timeleft(data, NULL, TRUE); 1100 1101 if(timeout_ms < 0) { 1102 /* no need to continue if time already is up */ 1103 failf(data, "SSL connection timeout"); 1104 return CURLE_OPERATION_TIMEDOUT; 1105 } 1106 retcode = mbed_connect_step1(cf, data); 1107 if(retcode) 1108 return retcode; 1109 } 1110 1111 while(ssl_connect_2 == connssl->connecting_state || 1112 ssl_connect_2_reading == connssl->connecting_state || 1113 ssl_connect_2_writing == connssl->connecting_state) { 1114 1115 /* check allowed time left */ 1116 timeout_ms = Curl_timeleft(data, NULL, TRUE); 1117 1118 if(timeout_ms < 0) { 1119 /* no need to continue if time already is up */ 1120 failf(data, "SSL connection timeout"); 1121 return CURLE_OPERATION_TIMEDOUT; 1122 } 1123 1124 /* if ssl is expecting something, check if it's available. */ 1125 if(connssl->connecting_state == ssl_connect_2_reading 1126 || connssl->connecting_state == ssl_connect_2_writing) { 1127 1128 curl_socket_t writefd = ssl_connect_2_writing == 1129 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 1130 curl_socket_t readfd = ssl_connect_2_reading == 1131 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 1132 1133 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 1134 nonblocking ? 0 : timeout_ms); 1135 if(what < 0) { 1136 /* fatal error */ 1137 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 1138 return CURLE_SSL_CONNECT_ERROR; 1139 } 1140 else if(0 == what) { 1141 if(nonblocking) { 1142 *done = FALSE; 1143 return CURLE_OK; 1144 } 1145 else { 1146 /* timeout */ 1147 failf(data, "SSL connection timeout"); 1148 return CURLE_OPERATION_TIMEDOUT; 1149 } 1150 } 1151 /* socket is readable or writable */ 1152 } 1153 1154 /* Run transaction, and return to the caller if it failed or if 1155 * this connection is part of a multi handle and this loop would 1156 * execute again. This permits the owner of a multi handle to 1157 * abort a connection attempt before step2 has completed while 1158 * ensuring that a client using select() or epoll() will always 1159 * have a valid fdset to wait on. 1160 */ 1161 retcode = mbed_connect_step2(cf, data); 1162 if(retcode || (nonblocking && 1163 (ssl_connect_2 == connssl->connecting_state || 1164 ssl_connect_2_reading == connssl->connecting_state || 1165 ssl_connect_2_writing == connssl->connecting_state))) 1166 return retcode; 1167 1168 } /* repeat step2 until all transactions are done. */ 1169 1170 if(ssl_connect_3 == connssl->connecting_state) { 1171 retcode = mbed_connect_step3(cf, data); 1172 if(retcode) 1173 return retcode; 1174 } 1175 1176 if(ssl_connect_done == connssl->connecting_state) { 1177 connssl->state = ssl_connection_complete; 1178 *done = TRUE; 1179 } 1180 else 1181 *done = FALSE; 1182 1183 /* Reset our connect state machine */ 1184 connssl->connecting_state = ssl_connect_1; 1185 1186 return CURLE_OK; 1187} 1188 1189static CURLcode mbedtls_connect_nonblocking(struct Curl_cfilter *cf, 1190 struct Curl_easy *data, 1191 bool *done) 1192{ 1193 return mbed_connect_common(cf, data, TRUE, done); 1194} 1195 1196 1197static CURLcode mbedtls_connect(struct Curl_cfilter *cf, 1198 struct Curl_easy *data) 1199{ 1200 CURLcode retcode; 1201 bool done = FALSE; 1202 1203 retcode = mbed_connect_common(cf, data, FALSE, &done); 1204 if(retcode) 1205 return retcode; 1206 1207 DEBUGASSERT(done); 1208 1209 return CURLE_OK; 1210} 1211 1212/* 1213 * return 0 error initializing SSL 1214 * return 1 SSL initialized successfully 1215 */ 1216static int mbedtls_init(void) 1217{ 1218 return Curl_mbedtlsthreadlock_thread_setup(); 1219} 1220 1221static void mbedtls_cleanup(void) 1222{ 1223#ifdef THREADING_SUPPORT 1224 mbedtls_entropy_free(&ts_entropy); 1225#endif /* THREADING_SUPPORT */ 1226 (void)Curl_mbedtlsthreadlock_thread_cleanup(); 1227} 1228 1229static bool mbedtls_data_pending(struct Curl_cfilter *cf, 1230 const struct Curl_easy *data) 1231{ 1232 struct ssl_connect_data *ctx = cf->ctx; 1233 struct mbed_ssl_backend_data *backend; 1234 1235 (void)data; 1236 DEBUGASSERT(ctx && ctx->backend); 1237 backend = (struct mbed_ssl_backend_data *)ctx->backend; 1238 return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0; 1239} 1240 1241static CURLcode mbedtls_sha256sum(const unsigned char *input, 1242 size_t inputlen, 1243 unsigned char *sha256sum, 1244 size_t sha256len UNUSED_PARAM) 1245{ 1246 /* TODO: explain this for different mbedtls 2.x vs 3 version */ 1247 (void)sha256len; 1248#if MBEDTLS_VERSION_NUMBER < 0x02070000 1249 mbedtls_sha256(input, inputlen, sha256sum, 0); 1250#else 1251 /* returns 0 on success, otherwise failure */ 1252#if MBEDTLS_VERSION_NUMBER >= 0x03000000 1253 if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0) 1254#else 1255 if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0) 1256#endif 1257 return CURLE_BAD_FUNCTION_ARGUMENT; 1258#endif 1259 return CURLE_OK; 1260} 1261 1262static void *mbedtls_get_internals(struct ssl_connect_data *connssl, 1263 CURLINFO info UNUSED_PARAM) 1264{ 1265 struct mbed_ssl_backend_data *backend = 1266 (struct mbed_ssl_backend_data *)connssl->backend; 1267 (void)info; 1268 DEBUGASSERT(backend); 1269 return &backend->ssl; 1270} 1271 1272const struct Curl_ssl Curl_ssl_mbedtls = { 1273 { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */ 1274 1275 SSLSUPP_CA_PATH | 1276 SSLSUPP_CAINFO_BLOB | 1277 SSLSUPP_PINNEDPUBKEY | 1278 SSLSUPP_SSL_CTX | 1279 SSLSUPP_HTTPS_PROXY, 1280 1281 sizeof(struct mbed_ssl_backend_data), 1282 1283 mbedtls_init, /* init */ 1284 mbedtls_cleanup, /* cleanup */ 1285 mbedtls_version, /* version */ 1286 Curl_none_check_cxn, /* check_cxn */ 1287 Curl_none_shutdown, /* shutdown */ 1288 mbedtls_data_pending, /* data_pending */ 1289 mbedtls_random, /* random */ 1290 Curl_none_cert_status_request, /* cert_status_request */ 1291 mbedtls_connect, /* connect */ 1292 mbedtls_connect_nonblocking, /* connect_nonblocking */ 1293 Curl_ssl_adjust_pollset, /* adjust_pollset */ 1294 mbedtls_get_internals, /* get_internals */ 1295 mbedtls_close, /* close_one */ 1296 mbedtls_close_all, /* close_all */ 1297 mbedtls_session_free, /* session_free */ 1298 Curl_none_set_engine, /* set_engine */ 1299 Curl_none_set_engine_default, /* set_engine_default */ 1300 Curl_none_engines_list, /* engines_list */ 1301 Curl_none_false_start, /* false_start */ 1302 mbedtls_sha256sum, /* sha256sum */ 1303 NULL, /* associate_connection */ 1304 NULL, /* disassociate_connection */ 1305 NULL, /* free_multi_ssl_backend_data */ 1306 mbed_recv, /* recv decrypted data */ 1307 mbed_send, /* send data to encrypt */ 1308}; 1309 1310#endif /* USE_MBEDTLS */ 1311