1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25/* 26 * Source file for all wolfSSL specific code for the TLS/SSL layer. No code 27 * but vtls.c should ever call or use these functions. 28 * 29 */ 30 31#include "curl_setup.h" 32 33#ifdef USE_WOLFSSL 34 35#define WOLFSSL_OPTIONS_IGNORE_SYS 36#include <wolfssl/version.h> 37#include <wolfssl/options.h> 38 39/* To determine what functions are available we rely on one or both of: 40 - the user's options.h generated by wolfSSL 41 - the symbols detected by curl's configure 42 Since they are markedly different from one another, and one or the other may 43 not be available, we do some checking below to bring things in sync. */ 44 45/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */ 46#ifndef HAVE_ALPN 47#ifdef HAVE_WOLFSSL_USEALPN 48#define HAVE_ALPN 49#endif 50#endif 51 52#include <limits.h> 53 54#include "urldata.h" 55#include "sendf.h" 56#include "inet_pton.h" 57#include "vtls.h" 58#include "vtls_int.h" 59#include "keylog.h" 60#include "parsedate.h" 61#include "connect.h" /* for the connect timeout */ 62#include "select.h" 63#include "strcase.h" 64#include "x509asn1.h" 65#include "curl_printf.h" 66#include "multiif.h" 67 68#include <wolfssl/openssl/ssl.h> 69#include <wolfssl/ssl.h> 70#include <wolfssl/error-ssl.h> 71#include "wolfssl.h" 72 73/* The last #include files should be: */ 74#include "curl_memory.h" 75#include "memdebug.h" 76 77/* KEEP_PEER_CERT is a product of the presence of build time symbol 78 OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is 79 in wolfSSL's settings.h, and the latter two are build time symbols in 80 options.h. */ 81#ifndef KEEP_PEER_CERT 82#if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \ 83 (defined(OPENSSL_EXTRA) && !defined(NO_CERTS)) 84#define KEEP_PEER_CERT 85#endif 86#endif 87 88#if defined(HAVE_WOLFSSL_FULL_BIO) && HAVE_WOLFSSL_FULL_BIO 89#define USE_BIO_CHAIN 90#else 91#undef USE_BIO_CHAIN 92#endif 93 94struct wolfssl_ssl_backend_data { 95 WOLFSSL_CTX *ctx; 96 WOLFSSL *handle; 97 CURLcode io_result; /* result of last BIO cfilter operation */ 98}; 99 100#ifdef OPENSSL_EXTRA 101/* 102 * Availability note: 103 * The TLS 1.3 secret callback (wolfSSL_set_tls13_secret_cb) was added in 104 * WolfSSL 4.4.0, but requires the -DHAVE_SECRET_CALLBACK build option. If that 105 * option is not set, then TLS 1.3 will not be logged. 106 * For TLS 1.2 and before, we use wolfSSL_get_keys(). 107 * SSL_get_client_random and wolfSSL_get_keys require OPENSSL_EXTRA 108 * (--enable-opensslextra or --enable-all). 109 */ 110#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) 111static int 112wolfssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret, 113 int secretSz, void *ctx) 114{ 115 const char *label; 116 unsigned char client_random[SSL3_RANDOM_SIZE]; 117 (void)ctx; 118 119 if(!ssl || !Curl_tls_keylog_enabled()) { 120 return 0; 121 } 122 123 switch(id) { 124 case CLIENT_EARLY_TRAFFIC_SECRET: 125 label = "CLIENT_EARLY_TRAFFIC_SECRET"; 126 break; 127 case CLIENT_HANDSHAKE_TRAFFIC_SECRET: 128 label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"; 129 break; 130 case SERVER_HANDSHAKE_TRAFFIC_SECRET: 131 label = "SERVER_HANDSHAKE_TRAFFIC_SECRET"; 132 break; 133 case CLIENT_TRAFFIC_SECRET: 134 label = "CLIENT_TRAFFIC_SECRET_0"; 135 break; 136 case SERVER_TRAFFIC_SECRET: 137 label = "SERVER_TRAFFIC_SECRET_0"; 138 break; 139 case EARLY_EXPORTER_SECRET: 140 label = "EARLY_EXPORTER_SECRET"; 141 break; 142 case EXPORTER_SECRET: 143 label = "EXPORTER_SECRET"; 144 break; 145 default: 146 return 0; 147 } 148 149 if(SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE) == 0) { 150 /* Should never happen as wolfSSL_KeepArrays() was called before. */ 151 return 0; 152 } 153 154 Curl_tls_keylog_write(label, client_random, secret, secretSz); 155 return 0; 156} 157#endif /* defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) */ 158 159static void 160wolfssl_log_tls12_secret(SSL *ssl) 161{ 162 unsigned char *ms, *sr, *cr; 163 unsigned int msLen, srLen, crLen, i, x = 0; 164 165#if LIBWOLFSSL_VERSION_HEX >= 0x0300d000 /* >= 3.13.0 */ 166 /* wolfSSL_GetVersion is available since 3.13, we use it instead of 167 * SSL_version since the latter relies on OPENSSL_ALL (--enable-opensslall or 168 * --enable-all). Failing to perform this check could result in an unusable 169 * key log line when TLS 1.3 is actually negotiated. */ 170 switch(wolfSSL_GetVersion(ssl)) { 171 case WOLFSSL_SSLV3: 172 case WOLFSSL_TLSV1: 173 case WOLFSSL_TLSV1_1: 174 case WOLFSSL_TLSV1_2: 175 break; 176 default: 177 /* TLS 1.3 does not use this mechanism, the "master secret" returned below 178 * is not directly usable. */ 179 return; 180 } 181#endif 182 183 if(wolfSSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) != 184 SSL_SUCCESS) { 185 return; 186 } 187 188 /* Check for a missing master secret and skip logging. That can happen if 189 * curl rejects the server certificate and aborts the handshake. 190 */ 191 for(i = 0; i < msLen; i++) { 192 x |= ms[i]; 193 } 194 if(x == 0) { 195 return; 196 } 197 198 Curl_tls_keylog_write("CLIENT_RANDOM", cr, ms, msLen); 199} 200#endif /* OPENSSL_EXTRA */ 201 202static int do_file_type(const char *type) 203{ 204 if(!type || !type[0]) 205 return SSL_FILETYPE_PEM; 206 if(strcasecompare(type, "PEM")) 207 return SSL_FILETYPE_PEM; 208 if(strcasecompare(type, "DER")) 209 return SSL_FILETYPE_ASN1; 210 return -1; 211} 212 213#ifdef HAVE_LIBOQS 214struct group_name_map { 215 const word16 group; 216 const char *name; 217}; 218 219static const struct group_name_map gnm[] = { 220 { WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" }, 221 { WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" }, 222 { WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" }, 223 { WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" }, 224 { WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" }, 225 { WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" }, 226 { 0, NULL } 227}; 228#endif 229 230#ifdef USE_BIO_CHAIN 231 232static int wolfssl_bio_cf_create(WOLFSSL_BIO *bio) 233{ 234 wolfSSL_BIO_set_shutdown(bio, 1); 235 wolfSSL_BIO_set_init(bio, 1); 236 wolfSSL_BIO_set_data(bio, NULL); 237 return 1; 238} 239 240static int wolfssl_bio_cf_destroy(WOLFSSL_BIO *bio) 241{ 242 if(!bio) 243 return 0; 244 return 1; 245} 246 247static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr) 248{ 249 struct Curl_cfilter *cf = BIO_get_data(bio); 250 long ret = 1; 251 252 (void)cf; 253 (void)ptr; 254 switch(cmd) { 255 case BIO_CTRL_GET_CLOSE: 256 ret = (long)wolfSSL_BIO_get_shutdown(bio); 257 break; 258 case BIO_CTRL_SET_CLOSE: 259 wolfSSL_BIO_set_shutdown(bio, (int)num); 260 break; 261 case BIO_CTRL_FLUSH: 262 /* we do no delayed writes, but if we ever would, this 263 * needs to trigger it. */ 264 ret = 1; 265 break; 266 case BIO_CTRL_DUP: 267 ret = 1; 268 break; 269#ifdef BIO_CTRL_EOF 270 case BIO_CTRL_EOF: 271 /* EOF has been reached on input? */ 272 return (!cf->next || !cf->next->connected); 273#endif 274 default: 275 ret = 0; 276 break; 277 } 278 return ret; 279} 280 281static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio, 282 const char *buf, int blen) 283{ 284 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); 285 struct ssl_connect_data *connssl = cf->ctx; 286 struct wolfssl_ssl_backend_data *backend = 287 (struct wolfssl_ssl_backend_data *)connssl->backend; 288 struct Curl_easy *data = CF_DATA_CURRENT(cf); 289 ssize_t nwritten; 290 CURLcode result = CURLE_OK; 291 292 DEBUGASSERT(data); 293 nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result); 294 backend->io_result = result; 295 CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d", 296 blen, nwritten, result); 297 wolfSSL_BIO_clear_retry_flags(bio); 298 if(nwritten < 0 && CURLE_AGAIN == result) 299 BIO_set_retry_write(bio); 300 return (int)nwritten; 301} 302 303static int wolfssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen) 304{ 305 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); 306 struct ssl_connect_data *connssl = cf->ctx; 307 struct wolfssl_ssl_backend_data *backend = 308 (struct wolfssl_ssl_backend_data *)connssl->backend; 309 struct Curl_easy *data = CF_DATA_CURRENT(cf); 310 ssize_t nread; 311 CURLcode result = CURLE_OK; 312 313 DEBUGASSERT(data); 314 /* OpenSSL catches this case, so should we. */ 315 if(!buf) 316 return 0; 317 318 nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result); 319 backend->io_result = result; 320 CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %zd, %d", blen, nread, result); 321 wolfSSL_BIO_clear_retry_flags(bio); 322 if(nread < 0 && CURLE_AGAIN == result) 323 BIO_set_retry_read(bio); 324 return (int)nread; 325} 326 327static WOLFSSL_BIO_METHOD *wolfssl_bio_cf_method = NULL; 328 329static void wolfssl_bio_cf_init_methods(void) 330{ 331 wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO"); 332 wolfSSL_BIO_meth_set_write(wolfssl_bio_cf_method, &wolfssl_bio_cf_out_write); 333 wolfSSL_BIO_meth_set_read(wolfssl_bio_cf_method, &wolfssl_bio_cf_in_read); 334 wolfSSL_BIO_meth_set_ctrl(wolfssl_bio_cf_method, &wolfssl_bio_cf_ctrl); 335 wolfSSL_BIO_meth_set_create(wolfssl_bio_cf_method, &wolfssl_bio_cf_create); 336 wolfSSL_BIO_meth_set_destroy(wolfssl_bio_cf_method, &wolfssl_bio_cf_destroy); 337} 338 339static void wolfssl_bio_cf_free_methods(void) 340{ 341 wolfSSL_BIO_meth_free(wolfssl_bio_cf_method); 342} 343 344#else /* USE_BIO_CHAIN */ 345 346#define wolfssl_bio_cf_init_methods() Curl_nop_stmt 347#define wolfssl_bio_cf_free_methods() Curl_nop_stmt 348 349#endif /* !USE_BIO_CHAIN */ 350 351/* 352 * This function loads all the client/CA certificates and CRLs. Setup the TLS 353 * layer and do all necessary magic. 354 */ 355static CURLcode 356wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) 357{ 358 char *ciphers, *curves; 359 struct ssl_connect_data *connssl = cf->ctx; 360 struct wolfssl_ssl_backend_data *backend = 361 (struct wolfssl_ssl_backend_data *)connssl->backend; 362 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 363 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; 364 const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 365 const char * const ssl_cafile = 366 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ 367 (ca_info_blob ? NULL : conn_config->CAfile); 368 const char * const ssl_capath = conn_config->CApath; 369 WOLFSSL_METHOD* req_method = NULL; 370#ifdef HAVE_LIBOQS 371 word16 oqsAlg = 0; 372 size_t idx = 0; 373#endif 374#ifdef HAVE_SNI 375 bool sni = FALSE; 376#define use_sni(x) sni = (x) 377#else 378#define use_sni(x) Curl_nop_stmt 379#endif 380 bool imported_native_ca = false; 381 bool imported_ca_info_blob = false; 382 383 DEBUGASSERT(backend); 384 385 if(connssl->state == ssl_connection_complete) 386 return CURLE_OK; 387 388 if(conn_config->version_max != CURL_SSLVERSION_MAX_NONE) { 389 failf(data, "wolfSSL does not support to set maximum SSL/TLS version"); 390 return CURLE_SSL_CONNECT_ERROR; 391 } 392 393 /* check to see if we've been told to use an explicit SSL/TLS version */ 394 switch(conn_config->version) { 395 case CURL_SSLVERSION_DEFAULT: 396 case CURL_SSLVERSION_TLSv1: 397#if LIBWOLFSSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */ 398 /* minimum protocol version is set later after the CTX object is created */ 399 req_method = SSLv23_client_method(); 400#else 401 infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, " 402 "TLS 1.0 is used exclusively"); 403 req_method = TLSv1_client_method(); 404#endif 405 use_sni(TRUE); 406 break; 407 case CURL_SSLVERSION_TLSv1_0: 408#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS) 409 req_method = TLSv1_client_method(); 410 use_sni(TRUE); 411#else 412 failf(data, "wolfSSL does not support TLS 1.0"); 413 return CURLE_NOT_BUILT_IN; 414#endif 415 break; 416 case CURL_SSLVERSION_TLSv1_1: 417#ifndef NO_OLD_TLS 418 req_method = TLSv1_1_client_method(); 419 use_sni(TRUE); 420#else 421 failf(data, "wolfSSL does not support TLS 1.1"); 422 return CURLE_NOT_BUILT_IN; 423#endif 424 break; 425 case CURL_SSLVERSION_TLSv1_2: 426#ifndef WOLFSSL_NO_TLS12 427 req_method = TLSv1_2_client_method(); 428 use_sni(TRUE); 429#else 430 failf(data, "wolfSSL does not support TLS 1.2"); 431 return CURLE_NOT_BUILT_IN; 432#endif 433 break; 434 case CURL_SSLVERSION_TLSv1_3: 435#ifdef WOLFSSL_TLS13 436 req_method = wolfTLSv1_3_client_method(); 437 use_sni(TRUE); 438 break; 439#else 440 failf(data, "wolfSSL: TLS 1.3 is not yet supported"); 441 return CURLE_SSL_CONNECT_ERROR; 442#endif 443 default: 444 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); 445 return CURLE_SSL_CONNECT_ERROR; 446 } 447 448 if(!req_method) { 449 failf(data, "SSL: couldn't create a method"); 450 return CURLE_OUT_OF_MEMORY; 451 } 452 453 if(backend->ctx) 454 wolfSSL_CTX_free(backend->ctx); 455 backend->ctx = wolfSSL_CTX_new(req_method); 456 457 if(!backend->ctx) { 458 failf(data, "SSL: couldn't create a context"); 459 return CURLE_OUT_OF_MEMORY; 460 } 461 462 switch(conn_config->version) { 463 case CURL_SSLVERSION_DEFAULT: 464 case CURL_SSLVERSION_TLSv1: 465#if LIBWOLFSSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */ 466 /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is 467 * whatever minimum version of TLS was built in and at least TLS 1.0. For 468 * later library versions that could change (eg TLS 1.0 built in but 469 * defaults to TLS 1.1) so we have this short circuit evaluation to find 470 * the minimum supported TLS version. 471 */ 472 if((wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1) != 1) && 473 (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_1) != 1) && 474 (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_2) != 1) 475#ifdef WOLFSSL_TLS13 476 && (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_3) != 1) 477#endif 478 ) { 479 failf(data, "SSL: couldn't set the minimum protocol version"); 480 return CURLE_SSL_CONNECT_ERROR; 481 } 482#endif 483 default: 484 break; 485 } 486 487 ciphers = conn_config->cipher_list; 488 if(ciphers) { 489 if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) { 490 failf(data, "failed setting cipher list: %s", ciphers); 491 return CURLE_SSL_CIPHER; 492 } 493 infof(data, "Cipher selection: %s", ciphers); 494 } 495 496 curves = conn_config->curves; 497 if(curves) { 498 499#ifdef HAVE_LIBOQS 500 for(idx = 0; gnm[idx].name != NULL; idx++) { 501 if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) { 502 oqsAlg = gnm[idx].group; 503 break; 504 } 505 } 506 507 if(oqsAlg == 0) 508#endif 509 { 510 if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) { 511 failf(data, "failed setting curves list: '%s'", curves); 512 return CURLE_SSL_CIPHER; 513 } 514 } 515 } 516 517#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS) 518 /* load native CA certificates */ 519 if(ssl_config->native_ca_store) { 520 if(wolfSSL_CTX_load_system_CA_certs(backend->ctx) != WOLFSSL_SUCCESS) { 521 infof(data, "error importing native CA store, continuing anyway"); 522 } 523 else { 524 imported_native_ca = true; 525 infof(data, "successfully imported native CA store"); 526 } 527 } 528#endif /* !NO_FILESYSTEM */ 529 530 /* load certificate blob */ 531 if(ca_info_blob) { 532 if(wolfSSL_CTX_load_verify_buffer(backend->ctx, ca_info_blob->data, 533 ca_info_blob->len, 534 SSL_FILETYPE_PEM) != SSL_SUCCESS) { 535 if(imported_native_ca) { 536 infof(data, "error importing CA certificate blob, continuing anyway"); 537 } 538 else { 539 failf(data, "error importing CA certificate blob"); 540 return CURLE_SSL_CACERT_BADFILE; 541 } 542 } 543 else { 544 imported_ca_info_blob = true; 545 infof(data, "successfully imported CA certificate blob"); 546 } 547 } 548 549#ifndef NO_FILESYSTEM 550 /* load trusted cacert from file if not blob */ 551 if(ssl_cafile || ssl_capath) { 552 int rc = 553 wolfSSL_CTX_load_verify_locations_ex(backend->ctx, 554 ssl_cafile, 555 ssl_capath, 556 WOLFSSL_LOAD_FLAG_IGNORE_ERR); 557 if(SSL_SUCCESS != rc) { 558 if(conn_config->verifypeer && !imported_ca_info_blob && 559 !imported_native_ca) { 560 /* Fail if we insist on successfully verifying the server. */ 561 failf(data, "error setting certificate verify locations:" 562 " CAfile: %s CApath: %s", 563 ssl_cafile ? ssl_cafile : "none", 564 ssl_capath ? ssl_capath : "none"); 565 return CURLE_SSL_CACERT_BADFILE; 566 } 567 else { 568 /* Just continue with a warning if no strict certificate 569 verification is required. */ 570 infof(data, "error setting certificate verify locations," 571 " continuing anyway:"); 572 } 573 } 574 else { 575 /* Everything is fine. */ 576 infof(data, "successfully set certificate verify locations:"); 577 } 578 infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none"); 579 infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none"); 580 } 581 582 /* Load the client certificate, and private key */ 583 if(ssl_config->primary.clientcert && ssl_config->key) { 584 int file_type = do_file_type(ssl_config->cert_type); 585 586 if(file_type == WOLFSSL_FILETYPE_PEM) { 587 if(wolfSSL_CTX_use_certificate_chain_file(backend->ctx, 588 ssl_config->primary.clientcert) 589 != 1) { 590 failf(data, "unable to use client certificate"); 591 return CURLE_SSL_CONNECT_ERROR; 592 } 593 } 594 else if(file_type == WOLFSSL_FILETYPE_ASN1) { 595 if(wolfSSL_CTX_use_certificate_file(backend->ctx, 596 ssl_config->primary.clientcert, 597 file_type) != 1) { 598 failf(data, "unable to use client certificate"); 599 return CURLE_SSL_CONNECT_ERROR; 600 } 601 } 602 else { 603 failf(data, "unknown cert type"); 604 return CURLE_BAD_FUNCTION_ARGUMENT; 605 } 606 607 file_type = do_file_type(ssl_config->key_type); 608 if(wolfSSL_CTX_use_PrivateKey_file(backend->ctx, ssl_config->key, 609 file_type) != 1) { 610 failf(data, "unable to set private key"); 611 return CURLE_SSL_CONNECT_ERROR; 612 } 613 } 614#endif /* !NO_FILESYSTEM */ 615 616 /* SSL always tries to verify the peer, this only says whether it should 617 * fail to connect if the verification fails, or if it should continue 618 * anyway. In the latter case the result of the verification is checked with 619 * SSL_get_verify_result() below. */ 620 wolfSSL_CTX_set_verify(backend->ctx, 621 conn_config->verifypeer?SSL_VERIFY_PEER: 622 SSL_VERIFY_NONE, NULL); 623 624#ifdef HAVE_SNI 625 if(sni && connssl->peer.sni) { 626 size_t sni_len = strlen(connssl->peer.sni); 627 if((sni_len < USHRT_MAX)) { 628 if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, 629 connssl->peer.sni, 630 (unsigned short)sni_len) != 1) { 631 failf(data, "Failed to set SNI"); 632 return CURLE_SSL_CONNECT_ERROR; 633 } 634 } 635 } 636#endif 637 638 /* give application a chance to interfere with SSL set up. */ 639 if(data->set.ssl.fsslctx) { 640 CURLcode result = (*data->set.ssl.fsslctx)(data, backend->ctx, 641 data->set.ssl.fsslctxp); 642 if(result) { 643 failf(data, "error signaled by ssl ctx callback"); 644 return result; 645 } 646 } 647#ifdef NO_FILESYSTEM 648 else if(conn_config->verifypeer) { 649 failf(data, "SSL: Certificates can't be loaded because wolfSSL was built" 650 " with \"no filesystem\". Either disable peer verification" 651 " (insecure) or if you are building an application with libcurl you" 652 " can load certificates via CURLOPT_SSL_CTX_FUNCTION."); 653 return CURLE_SSL_CONNECT_ERROR; 654 } 655#endif 656 657 /* Let's make an SSL structure */ 658 if(backend->handle) 659 wolfSSL_free(backend->handle); 660 backend->handle = wolfSSL_new(backend->ctx); 661 if(!backend->handle) { 662 failf(data, "SSL: couldn't create a handle"); 663 return CURLE_OUT_OF_MEMORY; 664 } 665 666#ifdef HAVE_LIBOQS 667 if(oqsAlg) { 668 if(wolfSSL_UseKeyShare(backend->handle, oqsAlg) != WOLFSSL_SUCCESS) { 669 failf(data, "unable to use oqs KEM"); 670 } 671 } 672#endif 673 674#ifdef HAVE_ALPN 675 if(connssl->alpn) { 676 struct alpn_proto_buf proto; 677 CURLcode result; 678 679 result = Curl_alpn_to_proto_str(&proto, connssl->alpn); 680 if(result || 681 wolfSSL_UseALPN(backend->handle, (char *)proto.data, proto.len, 682 WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) { 683 failf(data, "SSL: failed setting ALPN protocols"); 684 return CURLE_SSL_CONNECT_ERROR; 685 } 686 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); 687 } 688#endif /* HAVE_ALPN */ 689 690#ifdef OPENSSL_EXTRA 691 if(Curl_tls_keylog_enabled()) { 692 /* Ensure the Client Random is preserved. */ 693 wolfSSL_KeepArrays(backend->handle); 694#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) 695 wolfSSL_set_tls13_secret_cb(backend->handle, 696 wolfssl_tls13_secret_callback, NULL); 697#endif 698 } 699#endif /* OPENSSL_EXTRA */ 700 701#ifdef HAVE_SECURE_RENEGOTIATION 702 if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) { 703 failf(data, "SSL: failed setting secure renegotiation"); 704 return CURLE_SSL_CONNECT_ERROR; 705 } 706#endif /* HAVE_SECURE_RENEGOTIATION */ 707 708 /* Check if there's a cached ID we can/should use here! */ 709 if(ssl_config->primary.sessionid) { 710 void *ssl_sessionid = NULL; 711 712 Curl_ssl_sessionid_lock(data); 713 if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) { 714 /* we got a session id, use it! */ 715 if(!SSL_set_session(backend->handle, ssl_sessionid)) { 716 Curl_ssl_delsessionid(data, ssl_sessionid); 717 infof(data, "Can't use session ID, going on without"); 718 } 719 else 720 infof(data, "SSL reusing session ID"); 721 } 722 Curl_ssl_sessionid_unlock(data); 723 } 724 725#ifdef USE_BIO_CHAIN 726 { 727 WOLFSSL_BIO *bio; 728 729 bio = BIO_new(wolfssl_bio_cf_method); 730 if(!bio) 731 return CURLE_OUT_OF_MEMORY; 732 733 wolfSSL_BIO_set_data(bio, cf); 734 wolfSSL_set_bio(backend->handle, bio, bio); 735 } 736#else /* USE_BIO_CHAIN */ 737 /* pass the raw socket into the SSL layer */ 738 if(!wolfSSL_set_fd(backend->handle, 739 (int)Curl_conn_cf_get_socket(cf, data))) { 740 failf(data, "SSL: SSL_set_fd failed"); 741 return CURLE_SSL_CONNECT_ERROR; 742 } 743#endif /* !USE_BIO_CHAIN */ 744 745 connssl->connecting_state = ssl_connect_2; 746 return CURLE_OK; 747} 748 749 750static CURLcode 751wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) 752{ 753 int ret = -1; 754 struct ssl_connect_data *connssl = cf->ctx; 755 struct wolfssl_ssl_backend_data *backend = 756 (struct wolfssl_ssl_backend_data *)connssl->backend; 757 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 758 const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)? 759 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]: 760 data->set.str[STRING_SSL_PINNEDPUBLICKEY]; 761 762 DEBUGASSERT(backend); 763 764 wolfSSL_ERR_clear_error(); 765 766 /* Enable RFC2818 checks */ 767 if(conn_config->verifyhost) { 768 char *snihost = connssl->peer.sni? 769 connssl->peer.sni : connssl->peer.hostname; 770 if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE) 771 return CURLE_SSL_CONNECT_ERROR; 772 } 773 774 ret = wolfSSL_connect(backend->handle); 775 776#ifdef OPENSSL_EXTRA 777 if(Curl_tls_keylog_enabled()) { 778 /* If key logging is enabled, wait for the handshake to complete and then 779 * proceed with logging secrets (for TLS 1.2 or older). 780 * 781 * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits 782 * for the server response. At that point the master secret is not yet 783 * available, so we must not try to read it. 784 * To log the secret on completion with a handshake failure, detect 785 * completion via the observation that there is nothing to read or write. 786 * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever 787 * changes, the worst case is that no key is logged on error. 788 */ 789 if(ret == SSL_SUCCESS || 790 (!wolfSSL_want_read(backend->handle) && 791 !wolfSSL_want_write(backend->handle))) { 792 wolfssl_log_tls12_secret(backend->handle); 793 /* Client Random and master secrets are no longer needed, erase these. 794 * Ignored while the handshake is still in progress. */ 795 wolfSSL_FreeArrays(backend->handle); 796 } 797 } 798#endif /* OPENSSL_EXTRA */ 799 800 if(ret != 1) { 801 char error_buffer[WOLFSSL_MAX_ERROR_SZ]; 802 int detail = wolfSSL_get_error(backend->handle, ret); 803 804 if(SSL_ERROR_WANT_READ == detail) { 805 connssl->connecting_state = ssl_connect_2_reading; 806 return CURLE_OK; 807 } 808 else if(SSL_ERROR_WANT_WRITE == detail) { 809 connssl->connecting_state = ssl_connect_2_writing; 810 return CURLE_OK; 811 } 812 /* There is no easy way to override only the CN matching. 813 * This will enable the override of both mismatching SubjectAltNames 814 * as also mismatching CN fields */ 815 else if(DOMAIN_NAME_MISMATCH == detail) { 816#if 1 817 failf(data, " subject alt name(s) or common name do not match \"%s\"", 818 connssl->peer.dispname); 819 return CURLE_PEER_FAILED_VERIFICATION; 820#else 821 /* When the wolfssl_check_domain_name() is used and you desire to 822 * continue on a DOMAIN_NAME_MISMATCH, i.e. 'ssl_config.verifyhost 823 * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA 824 * error. The only way to do this is currently to switch the 825 * Wolfssl_check_domain_name() in and out based on the 826 * 'ssl_config.verifyhost' value. */ 827 if(conn_config->verifyhost) { 828 failf(data, 829 " subject alt name(s) or common name do not match \"%s\"\n", 830 connssl->dispname); 831 return CURLE_PEER_FAILED_VERIFICATION; 832 } 833 else { 834 infof(data, 835 " subject alt name(s) and/or common name do not match \"%s\"", 836 connssl->dispname); 837 return CURLE_OK; 838 } 839#endif 840 } 841#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */ 842 else if(ASN_NO_SIGNER_E == detail) { 843 if(conn_config->verifypeer) { 844 failf(data, " CA signer not available for verification"); 845 return CURLE_SSL_CACERT_BADFILE; 846 } 847 else { 848 /* Just continue with a warning if no strict certificate 849 verification is required. */ 850 infof(data, "CA signer not available for verification, " 851 "continuing anyway"); 852 } 853 } 854#endif 855 else if(backend->io_result == CURLE_AGAIN) { 856 return CURLE_OK; 857 } 858 else { 859 failf(data, "SSL_connect failed with error %d: %s", detail, 860 wolfSSL_ERR_error_string(detail, error_buffer)); 861 return CURLE_SSL_CONNECT_ERROR; 862 } 863 } 864 865 if(pinnedpubkey) { 866#ifdef KEEP_PEER_CERT 867 X509 *x509; 868 const char *x509_der; 869 int x509_der_len; 870 struct Curl_X509certificate x509_parsed; 871 struct Curl_asn1Element *pubkey; 872 CURLcode result; 873 874 x509 = wolfSSL_get_peer_certificate(backend->handle); 875 if(!x509) { 876 failf(data, "SSL: failed retrieving server certificate"); 877 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 878 } 879 880 x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len); 881 if(!x509_der) { 882 failf(data, "SSL: failed retrieving ASN.1 server certificate"); 883 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 884 } 885 886 memset(&x509_parsed, 0, sizeof(x509_parsed)); 887 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) 888 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 889 890 pubkey = &x509_parsed.subjectPublicKeyInfo; 891 if(!pubkey->header || pubkey->end <= pubkey->header) { 892 failf(data, "SSL: failed retrieving public key from server certificate"); 893 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 894 } 895 896 result = Curl_pin_peer_pubkey(data, 897 pinnedpubkey, 898 (const unsigned char *)pubkey->header, 899 (size_t)(pubkey->end - pubkey->header)); 900 wolfSSL_FreeX509(x509); 901 if(result) { 902 failf(data, "SSL: public key does not match pinned public key"); 903 return result; 904 } 905#else 906 failf(data, "Library lacks pinning support built-in"); 907 return CURLE_NOT_BUILT_IN; 908#endif 909 } 910 911#ifdef HAVE_ALPN 912 if(connssl->alpn) { 913 int rc; 914 char *protocol = NULL; 915 unsigned short protocol_len = 0; 916 917 rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len); 918 919 if(rc == SSL_SUCCESS) { 920 Curl_alpn_set_negotiated(cf, data, (const unsigned char *)protocol, 921 protocol_len); 922 } 923 else if(rc == SSL_ALPN_NOT_FOUND) 924 Curl_alpn_set_negotiated(cf, data, NULL, 0); 925 else { 926 failf(data, "ALPN, failure getting protocol, error %d", rc); 927 return CURLE_SSL_CONNECT_ERROR; 928 } 929 } 930#endif /* HAVE_ALPN */ 931 932 connssl->connecting_state = ssl_connect_3; 933#if (LIBWOLFSSL_VERSION_HEX >= 0x03009010) 934 infof(data, "SSL connection using %s / %s", 935 wolfSSL_get_version(backend->handle), 936 wolfSSL_get_cipher_name(backend->handle)); 937#else 938 infof(data, "SSL connected"); 939#endif 940 941 return CURLE_OK; 942} 943 944 945static CURLcode 946wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) 947{ 948 CURLcode result = CURLE_OK; 949 struct ssl_connect_data *connssl = cf->ctx; 950 struct wolfssl_ssl_backend_data *backend = 951 (struct wolfssl_ssl_backend_data *)connssl->backend; 952 const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 953 954 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); 955 DEBUGASSERT(backend); 956 957 if(ssl_config->primary.sessionid) { 958 bool incache; 959 bool added = FALSE; 960 void *old_ssl_sessionid = NULL; 961 /* wolfSSL_get1_session allocates memory that has to be freed. */ 962 WOLFSSL_SESSION *our_ssl_sessionid = wolfSSL_get1_session(backend->handle); 963 964 if(our_ssl_sessionid) { 965 Curl_ssl_sessionid_lock(data); 966 incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL)); 967 if(incache) { 968 if(old_ssl_sessionid != our_ssl_sessionid) { 969 infof(data, "old SSL session ID is stale, removing"); 970 Curl_ssl_delsessionid(data, old_ssl_sessionid); 971 incache = FALSE; 972 } 973 } 974 975 if(!incache) { 976 result = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid, 0, NULL); 977 if(result) { 978 Curl_ssl_sessionid_unlock(data); 979 wolfSSL_SESSION_free(our_ssl_sessionid); 980 failf(data, "failed to store ssl session"); 981 return result; 982 } 983 else { 984 added = TRUE; 985 } 986 } 987 Curl_ssl_sessionid_unlock(data); 988 989 if(!added) { 990 /* If the session info wasn't added to the cache, free our copy. */ 991 wolfSSL_SESSION_free(our_ssl_sessionid); 992 } 993 } 994 } 995 996 connssl->connecting_state = ssl_connect_done; 997 998 return result; 999} 1000 1001 1002static ssize_t wolfssl_send(struct Curl_cfilter *cf, 1003 struct Curl_easy *data, 1004 const void *mem, 1005 size_t len, 1006 CURLcode *curlcode) 1007{ 1008 struct ssl_connect_data *connssl = cf->ctx; 1009 struct wolfssl_ssl_backend_data *backend = 1010 (struct wolfssl_ssl_backend_data *)connssl->backend; 1011 char error_buffer[WOLFSSL_MAX_ERROR_SZ]; 1012 int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; 1013 int rc; 1014 1015 DEBUGASSERT(backend); 1016 1017 wolfSSL_ERR_clear_error(); 1018 1019 rc = wolfSSL_write(backend->handle, mem, memlen); 1020 if(rc <= 0) { 1021 int err = wolfSSL_get_error(backend->handle, rc); 1022 1023 switch(err) { 1024 case SSL_ERROR_WANT_READ: 1025 case SSL_ERROR_WANT_WRITE: 1026 /* there's data pending, re-invoke SSL_write() */ 1027 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len); 1028 *curlcode = CURLE_AGAIN; 1029 return -1; 1030 default: 1031 if(backend->io_result == CURLE_AGAIN) { 1032 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len); 1033 *curlcode = CURLE_AGAIN; 1034 return -1; 1035 } 1036 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d, %d", len, rc, err); 1037 failf(data, "SSL write: %s, errno %d", 1038 wolfSSL_ERR_error_string(err, error_buffer), 1039 SOCKERRNO); 1040 *curlcode = CURLE_SEND_ERROR; 1041 return -1; 1042 } 1043 } 1044 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d", len, rc); 1045 return rc; 1046} 1047 1048static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data) 1049{ 1050 struct ssl_connect_data *connssl = cf->ctx; 1051 struct wolfssl_ssl_backend_data *backend = 1052 (struct wolfssl_ssl_backend_data *)connssl->backend; 1053 1054 (void) data; 1055 1056 DEBUGASSERT(backend); 1057 1058 if(backend->handle) { 1059 char buf[32]; 1060 /* Maybe the server has already sent a close notify alert. 1061 Read it to avoid an RST on the TCP connection. */ 1062 (void)wolfSSL_read(backend->handle, buf, (int)sizeof(buf)); 1063 (void)wolfSSL_shutdown(backend->handle); 1064 wolfSSL_free(backend->handle); 1065 backend->handle = NULL; 1066 } 1067 if(backend->ctx) { 1068 wolfSSL_CTX_free(backend->ctx); 1069 backend->ctx = NULL; 1070 } 1071} 1072 1073static ssize_t wolfssl_recv(struct Curl_cfilter *cf, 1074 struct Curl_easy *data, 1075 char *buf, size_t blen, 1076 CURLcode *curlcode) 1077{ 1078 struct ssl_connect_data *connssl = cf->ctx; 1079 struct wolfssl_ssl_backend_data *backend = 1080 (struct wolfssl_ssl_backend_data *)connssl->backend; 1081 char error_buffer[WOLFSSL_MAX_ERROR_SZ]; 1082 int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen; 1083 int nread; 1084 1085 DEBUGASSERT(backend); 1086 1087 wolfSSL_ERR_clear_error(); 1088 *curlcode = CURLE_OK; 1089 1090 nread = wolfSSL_read(backend->handle, buf, buffsize); 1091 1092 if(nread <= 0) { 1093 int err = wolfSSL_get_error(backend->handle, nread); 1094 1095 switch(err) { 1096 case SSL_ERROR_ZERO_RETURN: /* no more data */ 1097 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen); 1098 *curlcode = CURLE_OK; 1099 return 0; 1100 case SSL_ERROR_NONE: 1101 case SSL_ERROR_WANT_READ: 1102 case SSL_ERROR_WANT_WRITE: 1103 /* there's data pending, re-invoke wolfSSL_read() */ 1104 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen); 1105 *curlcode = CURLE_AGAIN; 1106 return -1; 1107 default: 1108 if(backend->io_result == CURLE_AGAIN) { 1109 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen); 1110 *curlcode = CURLE_AGAIN; 1111 return -1; 1112 } 1113 failf(data, "SSL read: %s, errno %d", 1114 wolfSSL_ERR_error_string(err, error_buffer), SOCKERRNO); 1115 *curlcode = CURLE_RECV_ERROR; 1116 return -1; 1117 } 1118 } 1119 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread); 1120 return nread; 1121} 1122 1123 1124static void wolfssl_session_free(void *ptr) 1125{ 1126 wolfSSL_SESSION_free(ptr); 1127} 1128 1129 1130static size_t wolfssl_version(char *buffer, size_t size) 1131{ 1132#if LIBWOLFSSL_VERSION_HEX >= 0x03006000 1133 return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version()); 1134#elif defined(WOLFSSL_VERSION) 1135 return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); 1136#endif 1137} 1138 1139 1140static int wolfssl_init(void) 1141{ 1142 int ret; 1143 1144#ifdef OPENSSL_EXTRA 1145 Curl_tls_keylog_open(); 1146#endif 1147 ret = (wolfSSL_Init() == SSL_SUCCESS); 1148 wolfssl_bio_cf_init_methods(); 1149 return ret; 1150} 1151 1152 1153static void wolfssl_cleanup(void) 1154{ 1155 wolfssl_bio_cf_free_methods(); 1156 wolfSSL_Cleanup(); 1157#ifdef OPENSSL_EXTRA 1158 Curl_tls_keylog_close(); 1159#endif 1160} 1161 1162 1163static bool wolfssl_data_pending(struct Curl_cfilter *cf, 1164 const struct Curl_easy *data) 1165{ 1166 struct ssl_connect_data *ctx = cf->ctx; 1167 struct wolfssl_ssl_backend_data *backend; 1168 1169 (void)data; 1170 DEBUGASSERT(ctx && ctx->backend); 1171 1172 backend = (struct wolfssl_ssl_backend_data *)ctx->backend; 1173 if(backend->handle) /* SSL is in use */ 1174 return (0 != wolfSSL_pending(backend->handle)) ? TRUE : FALSE; 1175 else 1176 return FALSE; 1177} 1178 1179 1180/* 1181 * This function is called to shut down the SSL layer but keep the 1182 * socket open (CCC - Clear Command Channel) 1183 */ 1184static int wolfssl_shutdown(struct Curl_cfilter *cf, 1185 struct Curl_easy *data) 1186{ 1187 struct ssl_connect_data *ctx = cf->ctx; 1188 struct wolfssl_ssl_backend_data *backend; 1189 int retval = 0; 1190 1191 (void)data; 1192 DEBUGASSERT(ctx && ctx->backend); 1193 1194 backend = (struct wolfssl_ssl_backend_data *)ctx->backend; 1195 if(backend->handle) { 1196 wolfSSL_ERR_clear_error(); 1197 wolfSSL_free(backend->handle); 1198 backend->handle = NULL; 1199 } 1200 return retval; 1201} 1202 1203 1204static CURLcode 1205wolfssl_connect_common(struct Curl_cfilter *cf, 1206 struct Curl_easy *data, 1207 bool nonblocking, 1208 bool *done) 1209{ 1210 CURLcode result; 1211 struct ssl_connect_data *connssl = cf->ctx; 1212 curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); 1213 int what; 1214 1215 /* check if the connection has already been established */ 1216 if(ssl_connection_complete == connssl->state) { 1217 *done = TRUE; 1218 return CURLE_OK; 1219 } 1220 1221 if(ssl_connect_1 == connssl->connecting_state) { 1222 /* Find out how much more time we're allowed */ 1223 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); 1224 1225 if(timeout_ms < 0) { 1226 /* no need to continue if time already is up */ 1227 failf(data, "SSL connection timeout"); 1228 return CURLE_OPERATION_TIMEDOUT; 1229 } 1230 1231 result = wolfssl_connect_step1(cf, data); 1232 if(result) 1233 return result; 1234 } 1235 1236 while(ssl_connect_2 == connssl->connecting_state || 1237 ssl_connect_2_reading == connssl->connecting_state || 1238 ssl_connect_2_writing == connssl->connecting_state) { 1239 1240 /* check allowed time left */ 1241 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); 1242 1243 if(timeout_ms < 0) { 1244 /* no need to continue if time already is up */ 1245 failf(data, "SSL connection timeout"); 1246 return CURLE_OPERATION_TIMEDOUT; 1247 } 1248 1249 /* if ssl is expecting something, check if it's available. */ 1250 if(connssl->connecting_state == ssl_connect_2_reading 1251 || connssl->connecting_state == ssl_connect_2_writing) { 1252 1253 curl_socket_t writefd = ssl_connect_2_writing == 1254 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 1255 curl_socket_t readfd = ssl_connect_2_reading == 1256 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 1257 1258 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 1259 nonblocking?0:timeout_ms); 1260 if(what < 0) { 1261 /* fatal error */ 1262 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 1263 return CURLE_SSL_CONNECT_ERROR; 1264 } 1265 else if(0 == what) { 1266 if(nonblocking) { 1267 *done = FALSE; 1268 return CURLE_OK; 1269 } 1270 else { 1271 /* timeout */ 1272 failf(data, "SSL connection timeout"); 1273 return CURLE_OPERATION_TIMEDOUT; 1274 } 1275 } 1276 /* socket is readable or writable */ 1277 } 1278 1279 /* Run transaction, and return to the caller if it failed or if 1280 * this connection is part of a multi handle and this loop would 1281 * execute again. This permits the owner of a multi handle to 1282 * abort a connection attempt before step2 has completed while 1283 * ensuring that a client using select() or epoll() will always 1284 * have a valid fdset to wait on. 1285 */ 1286 result = wolfssl_connect_step2(cf, data); 1287 if(result || (nonblocking && 1288 (ssl_connect_2 == connssl->connecting_state || 1289 ssl_connect_2_reading == connssl->connecting_state || 1290 ssl_connect_2_writing == connssl->connecting_state))) 1291 return result; 1292 } /* repeat step2 until all transactions are done. */ 1293 1294 if(ssl_connect_3 == connssl->connecting_state) { 1295 result = wolfssl_connect_step3(cf, data); 1296 if(result) 1297 return result; 1298 } 1299 1300 if(ssl_connect_done == connssl->connecting_state) { 1301 connssl->state = ssl_connection_complete; 1302 *done = TRUE; 1303 } 1304 else 1305 *done = FALSE; 1306 1307 /* Reset our connect state machine */ 1308 connssl->connecting_state = ssl_connect_1; 1309 1310 return CURLE_OK; 1311} 1312 1313 1314static CURLcode wolfssl_connect_nonblocking(struct Curl_cfilter *cf, 1315 struct Curl_easy *data, 1316 bool *done) 1317{ 1318 return wolfssl_connect_common(cf, data, TRUE, done); 1319} 1320 1321 1322static CURLcode wolfssl_connect(struct Curl_cfilter *cf, 1323 struct Curl_easy *data) 1324{ 1325 CURLcode result; 1326 bool done = FALSE; 1327 1328 result = wolfssl_connect_common(cf, data, FALSE, &done); 1329 if(result) 1330 return result; 1331 1332 DEBUGASSERT(done); 1333 1334 return CURLE_OK; 1335} 1336 1337static CURLcode wolfssl_random(struct Curl_easy *data, 1338 unsigned char *entropy, size_t length) 1339{ 1340 WC_RNG rng; 1341 (void)data; 1342 if(wc_InitRng(&rng)) 1343 return CURLE_FAILED_INIT; 1344 if(length > UINT_MAX) 1345 return CURLE_FAILED_INIT; 1346 if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length)) 1347 return CURLE_FAILED_INIT; 1348 if(wc_FreeRng(&rng)) 1349 return CURLE_FAILED_INIT; 1350 return CURLE_OK; 1351} 1352 1353static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */ 1354 size_t tmplen, 1355 unsigned char *sha256sum /* output */, 1356 size_t unused) 1357{ 1358 wc_Sha256 SHA256pw; 1359 (void)unused; 1360 if(wc_InitSha256(&SHA256pw)) 1361 return CURLE_FAILED_INIT; 1362 wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen); 1363 wc_Sha256Final(&SHA256pw, sha256sum); 1364 return CURLE_OK; 1365} 1366 1367static void *wolfssl_get_internals(struct ssl_connect_data *connssl, 1368 CURLINFO info UNUSED_PARAM) 1369{ 1370 struct wolfssl_ssl_backend_data *backend = 1371 (struct wolfssl_ssl_backend_data *)connssl->backend; 1372 (void)info; 1373 DEBUGASSERT(backend); 1374 return backend->handle; 1375} 1376 1377const struct Curl_ssl Curl_ssl_wolfssl = { 1378 { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */ 1379 1380#ifdef KEEP_PEER_CERT 1381 SSLSUPP_PINNEDPUBKEY | 1382#endif 1383#ifdef USE_BIO_CHAIN 1384 SSLSUPP_HTTPS_PROXY | 1385#endif 1386 SSLSUPP_CA_PATH | 1387 SSLSUPP_CAINFO_BLOB | 1388 SSLSUPP_SSL_CTX, 1389 1390 sizeof(struct wolfssl_ssl_backend_data), 1391 1392 wolfssl_init, /* init */ 1393 wolfssl_cleanup, /* cleanup */ 1394 wolfssl_version, /* version */ 1395 Curl_none_check_cxn, /* check_cxn */ 1396 wolfssl_shutdown, /* shutdown */ 1397 wolfssl_data_pending, /* data_pending */ 1398 wolfssl_random, /* random */ 1399 Curl_none_cert_status_request, /* cert_status_request */ 1400 wolfssl_connect, /* connect */ 1401 wolfssl_connect_nonblocking, /* connect_nonblocking */ 1402 Curl_ssl_adjust_pollset, /* adjust_pollset */ 1403 wolfssl_get_internals, /* get_internals */ 1404 wolfssl_close, /* close_one */ 1405 Curl_none_close_all, /* close_all */ 1406 wolfssl_session_free, /* session_free */ 1407 Curl_none_set_engine, /* set_engine */ 1408 Curl_none_set_engine_default, /* set_engine_default */ 1409 Curl_none_engines_list, /* engines_list */ 1410 Curl_none_false_start, /* false_start */ 1411 wolfssl_sha256sum, /* sha256sum */ 1412 NULL, /* associate_connection */ 1413 NULL, /* disassociate_connection */ 1414 NULL, /* free_multi_ssl_backend_data */ 1415 wolfssl_recv, /* recv decrypted data */ 1416 wolfssl_send, /* send data to encrypt */ 1417}; 1418 1419#endif 1420