wolfssl.c (71254B)
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/options.h> 37 #include <wolfssl/version.h> 38 39 40 #if LIBWOLFSSL_VERSION_HEX < 0x03004006 /* wolfSSL 3.4.6 (2015) */ 41 #error "wolfSSL version should be at least 3.4.6" 42 #endif 43 44 /* To determine what functions are available we rely on one or both of: 45 - the user's options.h generated by wolfSSL 46 - the symbols detected by curl's configure 47 Since they are markedly different from one another, and one or the other may 48 not be available, we do some checking below to bring things in sync. */ 49 50 /* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */ 51 #ifndef HAVE_ALPN 52 #ifdef HAVE_WOLFSSL_USEALPN 53 #define HAVE_ALPN 54 #endif 55 #endif 56 57 #include <limits.h> 58 59 #include "../urldata.h" 60 #include "../sendf.h" 61 #include "../curlx/inet_pton.h" 62 #include "vtls.h" 63 #include "vtls_int.h" 64 #include "vtls_scache.h" 65 #include "keylog.h" 66 #include "../parsedate.h" 67 #include "../connect.h" /* for the connect timeout */ 68 #include "../progress.h" 69 #include "../select.h" 70 #include "../strdup.h" 71 #include "x509asn1.h" 72 #include "../curl_printf.h" 73 #include "../multiif.h" 74 75 #include <wolfssl/ssl.h> 76 #include <wolfssl/error-ssl.h> 77 #include "wolfssl.h" 78 79 /* The last #include files should be: */ 80 #include "../curl_memory.h" 81 #include "../memdebug.h" 82 83 #ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG 84 #define USE_ECH_WOLFSSL 85 #endif 86 87 /* KEEP_PEER_CERT is a product of the presence of build time symbol 88 OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is 89 in wolfSSL's settings.h, and the latter two are build time symbols in 90 options.h. */ 91 #ifndef KEEP_PEER_CERT 92 #if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \ 93 (defined(OPENSSL_EXTRA) && !defined(NO_CERTS)) 94 #define KEEP_PEER_CERT 95 #endif 96 #endif 97 98 #ifdef HAVE_WOLFSSL_BIO_NEW 99 #define USE_BIO_CHAIN 100 #ifdef HAVE_WOLFSSL_BIO_SET_SHUTDOWN 101 #define USE_FULL_BIO 102 #else /* HAVE_WOLFSSL_BIO_SET_SHUTDOWN */ 103 #undef USE_FULL_BIO 104 #endif 105 /* wolfSSL 5.7.4 and older do not have these symbols, but only the 106 * OpenSSL ones. */ 107 #ifndef WOLFSSL_BIO_CTRL_GET_CLOSE 108 #define WOLFSSL_BIO_CTRL_GET_CLOSE BIO_CTRL_GET_CLOSE 109 #define WOLFSSL_BIO_CTRL_SET_CLOSE BIO_CTRL_SET_CLOSE 110 #define WOLFSSL_BIO_CTRL_FLUSH BIO_CTRL_FLUSH 111 #define WOLFSSL_BIO_CTRL_DUP BIO_CTRL_DUP 112 #define wolfSSL_BIO_set_retry_write BIO_set_retry_write 113 #define wolfSSL_BIO_set_retry_read BIO_set_retry_read 114 #endif /* !WOLFSSL_BIO_CTRL_GET_CLOSE */ 115 116 #else /* HAVE_WOLFSSL_BIO_NEW */ 117 #undef USE_BIO_CHAIN 118 #endif 119 120 static CURLcode wssl_connect(struct Curl_cfilter *cf, 121 struct Curl_easy *data, 122 bool *done); 123 124 #ifdef OPENSSL_EXTRA 125 /* 126 * Availability note: 127 * The TLS 1.3 secret callback (wolfSSL_set_tls13_secret_cb) was added in 128 * wolfSSL 4.4.0, but requires the -DHAVE_SECRET_CALLBACK build option. If that 129 * option is not set, then TLS 1.3 will not be logged. 130 * For TLS 1.2 and before, we use wolfSSL_get_keys(). 131 * wolfSSL_get_client_random and wolfSSL_get_keys require OPENSSL_EXTRA 132 * (--enable-opensslextra or --enable-all). 133 */ 134 #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) 135 static int 136 wssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret, 137 int secretSz, void *ctx) 138 { 139 const char *label; 140 unsigned char client_random[SSL3_RANDOM_SIZE]; 141 (void)ctx; 142 143 if(!ssl || !Curl_tls_keylog_enabled()) { 144 return 0; 145 } 146 147 switch(id) { 148 case CLIENT_EARLY_TRAFFIC_SECRET: 149 label = "CLIENT_EARLY_TRAFFIC_SECRET"; 150 break; 151 case CLIENT_HANDSHAKE_TRAFFIC_SECRET: 152 label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"; 153 break; 154 case SERVER_HANDSHAKE_TRAFFIC_SECRET: 155 label = "SERVER_HANDSHAKE_TRAFFIC_SECRET"; 156 break; 157 case CLIENT_TRAFFIC_SECRET: 158 label = "CLIENT_TRAFFIC_SECRET_0"; 159 break; 160 case SERVER_TRAFFIC_SECRET: 161 label = "SERVER_TRAFFIC_SECRET_0"; 162 break; 163 case EARLY_EXPORTER_SECRET: 164 label = "EARLY_EXPORTER_SECRET"; 165 break; 166 case EXPORTER_SECRET: 167 label = "EXPORTER_SECRET"; 168 break; 169 default: 170 return 0; 171 } 172 173 if(wolfSSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE) == 0) { 174 /* Should never happen as wolfSSL_KeepArrays() was called before. */ 175 return 0; 176 } 177 178 Curl_tls_keylog_write(label, client_random, secret, secretSz); 179 return 0; 180 } 181 #endif /* defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) */ 182 183 static void wssl_log_tls12_secret(WOLFSSL *ssl) 184 { 185 unsigned char *ms, *sr, *cr; 186 unsigned int msLen, srLen, crLen, i, x = 0; 187 188 #if LIBWOLFSSL_VERSION_HEX >= 0x0300d000 /* >= 3.13.0 */ 189 /* wolfSSL_GetVersion is available since 3.13, we use it instead of 190 * SSL_version since the latter relies on OPENSSL_ALL (--enable-opensslall or 191 * --enable-all). Failing to perform this check could result in an unusable 192 * key log line when TLS 1.3 is actually negotiated. */ 193 switch(wolfSSL_GetVersion(ssl)) { 194 case WOLFSSL_SSLV3: 195 case WOLFSSL_TLSV1: 196 case WOLFSSL_TLSV1_1: 197 case WOLFSSL_TLSV1_2: 198 break; 199 default: 200 /* TLS 1.3 does not use this mechanism, the "master secret" returned below 201 * is not directly usable. */ 202 return; 203 } 204 #endif 205 206 if(wolfSSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) != 207 WOLFSSL_SUCCESS) { 208 return; 209 } 210 211 /* Check for a missing master secret and skip logging. That can happen if 212 * curl rejects the server certificate and aborts the handshake. 213 */ 214 for(i = 0; i < msLen; i++) { 215 x |= ms[i]; 216 } 217 if(x == 0) { 218 return; 219 } 220 221 Curl_tls_keylog_write("CLIENT_RANDOM", cr, ms, msLen); 222 } 223 #endif /* OPENSSL_EXTRA */ 224 225 static int wssl_do_file_type(const char *type) 226 { 227 if(!type || !type[0]) 228 return WOLFSSL_FILETYPE_PEM; 229 if(curl_strequal(type, "PEM")) 230 return WOLFSSL_FILETYPE_PEM; 231 if(curl_strequal(type, "DER")) 232 return WOLFSSL_FILETYPE_ASN1; 233 return -1; 234 } 235 236 #ifdef WOLFSSL_HAVE_KYBER 237 struct group_name_map { 238 const word16 group; 239 const char *name; 240 }; 241 242 static const struct group_name_map gnm[] = { 243 { WOLFSSL_ML_KEM_512, "ML_KEM_512" }, 244 { WOLFSSL_ML_KEM_768, "ML_KEM_768" }, 245 { WOLFSSL_ML_KEM_1024, "ML_KEM_1024" }, 246 { WOLFSSL_P256_ML_KEM_512, "P256_ML_KEM_512" }, 247 { WOLFSSL_P384_ML_KEM_768, "P384_ML_KEM_768" }, 248 { WOLFSSL_P521_ML_KEM_1024, "P521_ML_KEM_1024" }, 249 { WOLFSSL_P256_ML_KEM_768, "P256_ML_KEM_768" }, 250 { WOLFSSL_P384_ML_KEM_1024, "P384_ML_KEM_1024" }, 251 { WOLFSSL_X25519_ML_KEM_768, "X25519_ML_KEM_768" }, 252 { 0, NULL } 253 }; 254 #endif 255 256 #ifdef USE_BIO_CHAIN 257 258 static int wssl_bio_cf_create(WOLFSSL_BIO *bio) 259 { 260 #ifdef USE_FULL_BIO 261 wolfSSL_BIO_set_shutdown(bio, 1); 262 #endif 263 wolfSSL_BIO_set_data(bio, NULL); 264 return 1; 265 } 266 267 static int wssl_bio_cf_destroy(WOLFSSL_BIO *bio) 268 { 269 if(!bio) 270 return 0; 271 return 1; 272 } 273 274 static long wssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr) 275 { 276 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); 277 long ret = 1; 278 279 (void)cf; 280 (void)ptr; 281 (void)num; 282 switch(cmd) { 283 case WOLFSSL_BIO_CTRL_GET_CLOSE: 284 #ifdef USE_FULL_BIO 285 ret = (long)wolfSSL_BIO_get_shutdown(bio); 286 #else 287 ret = 0; 288 #endif 289 break; 290 case WOLFSSL_BIO_CTRL_SET_CLOSE: 291 #ifdef USE_FULL_BIO 292 wolfSSL_BIO_set_shutdown(bio, (int)num); 293 #endif 294 break; 295 case WOLFSSL_BIO_CTRL_FLUSH: 296 /* we do no delayed writes, but if we ever would, this 297 * needs to trigger it. */ 298 ret = 1; 299 break; 300 case WOLFSSL_BIO_CTRL_DUP: 301 ret = 1; 302 break; 303 #ifdef WOLFSSL_BIO_CTRL_EOF 304 case WOLFSSL_BIO_CTRL_EOF: { 305 /* EOF has been reached on input? */ 306 struct ssl_connect_data *connssl = cf->ctx; 307 return connssl->peer_closed; 308 } 309 #endif 310 default: 311 ret = 0; 312 break; 313 } 314 return ret; 315 } 316 317 static int wssl_bio_cf_out_write(WOLFSSL_BIO *bio, 318 const char *buf, int blen) 319 { 320 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); 321 struct ssl_connect_data *connssl = cf->ctx; 322 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 323 struct Curl_easy *data = CF_DATA_CURRENT(cf); 324 size_t nwritten, skiplen = 0; 325 CURLcode result = CURLE_OK; 326 327 DEBUGASSERT(data); 328 if(wssl->shutting_down && wssl->io_send_blocked_len && 329 (wssl->io_send_blocked_len < blen)) { 330 /* bug in wolfSSL: <https://github.com/wolfSSL/wolfssl/issues/7784> 331 * It adds the close notify message again every time we retry 332 * sending during shutdown. */ 333 CURL_TRC_CF(data, cf, "bio_write, shutdown restrict send of %d" 334 " to %d bytes", blen, wssl->io_send_blocked_len); 335 skiplen = (ssize_t)(blen - wssl->io_send_blocked_len); 336 blen = wssl->io_send_blocked_len; 337 } 338 result = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &nwritten); 339 wssl->io_result = result; 340 CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %d, %zu", 341 blen, result, nwritten); 342 #ifdef USE_FULL_BIO 343 wolfSSL_BIO_clear_retry_flags(bio); 344 #endif 345 if(CURLE_AGAIN == result) { 346 wolfSSL_BIO_set_retry_write(bio); 347 if(wssl->shutting_down && !wssl->io_send_blocked_len) 348 wssl->io_send_blocked_len = blen; 349 } 350 else if(!result && skiplen) 351 nwritten += skiplen; 352 return result ? -1 : (int)nwritten; 353 } 354 355 static int wssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen) 356 { 357 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); 358 struct ssl_connect_data *connssl = cf->ctx; 359 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 360 struct Curl_easy *data = CF_DATA_CURRENT(cf); 361 size_t nread; 362 CURLcode result = CURLE_OK; 363 364 DEBUGASSERT(data); 365 /* OpenSSL catches this case, so should we. */ 366 if(!buf) 367 return 0; 368 369 if((connssl->connecting_state == ssl_connect_2) && 370 !wssl->x509_store_setup) { 371 /* During handshake, init the x509 store before receiving the 372 * server response. This allows sending of ClientHello without delay. */ 373 result = Curl_wssl_setup_x509_store(cf, data, wssl); 374 if(result) { 375 CURL_TRC_CF(data, cf, "Curl_wssl_setup_x509_store() -> %d", result); 376 wssl->io_result = result; 377 return -1; 378 } 379 } 380 381 result = Curl_conn_cf_recv(cf->next, data, buf, blen, &nread); 382 wssl->io_result = result; 383 CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %d, %zu", blen, result, nread); 384 #ifdef USE_FULL_BIO 385 wolfSSL_BIO_clear_retry_flags(bio); 386 #endif 387 if(CURLE_AGAIN == result) 388 wolfSSL_BIO_set_retry_read(bio); 389 else if(nread == 0) 390 connssl->peer_closed = TRUE; 391 return result ? -1 : (int)nread; 392 } 393 394 static WOLFSSL_BIO_METHOD *wssl_bio_cf_method = NULL; 395 396 static void wssl_bio_cf_init_methods(void) 397 { 398 wssl_bio_cf_method = wolfSSL_BIO_meth_new(WOLFSSL_BIO_MEMORY, 399 "wolfSSL CF BIO"); 400 wolfSSL_BIO_meth_set_write(wssl_bio_cf_method, &wssl_bio_cf_out_write); 401 wolfSSL_BIO_meth_set_read(wssl_bio_cf_method, &wssl_bio_cf_in_read); 402 wolfSSL_BIO_meth_set_ctrl(wssl_bio_cf_method, &wssl_bio_cf_ctrl); 403 wolfSSL_BIO_meth_set_create(wssl_bio_cf_method, &wssl_bio_cf_create); 404 wolfSSL_BIO_meth_set_destroy(wssl_bio_cf_method, &wssl_bio_cf_destroy); 405 } 406 407 static void wssl_bio_cf_free_methods(void) 408 { 409 wolfSSL_BIO_meth_free(wssl_bio_cf_method); 410 } 411 412 #else /* USE_BIO_CHAIN */ 413 414 #define wssl_bio_cf_init_methods() Curl_nop_stmt 415 #define wssl_bio_cf_free_methods() Curl_nop_stmt 416 417 #endif /* !USE_BIO_CHAIN */ 418 419 CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, 420 struct Curl_easy *data, 421 const char *ssl_peer_key, 422 WOLFSSL_SESSION *session, 423 int ietf_tls_id, 424 const char *alpn, 425 unsigned char *quic_tp, 426 size_t quic_tp_len) 427 { 428 CURLcode result = CURLE_OK; 429 struct Curl_ssl_session *sc_session = NULL; 430 unsigned char *sdata = NULL, *qtp_clone = NULL; 431 unsigned int sdata_len; 432 unsigned int earlydata_max = 0; 433 434 if(!session) 435 goto out; 436 437 sdata_len = wolfSSL_i2d_SSL_SESSION(session, NULL); 438 if(sdata_len <= 0) { 439 CURL_TRC_CF(data, cf, "fail to assess session length: %u", sdata_len); 440 result = CURLE_FAILED_INIT; 441 goto out; 442 } 443 sdata = calloc(1, sdata_len); 444 if(!sdata) { 445 failf(data, "unable to allocate session buffer of %u bytes", sdata_len); 446 result = CURLE_OUT_OF_MEMORY; 447 goto out; 448 } 449 sdata_len = wolfSSL_i2d_SSL_SESSION(session, &sdata); 450 if(sdata_len <= 0) { 451 CURL_TRC_CF(data, cf, "fail to serialize session: %u", sdata_len); 452 result = CURLE_FAILED_INIT; 453 goto out; 454 } 455 if(quic_tp && quic_tp_len) { 456 qtp_clone = Curl_memdup0((char *)quic_tp, quic_tp_len); 457 if(!qtp_clone) { 458 free(sdata); 459 return CURLE_OUT_OF_MEMORY; 460 } 461 } 462 #ifdef WOLFSSL_EARLY_DATA 463 earlydata_max = wolfSSL_SESSION_get_max_early_data(session); 464 #endif 465 466 result = Curl_ssl_session_create2(sdata, sdata_len, 467 ietf_tls_id, alpn, 468 (curl_off_t)time(NULL) + 469 wolfSSL_SESSION_get_timeout(session), 470 earlydata_max, qtp_clone, quic_tp_len, 471 &sc_session); 472 sdata = NULL; /* took ownership of sdata */ 473 if(!result) { 474 result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session); 475 /* took ownership of `sc_session` */ 476 } 477 478 out: 479 free(sdata); 480 return result; 481 } 482 483 static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session) 484 { 485 struct Curl_cfilter *cf; 486 487 cf = (struct Curl_cfilter*)wolfSSL_get_app_data(ssl); 488 DEBUGASSERT(cf != NULL); 489 if(cf && session) { 490 struct ssl_connect_data *connssl = cf->ctx; 491 struct Curl_easy *data = CF_DATA_CURRENT(cf); 492 DEBUGASSERT(connssl); 493 DEBUGASSERT(data); 494 if(connssl && data) { 495 (void)Curl_wssl_cache_session(cf, data, connssl->peer.scache_key, 496 session, wolfSSL_version(ssl), 497 connssl->negotiated.alpn, NULL, 0); 498 } 499 } 500 return 0; 501 } 502 503 static CURLcode wssl_on_session_reuse(struct Curl_cfilter *cf, 504 struct Curl_easy *data, 505 struct alpn_spec *alpns, 506 struct Curl_ssl_session *scs, 507 bool *do_early_data) 508 { 509 struct ssl_connect_data *connssl = cf->ctx; 510 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 511 CURLcode result = CURLE_OK; 512 513 *do_early_data = FALSE; 514 #ifdef WOLFSSL_EARLY_DATA 515 connssl->earlydata_max = wolfSSL_SESSION_get_max_early_data( 516 wolfSSL_get_session(wssl->ssl)); 517 #else 518 (void)wssl; 519 connssl->earlydata_max = 0; 520 #endif 521 522 if(!connssl->earlydata_max) { 523 /* Seems to be no WolfSSL way to signal no EarlyData in session */ 524 CURL_TRC_CF(data, cf, "SSL session does not allow earlydata"); 525 } 526 else if(!Curl_alpn_contains_proto(alpns, scs->alpn)) { 527 CURL_TRC_CF(data, cf, "SSL session has different ALPN, no early data"); 528 } 529 else { 530 infof(data, "SSL session allows %zu bytes of early data, " 531 "reusing ALPN '%s'", connssl->earlydata_max, scs->alpn); 532 connssl->earlydata_state = ssl_earlydata_await; 533 connssl->state = ssl_connection_deferred; 534 result = Curl_alpn_set_negotiated(cf, data, connssl, 535 (const unsigned char *)scs->alpn, 536 scs->alpn ? strlen(scs->alpn) : 0); 537 *do_early_data = !result; 538 } 539 return result; 540 } 541 542 static CURLcode 543 wssl_setup_session(struct Curl_cfilter *cf, 544 struct Curl_easy *data, 545 struct wssl_ctx *wss, 546 struct alpn_spec *alpns, 547 const char *ssl_peer_key, 548 Curl_wssl_init_session_reuse_cb *sess_reuse_cb) 549 { 550 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 551 struct Curl_ssl_session *scs = NULL; 552 CURLcode result; 553 554 result = Curl_ssl_scache_take(cf, data, ssl_peer_key, &scs); 555 if(!result && scs && scs->sdata && scs->sdata_len && 556 (!scs->alpn || Curl_alpn_contains_proto(alpns, scs->alpn))) { 557 WOLFSSL_SESSION *session; 558 /* wolfSSL changes the passed pointer for whatever reasons, yikes */ 559 const unsigned char *sdata = scs->sdata; 560 session = wolfSSL_d2i_SSL_SESSION(NULL, &sdata, (long)scs->sdata_len); 561 if(session) { 562 int ret = wolfSSL_set_session(wss->ssl, session); 563 if(ret != WOLFSSL_SUCCESS) { 564 Curl_ssl_session_destroy(scs); 565 scs = NULL; 566 infof(data, "cached session not accepted (%d), " 567 "removing from cache", ret); 568 } 569 else { 570 infof(data, "SSL reusing session with ALPN '%s'", 571 scs->alpn ? scs->alpn : "-"); 572 if(ssl_config->earlydata && 573 !cf->conn->connect_only && 574 !strcmp("TLSv1.3", wolfSSL_get_version(wss->ssl))) { 575 bool do_early_data = FALSE; 576 if(sess_reuse_cb) { 577 result = sess_reuse_cb(cf, data, alpns, scs, &do_early_data); 578 if(result) 579 goto out; 580 } 581 #ifdef WOLFSSL_EARLY_DATA 582 if(do_early_data) { 583 unsigned int edmax = (scs->earlydata_max < UINT_MAX) ? 584 (unsigned int)scs->earlydata_max : UINT_MAX; 585 /* We only try the ALPN protocol the session used before, 586 * otherwise we might send early data for the wrong protocol */ 587 Curl_alpn_restrict_to(alpns, scs->alpn); 588 wolfSSL_set_max_early_data(wss->ssl, edmax); 589 } 590 #else 591 /* Should never enable when not supported */ 592 DEBUGASSERT(!do_early_data); 593 #endif 594 } 595 } 596 wolfSSL_SESSION_free(session); 597 } 598 else { 599 failf(data, "could not decode previous session"); 600 } 601 } 602 out: 603 Curl_ssl_scache_return(cf, data, ssl_peer_key, scs); 604 return result; 605 } 606 607 static CURLcode wssl_populate_x509_store(struct Curl_cfilter *cf, 608 struct Curl_easy *data, 609 WOLFSSL_X509_STORE *store, 610 struct wssl_ctx *wssl) 611 { 612 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 613 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; 614 const char * const ssl_cafile = 615 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ 616 (ca_info_blob ? NULL : conn_config->CAfile); 617 const char * const ssl_capath = conn_config->CApath; 618 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 619 bool imported_native_ca = FALSE; 620 bool imported_ca_info_blob = FALSE; 621 622 /* We do not want to do this again, no matter the outcome */ 623 wssl->x509_store_setup = TRUE; 624 625 #ifndef NO_FILESYSTEM 626 /* load native CA certificates */ 627 if(ssl_config->native_ca_store) { 628 #ifdef WOLFSSL_SYS_CA_CERTS 629 if(wolfSSL_CTX_load_system_CA_certs(wssl->ssl_ctx) != WOLFSSL_SUCCESS) { 630 infof(data, "error importing native CA store, continuing anyway"); 631 } 632 else { 633 imported_native_ca = TRUE; 634 infof(data, "successfully imported native CA store"); 635 } 636 #else 637 infof(data, "ignoring native CA option because wolfSSL was built without " 638 "native CA support"); 639 #endif 640 } 641 #endif /* !NO_FILESYSTEM */ 642 643 /* load certificate blob */ 644 if(ca_info_blob) { 645 if(wolfSSL_CTX_load_verify_buffer(wssl->ssl_ctx, ca_info_blob->data, 646 (long)ca_info_blob->len, 647 WOLFSSL_FILETYPE_PEM) != 648 WOLFSSL_SUCCESS) { 649 failf(data, "error importing CA certificate blob"); 650 return CURLE_SSL_CACERT_BADFILE; 651 } 652 else { 653 imported_ca_info_blob = TRUE; 654 infof(data, "successfully imported CA certificate blob"); 655 } 656 } 657 658 #ifndef NO_FILESYSTEM 659 /* load trusted cacert from file if not blob */ 660 661 CURL_TRC_CF(data, cf, "wssl_populate_x509_store, path=%s, blob=%d", 662 ssl_cafile ? ssl_cafile : "none", !!ca_info_blob); 663 if(!store) 664 return CURLE_OUT_OF_MEMORY; 665 666 if(ssl_cafile || ssl_capath) { 667 int rc = 668 wolfSSL_CTX_load_verify_locations_ex(wssl->ssl_ctx, 669 ssl_cafile, 670 ssl_capath, 671 WOLFSSL_LOAD_FLAG_IGNORE_ERR); 672 if(WOLFSSL_SUCCESS != rc) { 673 if(conn_config->verifypeer && 674 !imported_native_ca && !imported_ca_info_blob) { 675 /* Fail if we insist on successfully verifying the server. */ 676 failf(data, "error setting certificate verify locations:" 677 " CAfile: %s CApath: %s", 678 ssl_cafile ? ssl_cafile : "none", 679 ssl_capath ? ssl_capath : "none"); 680 return CURLE_SSL_CACERT_BADFILE; 681 } 682 else { 683 /* Just continue with a warning if no strict certificate 684 verification is required. */ 685 infof(data, "error setting certificate verify locations," 686 " continuing anyway:"); 687 } 688 } 689 else { 690 /* Everything is fine. */ 691 infof(data, "successfully set certificate verify locations:"); 692 } 693 infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none"); 694 infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none"); 695 } 696 #endif 697 (void)store; 698 return CURLE_OK; 699 } 700 701 /* key to use at `multi->proto_hash` */ 702 #define MPROTO_WSSL_X509_KEY "tls:wssl:x509:share" 703 704 struct wssl_x509_share { 705 char *CAfile; /* CAfile path used to generate X509 store */ 706 WOLFSSL_X509_STORE *store; /* cached X509 store or NULL if none */ 707 struct curltime time; /* when the cached store was created */ 708 }; 709 710 static void wssl_x509_share_free(void *key, size_t key_len, void *p) 711 { 712 struct wssl_x509_share *share = p; 713 DEBUGASSERT(key_len == (sizeof(MPROTO_WSSL_X509_KEY)-1)); 714 DEBUGASSERT(!memcmp(MPROTO_WSSL_X509_KEY, key, key_len)); 715 (void)key; 716 (void)key_len; 717 if(share->store) { 718 wolfSSL_X509_STORE_free(share->store); 719 } 720 free(share->CAfile); 721 free(share); 722 } 723 724 static bool 725 wssl_cached_x509_store_expired(const struct Curl_easy *data, 726 const struct wssl_x509_share *mb) 727 { 728 const struct ssl_general_config *cfg = &data->set.general_ssl; 729 struct curltime now = curlx_now(); 730 timediff_t elapsed_ms = curlx_timediff(now, mb->time); 731 timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; 732 733 if(timeout_ms < 0) 734 return FALSE; 735 736 return elapsed_ms >= timeout_ms; 737 } 738 739 static bool 740 wssl_cached_x509_store_different(struct Curl_cfilter *cf, 741 const struct wssl_x509_share *mb) 742 { 743 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 744 if(!mb->CAfile || !conn_config->CAfile) 745 return mb->CAfile != conn_config->CAfile; 746 747 return strcmp(mb->CAfile, conn_config->CAfile); 748 } 749 750 static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf, 751 const struct Curl_easy *data) 752 { 753 struct Curl_multi *multi = data->multi; 754 struct wssl_x509_share *share; 755 WOLFSSL_X509_STORE *store = NULL; 756 757 DEBUGASSERT(multi); 758 share = multi ? Curl_hash_pick(&multi->proto_hash, 759 CURL_UNCONST(MPROTO_WSSL_X509_KEY), 760 sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL; 761 if(share && share->store && 762 !wssl_cached_x509_store_expired(data, share) && 763 !wssl_cached_x509_store_different(cf, share)) { 764 store = share->store; 765 } 766 767 return store; 768 } 769 770 static void wssl_set_cached_x509_store(struct Curl_cfilter *cf, 771 const struct Curl_easy *data, 772 WOLFSSL_X509_STORE *store) 773 { 774 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 775 struct Curl_multi *multi = data->multi; 776 struct wssl_x509_share *share; 777 778 DEBUGASSERT(multi); 779 if(!multi) 780 return; 781 share = Curl_hash_pick(&multi->proto_hash, 782 CURL_UNCONST(MPROTO_WSSL_X509_KEY), 783 sizeof(MPROTO_WSSL_X509_KEY)-1); 784 785 if(!share) { 786 share = calloc(1, sizeof(*share)); 787 if(!share) 788 return; 789 if(!Curl_hash_add2(&multi->proto_hash, 790 CURL_UNCONST(MPROTO_WSSL_X509_KEY), 791 sizeof(MPROTO_WSSL_X509_KEY)-1, 792 share, wssl_x509_share_free)) { 793 free(share); 794 return; 795 } 796 } 797 798 if(wolfSSL_X509_STORE_up_ref(store)) { 799 char *CAfile = NULL; 800 801 if(conn_config->CAfile) { 802 CAfile = strdup(conn_config->CAfile); 803 if(!CAfile) { 804 wolfSSL_X509_STORE_free(store); 805 return; 806 } 807 } 808 809 if(share->store) { 810 wolfSSL_X509_STORE_free(share->store); 811 free(share->CAfile); 812 } 813 814 share->time = curlx_now(); 815 share->store = store; 816 share->CAfile = CAfile; 817 } 818 } 819 820 CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, 821 struct Curl_easy *data, 822 struct wssl_ctx *wssl) 823 { 824 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 825 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 826 CURLcode result = CURLE_OK; 827 WOLFSSL_X509_STORE *cached_store; 828 bool cache_criteria_met; 829 830 /* Consider the X509 store cacheable if it comes exclusively from a CAfile, 831 or no source is provided and we are falling back to wolfSSL's built-in 832 default. */ 833 cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) && 834 conn_config->verifypeer && 835 !conn_config->CApath && 836 !conn_config->ca_info_blob && 837 !ssl_config->primary.CRLfile && 838 !ssl_config->native_ca_store; 839 840 cached_store = cache_criteria_met ? wssl_get_cached_x509_store(cf, data) 841 : NULL; 842 if(cached_store && 843 wolfSSL_CTX_get_cert_store(wssl->ssl_ctx) == cached_store) { 844 /* The cached store is already in use, do nothing. */ 845 } 846 else if(cached_store && wolfSSL_X509_STORE_up_ref(cached_store)) { 847 wolfSSL_CTX_set_cert_store(wssl->ssl_ctx, cached_store); 848 } 849 else if(cache_criteria_met) { 850 /* wolfSSL's initial store in CTX is not shareable by default. 851 * Make a new one, suitable for adding to the cache. See #14278 */ 852 WOLFSSL_X509_STORE *store = wolfSSL_X509_STORE_new(); 853 if(!store) { 854 failf(data, "SSL: could not create a X509 store"); 855 return CURLE_OUT_OF_MEMORY; 856 } 857 wolfSSL_CTX_set_cert_store(wssl->ssl_ctx, store); 858 859 result = wssl_populate_x509_store(cf, data, store, wssl); 860 if(!result) { 861 wssl_set_cached_x509_store(cf, data, store); 862 } 863 } 864 else { 865 /* We never share the CTX's store, use it. */ 866 WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ssl_ctx); 867 result = wssl_populate_x509_store(cf, data, store, wssl); 868 } 869 870 return result; 871 } 872 873 #ifdef WOLFSSL_TLS13 874 static CURLcode 875 wssl_add_default_ciphers(bool tls13, struct dynbuf *buf) 876 { 877 int i; 878 char *str; 879 880 for(i = 0; (str = wolfSSL_get_cipher_list(i)) != NULL; i++) { 881 size_t n; 882 if((strncmp(str, "TLS13", 5) == 0) != tls13) 883 continue; 884 885 /* if there already is data in the string, add colon separator */ 886 if(curlx_dyn_len(buf)) { 887 CURLcode result = curlx_dyn_addn(buf, ":", 1); 888 if(result) 889 return result; 890 } 891 892 n = strlen(str); 893 if(curlx_dyn_addn(buf, str, n)) 894 return CURLE_OUT_OF_MEMORY; 895 } 896 897 return CURLE_OK; 898 } 899 #endif 900 901 /* 4.2.0 (2019) */ 902 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 || !defined(OPENSSL_EXTRA) 903 static int 904 wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) 905 { 906 int res; 907 switch(version) { 908 default: 909 case TLS1_VERSION: 910 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1); 911 if(res == WOLFSSL_SUCCESS) 912 return res; 913 FALLTHROUGH(); 914 case TLS1_1_VERSION: 915 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_1); 916 if(res == WOLFSSL_SUCCESS) 917 return res; 918 FALLTHROUGH(); 919 case TLS1_2_VERSION: 920 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_2); 921 #ifdef WOLFSSL_TLS13 922 if(res == WOLFSSL_SUCCESS) 923 return res; 924 FALLTHROUGH(); 925 case TLS1_3_VERSION: 926 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_3); 927 #endif 928 } 929 return res; 930 } 931 static int 932 wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int version) 933 { 934 (void) ctx, (void) version; 935 return WOLFSSL_NOT_IMPLEMENTED; 936 } 937 #define wolfSSL_CTX_set_min_proto_version wssl_legacy_CTX_set_min_proto_version 938 #define wolfSSL_CTX_set_max_proto_version wssl_legacy_CTX_set_max_proto_version 939 #endif 940 941 #define QUIC_CIPHERS \ 942 "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \ 943 "POLY1305_SHA256:TLS_AES_128_CCM_SHA256" 944 #define QUIC_GROUPS "P-256:P-384:P-521" 945 946 CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, 947 struct Curl_cfilter *cf, 948 struct Curl_easy *data, 949 struct ssl_peer *peer, 950 const struct alpn_spec *alpns_requested, 951 Curl_wssl_ctx_setup_cb *cb_setup, 952 void *cb_user_data, 953 void *ssl_user_data, 954 Curl_wssl_init_session_reuse_cb *sess_reuse_cb) 955 { 956 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 957 struct ssl_primary_config *conn_config; 958 WOLFSSL_METHOD* req_method = NULL; 959 struct alpn_spec alpns; 960 int res; 961 char *curves; 962 #ifdef WOLFSSL_HAVE_KYBER 963 word16 pqkem = 0; 964 size_t idx = 0; 965 #endif 966 CURLcode result = CURLE_FAILED_INIT; 967 unsigned char transport; 968 969 DEBUGASSERT(!wctx->ssl_ctx); 970 DEBUGASSERT(!wctx->ssl); 971 conn_config = Curl_ssl_cf_get_primary_config(cf); 972 if(!conn_config) { 973 result = CURLE_FAILED_INIT; 974 goto out; 975 } 976 Curl_alpn_copy(&alpns, alpns_requested); 977 DEBUGASSERT(cf->next); 978 transport = Curl_conn_cf_get_transport(cf->next, data); 979 980 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 /* 4.2.0 (2019) */ 981 req_method = wolfSSLv23_client_method(); 982 #else 983 req_method = wolfTLS_client_method(); 984 #endif 985 if(!req_method) { 986 failf(data, "wolfSSL: could not create a client method"); 987 result = CURLE_OUT_OF_MEMORY; 988 goto out; 989 } 990 991 if(wctx->ssl_ctx) 992 wolfSSL_CTX_free(wctx->ssl_ctx); 993 994 wctx->ssl_ctx = wolfSSL_CTX_new(req_method); 995 if(!wctx->ssl_ctx) { 996 failf(data, "wolfSSL: could not create a context"); 997 result = CURLE_OUT_OF_MEMORY; 998 goto out; 999 } 1000 1001 switch(conn_config->version) { 1002 case CURL_SSLVERSION_DEFAULT: 1003 case CURL_SSLVERSION_TLSv1: 1004 case CURL_SSLVERSION_TLSv1_0: 1005 res = wolfSSL_CTX_set_min_proto_version(wctx->ssl_ctx, TLS1_VERSION); 1006 break; 1007 case CURL_SSLVERSION_TLSv1_1: 1008 res = wolfSSL_CTX_set_min_proto_version(wctx->ssl_ctx, TLS1_1_VERSION); 1009 break; 1010 case CURL_SSLVERSION_TLSv1_2: 1011 res = wolfSSL_CTX_set_min_proto_version(wctx->ssl_ctx, TLS1_2_VERSION); 1012 break; 1013 #ifdef WOLFSSL_TLS13 1014 case CURL_SSLVERSION_TLSv1_3: 1015 res = wolfSSL_CTX_set_min_proto_version(wctx->ssl_ctx, TLS1_3_VERSION); 1016 break; 1017 #endif 1018 default: 1019 failf(data, "wolfSSL: unsupported minimum TLS version value"); 1020 result = CURLE_SSL_CONNECT_ERROR; 1021 goto out; 1022 } 1023 if(res != WOLFSSL_SUCCESS) { 1024 failf(data, "wolfSSL: failed set the minimum TLS version"); 1025 result = CURLE_SSL_CONNECT_ERROR; 1026 goto out; 1027 } 1028 1029 switch(conn_config->version_max) { 1030 #ifdef WOLFSSL_TLS13 1031 case CURL_SSLVERSION_MAX_TLSv1_3: 1032 res = wolfSSL_CTX_set_max_proto_version(wctx->ssl_ctx, TLS1_3_VERSION); 1033 break; 1034 #endif 1035 case CURL_SSLVERSION_MAX_TLSv1_2: 1036 res = wolfSSL_CTX_set_max_proto_version(wctx->ssl_ctx, TLS1_2_VERSION); 1037 break; 1038 case CURL_SSLVERSION_MAX_TLSv1_1: 1039 res = wolfSSL_CTX_set_max_proto_version(wctx->ssl_ctx, TLS1_1_VERSION); 1040 break; 1041 case CURL_SSLVERSION_MAX_TLSv1_0: 1042 res = wolfSSL_CTX_set_max_proto_version(wctx->ssl_ctx, TLS1_VERSION); 1043 break; 1044 case CURL_SSLVERSION_MAX_DEFAULT: 1045 case CURL_SSLVERSION_MAX_NONE: 1046 res = WOLFSSL_SUCCESS; 1047 break; 1048 default: 1049 failf(data, "wolfSSL: unsupported maximum TLS version value"); 1050 result = CURLE_SSL_CONNECT_ERROR; 1051 goto out; 1052 } 1053 if(res != WOLFSSL_SUCCESS) { 1054 failf(data, "wolfSSL: failed set the maximum TLS version"); 1055 result = CURLE_SSL_CONNECT_ERROR; 1056 goto out; 1057 } 1058 1059 #ifndef WOLFSSL_TLS13 1060 { 1061 char *ciphers = conn_config->cipher_list; 1062 if(ciphers) { 1063 if(!SSL_CTX_set_cipher_list(wctx->ssl_ctx, ciphers)) { 1064 failf(data, "failed setting cipher list: %s", ciphers); 1065 result = CURLE_SSL_CIPHER; 1066 goto out; 1067 } 1068 infof(data, "Cipher selection: %s", ciphers); 1069 } 1070 } 1071 #else 1072 #define MAX_CIPHER_LEN 4096 1073 if(conn_config->cipher_list || conn_config->cipher_list13) { 1074 const char *ciphers12 = conn_config->cipher_list; 1075 const char *ciphers13 = conn_config->cipher_list13; 1076 struct dynbuf c; 1077 curlx_dyn_init(&c, MAX_CIPHER_LEN); 1078 1079 if(ciphers13) 1080 result = curlx_dyn_add(&c, ciphers13); 1081 else 1082 result = wssl_add_default_ciphers(TRUE, &c); 1083 1084 if(!result) { 1085 if(ciphers12) { 1086 if(curlx_dyn_len(&c)) 1087 result = curlx_dyn_addn(&c, ":", 1); 1088 if(!result) 1089 result = curlx_dyn_add(&c, ciphers12); 1090 } 1091 else 1092 result = wssl_add_default_ciphers(FALSE, &c); 1093 } 1094 if(result) 1095 goto out; 1096 1097 if(!wolfSSL_CTX_set_cipher_list(wctx->ssl_ctx, curlx_dyn_ptr(&c))) { 1098 failf(data, "failed setting cipher list: %s", curlx_dyn_ptr(&c)); 1099 curlx_dyn_free(&c); 1100 result = CURLE_SSL_CIPHER; 1101 goto out; 1102 } 1103 infof(data, "Cipher selection: %s", curlx_dyn_ptr(&c)); 1104 curlx_dyn_free(&c); 1105 } 1106 #endif 1107 1108 curves = conn_config->curves; 1109 if(!curves && (transport == TRNSPRT_QUIC)) 1110 curves = (char *)CURL_UNCONST(QUIC_GROUPS); 1111 1112 if(curves) { 1113 #ifdef WOLFSSL_HAVE_KYBER 1114 for(idx = 0; gnm[idx].name != NULL; idx++) { 1115 if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) { 1116 pqkem = gnm[idx].group; 1117 break; 1118 } 1119 } 1120 1121 if(pqkem == 0) 1122 #endif 1123 { 1124 if(!wolfSSL_CTX_set1_curves_list(wctx->ssl_ctx, curves)) { 1125 failf(data, "failed setting curves list: '%s'", curves); 1126 result = CURLE_SSL_CIPHER; 1127 goto out; 1128 } 1129 } 1130 } 1131 1132 /* Load the client certificate, and private key */ 1133 #ifndef NO_FILESYSTEM 1134 if(ssl_config->primary.cert_blob || ssl_config->primary.clientcert) { 1135 const char *cert_file = ssl_config->primary.clientcert; 1136 const char *key_file = ssl_config->key; 1137 const struct curl_blob *cert_blob = ssl_config->primary.cert_blob; 1138 const struct curl_blob *key_blob = ssl_config->key_blob; 1139 int file_type = wssl_do_file_type(ssl_config->cert_type); 1140 int rc; 1141 1142 switch(file_type) { 1143 case WOLFSSL_FILETYPE_PEM: 1144 rc = cert_blob ? 1145 wolfSSL_CTX_use_certificate_chain_buffer(wctx->ssl_ctx, 1146 cert_blob->data, 1147 (long)cert_blob->len) : 1148 wolfSSL_CTX_use_certificate_chain_file(wctx->ssl_ctx, cert_file); 1149 break; 1150 case WOLFSSL_FILETYPE_ASN1: 1151 rc = cert_blob ? 1152 wolfSSL_CTX_use_certificate_buffer(wctx->ssl_ctx, cert_blob->data, 1153 (long)cert_blob->len, file_type) : 1154 wolfSSL_CTX_use_certificate_file(wctx->ssl_ctx, cert_file, file_type); 1155 break; 1156 default: 1157 failf(data, "unknown cert type"); 1158 result = CURLE_BAD_FUNCTION_ARGUMENT; 1159 goto out; 1160 } 1161 if(rc != 1) { 1162 failf(data, "unable to use client certificate"); 1163 result = CURLE_SSL_CONNECT_ERROR; 1164 goto out; 1165 } 1166 1167 if(!key_blob && !key_file) { 1168 key_blob = cert_blob; 1169 key_file = cert_file; 1170 } 1171 else 1172 file_type = wssl_do_file_type(ssl_config->key_type); 1173 1174 rc = key_blob ? 1175 wolfSSL_CTX_use_PrivateKey_buffer(wctx->ssl_ctx, key_blob->data, 1176 (long)key_blob->len, file_type) : 1177 wolfSSL_CTX_use_PrivateKey_file(wctx->ssl_ctx, key_file, file_type); 1178 if(rc != 1) { 1179 failf(data, "unable to set private key"); 1180 result = CURLE_SSL_CONNECT_ERROR; 1181 goto out; 1182 } 1183 } 1184 #else /* NO_FILESYSTEM */ 1185 if(ssl_config->primary.cert_blob) { 1186 const struct curl_blob *cert_blob = ssl_config->primary.cert_blob; 1187 const struct curl_blob *key_blob = ssl_config->key_blob; 1188 int file_type = wssl_do_file_type(ssl_config->cert_type); 1189 int rc; 1190 1191 switch(file_type) { 1192 case WOLFSSL_FILETYPE_PEM: 1193 rc = wolfSSL_CTX_use_certificate_chain_buffer(wctx->ssl_ctx, 1194 cert_blob->data, 1195 (long)cert_blob->len); 1196 break; 1197 case WOLFSSL_FILETYPE_ASN1: 1198 rc = wolfSSL_CTX_use_certificate_buffer(wctx->ssl_ctx, cert_blob->data, 1199 (long)cert_blob->len, file_type); 1200 break; 1201 default: 1202 failf(data, "unknown cert type"); 1203 result = CURLE_BAD_FUNCTION_ARGUMENT; 1204 goto out; 1205 } 1206 if(rc != 1) { 1207 failf(data, "unable to use client certificate"); 1208 result = CURLE_SSL_CONNECT_ERROR; 1209 goto out; 1210 } 1211 1212 if(!key_blob) 1213 key_blob = cert_blob; 1214 else 1215 file_type = wssl_do_file_type(ssl_config->key_type); 1216 1217 if(wolfSSL_CTX_use_PrivateKey_buffer(wctx->ssl_ctx, key_blob->data, 1218 (long)key_blob->len, 1219 file_type) != 1) { 1220 failf(data, "unable to set private key"); 1221 result = CURLE_SSL_CONNECT_ERROR; 1222 goto out; 1223 } 1224 } 1225 #endif /* !NO_FILESYSTEM */ 1226 1227 /* SSL always tries to verify the peer, this only says whether it should 1228 * fail to connect if the verification fails, or if it should continue 1229 * anyway. In the latter case the result of the verification is checked with 1230 * SSL_get_verify_result() below. */ 1231 wolfSSL_CTX_set_verify(wctx->ssl_ctx, 1232 conn_config->verifypeer ? WOLFSSL_VERIFY_PEER : 1233 WOLFSSL_VERIFY_NONE, NULL); 1234 1235 #ifdef HAVE_SNI 1236 if(peer->sni) { 1237 size_t sni_len = strlen(peer->sni); 1238 if((sni_len < USHRT_MAX)) { 1239 if(wolfSSL_CTX_UseSNI(wctx->ssl_ctx, WOLFSSL_SNI_HOST_NAME, 1240 peer->sni, (unsigned short)sni_len) != 1) { 1241 failf(data, "Failed to set SNI"); 1242 result = CURLE_SSL_CONNECT_ERROR; 1243 goto out; 1244 } 1245 CURL_TRC_CF(data, cf, "set SNI '%s'", peer->sni); 1246 } 1247 } 1248 #endif 1249 1250 if(ssl_config->primary.cache_session && (transport != TRNSPRT_QUIC)) { 1251 /* Register to get notified when a new session is received */ 1252 wolfSSL_CTX_sess_set_new_cb(wctx->ssl_ctx, wssl_vtls_new_session_cb); 1253 } 1254 1255 if(cb_setup) { 1256 result = cb_setup(cf, data, cb_user_data); 1257 if(result) 1258 goto out; 1259 } 1260 1261 /* give application a chance to interfere with SSL set up. */ 1262 if(data->set.ssl.fsslctx) { 1263 if(!wctx->x509_store_setup) { 1264 result = Curl_wssl_setup_x509_store(cf, data, wctx); 1265 if(result) 1266 goto out; 1267 } 1268 result = (*data->set.ssl.fsslctx)(data, wctx->ssl_ctx, 1269 data->set.ssl.fsslctxp); 1270 if(result) { 1271 failf(data, "error signaled by ssl ctx callback"); 1272 goto out; 1273 } 1274 } 1275 #ifdef NO_FILESYSTEM 1276 else if(conn_config->verifypeer) { 1277 failf(data, "SSL: Certificates cannot be loaded because wolfSSL was built" 1278 " with \"no filesystem\". Either disable peer verification" 1279 " (insecure) or if you are building an application with libcurl you" 1280 " can load certificates via CURLOPT_SSL_CTX_FUNCTION."); 1281 result = CURLE_SSL_CONNECT_ERROR; 1282 goto out; 1283 } 1284 #endif 1285 1286 /* Let's make an SSL structure */ 1287 wctx->ssl = wolfSSL_new(wctx->ssl_ctx); 1288 if(!wctx->ssl) { 1289 failf(data, "SSL: could not create a handle"); 1290 result = CURLE_OUT_OF_MEMORY; 1291 goto out; 1292 } 1293 1294 wolfSSL_set_app_data(wctx->ssl, ssl_user_data); 1295 #ifdef WOLFSSL_QUIC 1296 if(transport == TRNSPRT_QUIC) 1297 wolfSSL_set_quic_use_legacy_codepoint(wctx->ssl, 0); 1298 #endif 1299 1300 #ifdef WOLFSSL_HAVE_KYBER 1301 if(pqkem) { 1302 if(wolfSSL_UseKeyShare(wctx->ssl, pqkem) != WOLFSSL_SUCCESS) { 1303 failf(data, "unable to use PQ KEM"); 1304 } 1305 } 1306 #endif 1307 1308 /* Check if there is a cached ID we can/should use here! */ 1309 if(ssl_config->primary.cache_session) { 1310 /* Set session from cache if there is one */ 1311 (void)wssl_setup_session(cf, data, wctx, &alpns, 1312 peer->scache_key, sess_reuse_cb); 1313 } 1314 1315 #ifdef HAVE_ALPN 1316 if(alpns.count) { 1317 struct alpn_proto_buf proto; 1318 memset(&proto, 0, sizeof(proto)); 1319 Curl_alpn_to_proto_str(&proto, &alpns); 1320 1321 if(wolfSSL_UseALPN(wctx->ssl, (char *)proto.data, 1322 (unsigned int)proto.len, 1323 WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != WOLFSSL_SUCCESS) { 1324 failf(data, "SSL: failed setting ALPN protocols"); 1325 result = CURLE_SSL_CONNECT_ERROR; 1326 goto out; 1327 } 1328 CURL_TRC_CF(data, cf, "set ALPN: %s", proto.data); 1329 } 1330 #endif /* HAVE_ALPN */ 1331 1332 #ifdef OPENSSL_EXTRA 1333 if(Curl_tls_keylog_enabled()) { 1334 /* Ensure the Client Random is preserved. */ 1335 wolfSSL_KeepArrays(wctx->ssl); 1336 #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) 1337 wolfSSL_set_tls13_secret_cb(wctx->ssl, 1338 wssl_tls13_secret_callback, NULL); 1339 #endif 1340 } 1341 #endif /* OPENSSL_EXTRA */ 1342 1343 #ifdef HAVE_SECURE_RENEGOTIATION 1344 if(wolfSSL_UseSecureRenegotiation(wctx->ssl) != SSL_SUCCESS) { 1345 failf(data, "SSL: failed setting secure renegotiation"); 1346 result = CURLE_SSL_CONNECT_ERROR; 1347 goto out; 1348 } 1349 #endif /* HAVE_SECURE_RENEGOTIATION */ 1350 1351 #ifdef USE_ECH_WOLFSSL 1352 if(ECH_ENABLED(data)) { 1353 int trying_ech_now = 0; 1354 1355 if(data->set.str[STRING_ECH_PUBLIC]) { 1356 infof(data, "ECH: outername not (yet) supported with wolfSSL"); 1357 result = CURLE_SSL_CONNECT_ERROR; 1358 goto out; 1359 } 1360 if(data->set.tls_ech == CURLECH_GREASE) { 1361 infof(data, "ECH: GREASE is done by default by wolfSSL: no need to ask"); 1362 } 1363 if(data->set.tls_ech & CURLECH_CLA_CFG 1364 && data->set.str[STRING_ECH_CONFIG]) { 1365 char *b64val = data->set.str[STRING_ECH_CONFIG]; 1366 word32 b64len = 0; 1367 1368 b64len = (word32) strlen(b64val); 1369 if(b64len 1370 && wolfSSL_SetEchConfigsBase64(wctx->ssl, b64val, b64len) 1371 != WOLFSSL_SUCCESS) { 1372 if(data->set.tls_ech & CURLECH_HARD) { 1373 result = CURLE_SSL_CONNECT_ERROR; 1374 goto out; 1375 } 1376 } 1377 else { 1378 trying_ech_now = 1; 1379 infof(data, "ECH: ECHConfig from command line"); 1380 } 1381 } 1382 else { 1383 struct ssl_connect_data *connssl = cf->ctx; 1384 struct Curl_dns_entry *dns = NULL; 1385 1386 dns = Curl_dnscache_get(data, connssl->peer.hostname, connssl->peer.port, 1387 cf->conn->ip_version); 1388 if(!dns) { 1389 infof(data, "ECH: requested but no DNS info available"); 1390 if(data->set.tls_ech & CURLECH_HARD) { 1391 result = CURLE_SSL_CONNECT_ERROR; 1392 goto out; 1393 } 1394 } 1395 else { 1396 struct Curl_https_rrinfo *rinfo = NULL; 1397 1398 rinfo = dns->hinfo; 1399 if(rinfo && rinfo->echconfiglist) { 1400 unsigned char *ecl = rinfo->echconfiglist; 1401 size_t elen = rinfo->echconfiglist_len; 1402 1403 infof(data, "ECH: ECHConfig from DoH HTTPS RR"); 1404 if(wolfSSL_SetEchConfigs(wctx->ssl, ecl, (word32) elen) != 1405 WOLFSSL_SUCCESS) { 1406 infof(data, "ECH: wolfSSL_SetEchConfigs failed"); 1407 if(data->set.tls_ech & CURLECH_HARD) { 1408 result = CURLE_SSL_CONNECT_ERROR; 1409 goto out; 1410 } 1411 } 1412 else { 1413 trying_ech_now = 1; 1414 infof(data, "ECH: imported ECHConfigList of length %ld", elen); 1415 } 1416 } 1417 else { 1418 infof(data, "ECH: requested but no ECHConfig available"); 1419 if(data->set.tls_ech & CURLECH_HARD) { 1420 result = CURLE_SSL_CONNECT_ERROR; 1421 goto out; 1422 } 1423 } 1424 Curl_resolv_unlink(data, &dns); 1425 } 1426 } 1427 1428 if(trying_ech_now && wolfSSL_set_min_proto_version(wctx->ssl, 1429 TLS1_3_VERSION) != 1) { 1430 infof(data, "ECH: cannot force TLSv1.3 [ERROR]"); 1431 result = CURLE_SSL_CONNECT_ERROR; 1432 goto out; 1433 } 1434 1435 } 1436 #endif /* USE_ECH_WOLFSSL */ 1437 1438 result = CURLE_OK; 1439 1440 out: 1441 if(result && wctx->ssl) { 1442 wolfSSL_free(wctx->ssl); 1443 wctx->ssl = NULL; 1444 } 1445 if(result && wctx->ssl_ctx) { 1446 wolfSSL_CTX_free(wctx->ssl_ctx); 1447 wctx->ssl_ctx = NULL; 1448 } 1449 return result; 1450 } 1451 1452 /* 1453 * This function loads all the client/CA certificates and CRLs. Setup the TLS 1454 * layer and do all necessary magic. 1455 */ 1456 static CURLcode 1457 wssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) 1458 { 1459 struct ssl_connect_data *connssl = cf->ctx; 1460 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 1461 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 1462 CURLcode result; 1463 1464 DEBUGASSERT(wssl); 1465 1466 if(connssl->state == ssl_connection_complete) 1467 return CURLE_OK; 1468 1469 result = Curl_wssl_ctx_init(wssl, cf, data, &connssl->peer, 1470 connssl->alpn, NULL, NULL, cf, 1471 wssl_on_session_reuse); 1472 if(result) 1473 return result; 1474 1475 #ifdef HAVE_ALPN 1476 if(connssl->alpn && (connssl->state != ssl_connection_deferred)) { 1477 struct alpn_proto_buf proto; 1478 memset(&proto, 0, sizeof(proto)); 1479 Curl_alpn_to_proto_str(&proto, connssl->alpn); 1480 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); 1481 } 1482 #endif 1483 1484 /* Enable RFC2818 checks */ 1485 if(conn_config->verifyhost) { 1486 char *snihost = connssl->peer.sni ? 1487 connssl->peer.sni : connssl->peer.hostname; 1488 if(wolfSSL_check_domain_name(wssl->ssl, snihost) != 1489 WOLFSSL_SUCCESS) { 1490 return CURLE_SSL_CONNECT_ERROR; 1491 } 1492 } 1493 1494 #ifdef USE_BIO_CHAIN 1495 { 1496 WOLFSSL_BIO *bio; 1497 1498 bio = wolfSSL_BIO_new(wssl_bio_cf_method); 1499 if(!bio) 1500 return CURLE_OUT_OF_MEMORY; 1501 1502 wolfSSL_BIO_set_data(bio, cf); 1503 wolfSSL_set_bio(wssl->ssl, bio, bio); 1504 } 1505 #else /* USE_BIO_CHAIN */ 1506 /* pass the raw socket into the SSL layer */ 1507 if(!wolfSSL_set_fd(wssl->ssl, 1508 (int)Curl_conn_cf_get_socket(cf, data))) { 1509 failf(data, "SSL: wolfSSL_set_fd failed"); 1510 return CURLE_SSL_CONNECT_ERROR; 1511 } 1512 #endif /* !USE_BIO_CHAIN */ 1513 1514 return CURLE_OK; 1515 } 1516 1517 1518 static char *wssl_strerror(unsigned long error, char *buf, 1519 unsigned long size) 1520 { 1521 DEBUGASSERT(size > 40); 1522 *buf = '\0'; 1523 1524 wolfSSL_ERR_error_string_n(error, buf, size); 1525 1526 if(!*buf) { 1527 const char *msg = error ? "Unknown error" : "No error"; 1528 /* the string fits because the assert above assures this */ 1529 strcpy(buf, msg); 1530 } 1531 1532 return buf; 1533 } 1534 1535 CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf, 1536 struct Curl_easy *data, 1537 struct wssl_ctx *wssl) 1538 { 1539 #ifndef CURL_DISABLE_PROXY 1540 const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ? 1541 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : 1542 data->set.str[STRING_SSL_PINNEDPUBLICKEY]; 1543 #else 1544 const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; 1545 #endif 1546 1547 if(pinnedpubkey) { 1548 #ifdef KEEP_PEER_CERT 1549 WOLFSSL_X509 *x509; 1550 const char *x509_der; 1551 int x509_der_len; 1552 struct Curl_X509certificate x509_parsed; 1553 struct Curl_asn1Element *pubkey; 1554 CURLcode result; 1555 1556 x509 = wolfSSL_get_peer_certificate(wssl->ssl); 1557 if(!x509) { 1558 failf(data, "SSL: failed retrieving server certificate"); 1559 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 1560 } 1561 1562 x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len); 1563 if(!x509_der) { 1564 failf(data, "SSL: failed retrieving ASN.1 server certificate"); 1565 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 1566 } 1567 1568 memset(&x509_parsed, 0, sizeof(x509_parsed)); 1569 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) 1570 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 1571 1572 pubkey = &x509_parsed.subjectPublicKeyInfo; 1573 if(!pubkey->header || pubkey->end <= pubkey->header) { 1574 failf(data, "SSL: failed retrieving public key from server certificate"); 1575 return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 1576 } 1577 1578 result = Curl_pin_peer_pubkey(data, 1579 pinnedpubkey, 1580 (const unsigned char *)pubkey->header, 1581 (size_t)(pubkey->end - pubkey->header)); 1582 wolfSSL_FreeX509(x509); 1583 if(result) { 1584 failf(data, "SSL: public key does not match pinned public key"); 1585 return result; 1586 } 1587 #else 1588 failf(data, "Library lacks pinning support built-in"); 1589 return CURLE_NOT_BUILT_IN; 1590 #endif 1591 } 1592 return CURLE_OK; 1593 } 1594 1595 #ifdef WOLFSSL_EARLY_DATA 1596 static CURLcode wssl_send_earlydata(struct Curl_cfilter *cf, 1597 struct Curl_easy *data) 1598 { 1599 struct ssl_connect_data *connssl = cf->ctx; 1600 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 1601 CURLcode result = CURLE_OK; 1602 const unsigned char *buf; 1603 size_t blen; 1604 1605 DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sending); 1606 wssl->io_result = CURLE_OK; 1607 while(Curl_bufq_peek(&connssl->earlydata, &buf, &blen)) { 1608 int nwritten = 0, rc; 1609 1610 wolfSSL_ERR_clear_error(); 1611 rc = wolfSSL_write_early_data(wssl->ssl, buf, (int)blen, &nwritten); 1612 CURL_TRC_CF(data, cf, "wolfSSL_write_early_data(len=%zu) -> %d, %d", 1613 blen, rc, nwritten); 1614 if(rc < 0) { 1615 int err = wolfSSL_get_error(wssl->ssl, rc); 1616 switch(err) { 1617 case WOLFSSL_ERROR_NONE: /* just did not get anything */ 1618 case WOLFSSL_ERROR_WANT_READ: 1619 case WOLFSSL_ERROR_WANT_WRITE: 1620 result = CURLE_AGAIN; 1621 break; 1622 default: { 1623 char error_buffer[256]; 1624 int detail = wolfSSL_get_error(wssl->ssl, err); 1625 CURL_TRC_CF(data, cf, "SSL send early data, error: '%s'(%d)", 1626 wssl_strerror((unsigned long)err, error_buffer, 1627 sizeof(error_buffer)), 1628 detail); 1629 result = CURLE_SEND_ERROR; 1630 break; 1631 } 1632 } 1633 goto out; 1634 } 1635 1636 Curl_bufq_skip(&connssl->earlydata, (size_t)nwritten); 1637 } 1638 /* sent everything there was */ 1639 connssl->earlydata_state = ssl_earlydata_sent; 1640 if(!Curl_ssl_cf_is_proxy(cf)) 1641 Curl_pgrsEarlyData(data, (curl_off_t)connssl->earlydata_skip); 1642 infof(data, "SSL sending %zu bytes of early data", connssl->earlydata_skip); 1643 out: 1644 return result; 1645 } 1646 #endif /* WOLFSSL_EARLY_DATA */ 1647 1648 static CURLcode wssl_handshake(struct Curl_cfilter *cf, 1649 struct Curl_easy *data) 1650 { 1651 struct ssl_connect_data *connssl = cf->ctx; 1652 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 1653 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 1654 int ret = -1, detail; 1655 CURLcode result; 1656 1657 DEBUGASSERT(wssl); 1658 connssl->io_need = CURL_SSL_IO_NEED_NONE; 1659 1660 #ifdef WOLFSSL_EARLY_DATA 1661 if(connssl->earlydata_state == ssl_earlydata_sending) { 1662 result = wssl_send_earlydata(cf, data); 1663 if(result) 1664 return result; 1665 } 1666 DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) || 1667 (connssl->earlydata_state == ssl_earlydata_sent)); 1668 #else 1669 DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_none); 1670 #endif /* WOLFSSL_EARLY_DATA */ 1671 1672 wolfSSL_ERR_clear_error(); 1673 ret = wolfSSL_connect(wssl->ssl); 1674 1675 if(!wssl->x509_store_setup) { 1676 /* After having send off the ClientHello, we prepare the x509 1677 * store to verify the coming certificate from the server */ 1678 result = Curl_wssl_setup_x509_store(cf, data, wssl); 1679 if(result) { 1680 CURL_TRC_CF(data, cf, "Curl_wssl_setup_x509_store() -> %d", result); 1681 return result; 1682 } 1683 } 1684 1685 #ifdef OPENSSL_EXTRA 1686 if(Curl_tls_keylog_enabled()) { 1687 /* If key logging is enabled, wait for the handshake to complete and then 1688 * proceed with logging secrets (for TLS 1.2 or older). 1689 * 1690 * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits 1691 * for the server response. At that point the master secret is not yet 1692 * available, so we must not try to read it. 1693 * To log the secret on completion with a handshake failure, detect 1694 * completion via the observation that there is nothing to read or write. 1695 * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever 1696 * changes, the worst case is that no key is logged on error. 1697 */ 1698 if(ret == WOLFSSL_SUCCESS || 1699 (!wolfSSL_want_read(wssl->ssl) && 1700 !wolfSSL_want_write(wssl->ssl))) { 1701 wssl_log_tls12_secret(wssl->ssl); 1702 /* Client Random and master secrets are no longer needed, erase these. 1703 * Ignored while the handshake is still in progress. */ 1704 wolfSSL_FreeArrays(wssl->ssl); 1705 } 1706 } 1707 #endif /* OPENSSL_EXTRA */ 1708 1709 detail = wolfSSL_get_error(wssl->ssl, ret); 1710 CURL_TRC_CF(data, cf, "wolfSSL_connect() -> %d, detail=%d", ret, detail); 1711 1712 if(ret == WOLFSSL_SUCCESS) { 1713 return CURLE_OK; 1714 } 1715 else { 1716 if(WOLFSSL_ERROR_WANT_READ == detail) { 1717 connssl->io_need = CURL_SSL_IO_NEED_RECV; 1718 return CURLE_AGAIN; 1719 } 1720 else if(WOLFSSL_ERROR_WANT_WRITE == detail) { 1721 connssl->io_need = CURL_SSL_IO_NEED_SEND; 1722 return CURLE_AGAIN; 1723 } 1724 else if(DOMAIN_NAME_MISMATCH == detail) { 1725 /* There is no easy way to override only the CN matching. 1726 * This will enable the override of both mismatching SubjectAltNames 1727 * as also mismatching CN fields */ 1728 failf(data, " subject alt name(s) or common name do not match \"%s\"", 1729 connssl->peer.dispname); 1730 return CURLE_PEER_FAILED_VERIFICATION; 1731 } 1732 else if(ASN_NO_SIGNER_E == detail) { 1733 if(conn_config->verifypeer) { 1734 failf(data, " CA signer not available for verification"); 1735 return CURLE_SSL_CACERT_BADFILE; 1736 } 1737 /* Just continue with a warning if no strict certificate 1738 verification is required. */ 1739 infof(data, "CA signer not available for verification, " 1740 "continuing anyway"); 1741 return CURLE_OK; 1742 } 1743 else if(ASN_AFTER_DATE_E == detail) { 1744 failf(data, "server verification failed: certificate has expired."); 1745 return CURLE_PEER_FAILED_VERIFICATION; 1746 } 1747 else if(ASN_BEFORE_DATE_E == detail) { 1748 failf(data, "server verification failed: certificate not valid yet."); 1749 return CURLE_PEER_FAILED_VERIFICATION; 1750 } 1751 else if(wssl->io_result) { 1752 switch(wssl->io_result) { 1753 case CURLE_SEND_ERROR: 1754 case CURLE_RECV_ERROR: 1755 return CURLE_SSL_CONNECT_ERROR; 1756 default: 1757 return wssl->io_result; 1758 } 1759 } 1760 #ifdef USE_ECH_WOLFSSL 1761 else if(-1 == detail) { 1762 /* try access a retry_config ECHConfigList for tracing */ 1763 byte echConfigs[1000]; 1764 word32 echConfigsLen = 1000; 1765 int rv = 0; 1766 1767 /* this currently does not produce the retry_configs */ 1768 rv = wolfSSL_GetEchConfigs(wssl->ssl, echConfigs, 1769 &echConfigsLen); 1770 if(rv != WOLFSSL_SUCCESS) { 1771 infof(data, "Failed to get ECHConfigs"); 1772 } 1773 else { 1774 char *b64str = NULL; 1775 size_t blen = 0; 1776 1777 result = curlx_base64_encode((const char *)echConfigs, echConfigsLen, 1778 &b64str, &blen); 1779 if(!result && b64str) 1780 infof(data, "ECH: (not yet) retry_configs %s", b64str); 1781 free(b64str); 1782 } 1783 return CURLE_SSL_CONNECT_ERROR; 1784 } 1785 #endif 1786 else { 1787 char error_buffer[256]; 1788 failf(data, "SSL_connect failed with error %d: %s", detail, 1789 wssl_strerror((unsigned long)detail, error_buffer, 1790 sizeof(error_buffer))); 1791 return CURLE_SSL_CONNECT_ERROR; 1792 } 1793 } 1794 } 1795 1796 static CURLcode wssl_send(struct Curl_cfilter *cf, 1797 struct Curl_easy *data, 1798 const void *buf, size_t blen, 1799 size_t *pnwritten) 1800 { 1801 struct ssl_connect_data *connssl = cf->ctx; 1802 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 1803 CURLcode result = CURLE_OK; 1804 int nwritten; 1805 1806 DEBUGASSERT(wssl); 1807 *pnwritten = 0; 1808 wolfSSL_ERR_clear_error(); 1809 1810 if(blen) { 1811 int memlen = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen; 1812 1813 nwritten = wolfSSL_write(wssl->ssl, buf, memlen); 1814 1815 if(nwritten > 0) 1816 *pnwritten += (size_t)nwritten; 1817 else { 1818 int err = wolfSSL_get_error(wssl->ssl, nwritten); 1819 1820 switch(err) { 1821 case WOLFSSL_ERROR_WANT_READ: 1822 case WOLFSSL_ERROR_WANT_WRITE: 1823 /* there is data pending, re-invoke wolfSSL_write() */ 1824 if(*pnwritten) { 1825 result = CURLE_OK; 1826 goto out; 1827 } 1828 result = CURLE_AGAIN; 1829 goto out; 1830 1831 default: 1832 if(wssl->io_result == CURLE_AGAIN) { 1833 if(*pnwritten) { 1834 result = CURLE_OK; 1835 goto out; 1836 } 1837 result = CURLE_AGAIN; 1838 goto out; 1839 } 1840 { 1841 char error_buffer[256]; 1842 failf(data, "SSL write: %s, errno %d", 1843 wssl_strerror((unsigned long)err, error_buffer, 1844 sizeof(error_buffer)), 1845 SOCKERRNO); 1846 } 1847 result = CURLE_SEND_ERROR; 1848 goto out; 1849 } 1850 } 1851 } 1852 1853 out: 1854 CURL_TRC_CF(data, cf, "wssl_send(len=%zu) -> %d, %zu", 1855 blen, result, *pnwritten); 1856 return result; 1857 } 1858 1859 static CURLcode wssl_shutdown(struct Curl_cfilter *cf, 1860 struct Curl_easy *data, 1861 bool send_shutdown, bool *done) 1862 { 1863 struct ssl_connect_data *connssl = cf->ctx; 1864 struct wssl_ctx *wctx = (struct wssl_ctx *)connssl->backend; 1865 CURLcode result = CURLE_OK; 1866 char buf[1024]; 1867 char error_buffer[256]; 1868 int nread = -1, err; 1869 size_t i; 1870 int detail; 1871 1872 DEBUGASSERT(wctx); 1873 if(!wctx->ssl || cf->shutdown) { 1874 *done = TRUE; 1875 goto out; 1876 } 1877 1878 wctx->shutting_down = TRUE; 1879 connssl->io_need = CURL_SSL_IO_NEED_NONE; 1880 *done = FALSE; 1881 if(!(wolfSSL_get_shutdown(wctx->ssl) & WOLFSSL_SENT_SHUTDOWN)) { 1882 /* We have not started the shutdown from our side yet. Check 1883 * if the server already sent us one. */ 1884 wolfSSL_ERR_clear_error(); 1885 nread = wolfSSL_read(wctx->ssl, buf, (int)sizeof(buf)); 1886 err = wolfSSL_get_error(wctx->ssl, nread); 1887 CURL_TRC_CF(data, cf, "wolfSSL_read, nread=%d, err=%d", nread, err); 1888 if(!nread && err == WOLFSSL_ERROR_ZERO_RETURN) { 1889 bool input_pending; 1890 /* Yes, it did. */ 1891 if(!send_shutdown) { 1892 CURL_TRC_CF(data, cf, "SSL shutdown received, not sending"); 1893 *done = TRUE; 1894 goto out; 1895 } 1896 else if(!cf->next->cft->is_alive(cf->next, data, &input_pending)) { 1897 /* Server closed the connection after its closy notify. It 1898 * seems not interested to see our close notify, so do not 1899 * send it. We are done. */ 1900 CURL_TRC_CF(data, cf, "peer closed connection"); 1901 connssl->peer_closed = TRUE; 1902 *done = TRUE; 1903 goto out; 1904 } 1905 } 1906 } 1907 1908 /* wolfSSL should now have started the shutdown from our side. Since it 1909 * was not complete, we are lacking the close notify from the server. */ 1910 if(send_shutdown) { 1911 wolfSSL_ERR_clear_error(); 1912 if(wolfSSL_shutdown(wctx->ssl) == 1) { 1913 CURL_TRC_CF(data, cf, "SSL shutdown finished"); 1914 *done = TRUE; 1915 goto out; 1916 } 1917 if(WOLFSSL_ERROR_WANT_WRITE == wolfSSL_get_error(wctx->ssl, nread)) { 1918 CURL_TRC_CF(data, cf, "SSL shutdown still wants to send"); 1919 connssl->io_need = CURL_SSL_IO_NEED_SEND; 1920 goto out; 1921 } 1922 /* Having sent the close notify, we use wolfSSL_read() to get the 1923 * missing close notify from the server. */ 1924 } 1925 1926 for(i = 0; i < 10; ++i) { 1927 wolfSSL_ERR_clear_error(); 1928 nread = wolfSSL_read(wctx->ssl, buf, (int)sizeof(buf)); 1929 if(nread <= 0) 1930 break; 1931 } 1932 err = wolfSSL_get_error(wctx->ssl, nread); 1933 switch(err) { 1934 case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */ 1935 CURL_TRC_CF(data, cf, "SSL shutdown received"); 1936 *done = TRUE; 1937 break; 1938 case WOLFSSL_ERROR_NONE: /* just did not get anything */ 1939 case WOLFSSL_ERROR_WANT_READ: 1940 /* wolfSSL has send its notify and now wants to read the reply 1941 * from the server. We are not really interested in that. */ 1942 CURL_TRC_CF(data, cf, "SSL shutdown sent, want receive"); 1943 connssl->io_need = CURL_SSL_IO_NEED_RECV; 1944 break; 1945 case WOLFSSL_ERROR_WANT_WRITE: 1946 CURL_TRC_CF(data, cf, "SSL shutdown send blocked"); 1947 connssl->io_need = CURL_SSL_IO_NEED_SEND; 1948 break; 1949 default: 1950 detail = wolfSSL_get_error(wctx->ssl, err); 1951 CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s'(%d)", 1952 wssl_strerror((unsigned long)err, error_buffer, 1953 sizeof(error_buffer)), 1954 detail); 1955 result = CURLE_RECV_ERROR; 1956 break; 1957 } 1958 1959 out: 1960 cf->shutdown = (result || *done); 1961 return result; 1962 } 1963 1964 static void wssl_close(struct Curl_cfilter *cf, struct Curl_easy *data) 1965 { 1966 struct ssl_connect_data *connssl = cf->ctx; 1967 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 1968 1969 (void) data; 1970 1971 DEBUGASSERT(wssl); 1972 1973 if(wssl->ssl) { 1974 wolfSSL_free(wssl->ssl); 1975 wssl->ssl = NULL; 1976 } 1977 if(wssl->ssl_ctx) { 1978 wolfSSL_CTX_free(wssl->ssl_ctx); 1979 wssl->ssl_ctx = NULL; 1980 } 1981 } 1982 1983 static CURLcode wssl_recv(struct Curl_cfilter *cf, 1984 struct Curl_easy *data, 1985 char *buf, size_t blen, 1986 size_t *pnread) 1987 { 1988 struct ssl_connect_data *connssl = cf->ctx; 1989 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 1990 int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen; 1991 int nread; 1992 1993 DEBUGASSERT(wssl); 1994 1995 *pnread = 0; 1996 wolfSSL_ERR_clear_error(); 1997 1998 nread = wolfSSL_read(wssl->ssl, buf, buffsize); 1999 2000 if(nread > 0) 2001 *pnread = (size_t)nread; 2002 else { 2003 int err = wolfSSL_get_error(wssl->ssl, nread); 2004 2005 switch(err) { 2006 case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */ 2007 CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> CLOSED", blen); 2008 return CURLE_OK; 2009 case WOLFSSL_ERROR_NONE: 2010 case WOLFSSL_ERROR_WANT_READ: 2011 case WOLFSSL_ERROR_WANT_WRITE: 2012 if(!wssl->io_result && connssl->peer_closed) { 2013 CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> CLOSED", blen); 2014 return CURLE_OK; 2015 } 2016 /* there is data pending, re-invoke wolfSSL_read() */ 2017 CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> AGAIN", blen); 2018 return CURLE_AGAIN; 2019 default: 2020 if(wssl->io_result == CURLE_AGAIN) { 2021 CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> AGAIN", blen); 2022 return CURLE_AGAIN; 2023 } 2024 else if(!wssl->io_result && connssl->peer_closed) { 2025 CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> CLOSED", blen); 2026 failf(data, "Connection closed abruptly"); 2027 } 2028 else { 2029 char error_buffer[256]; 2030 failf(data, "SSL read: %s, errno %d", 2031 wssl_strerror((unsigned long)err, error_buffer, 2032 sizeof(error_buffer)), 2033 SOCKERRNO); 2034 } 2035 return CURLE_RECV_ERROR; 2036 } 2037 } 2038 2039 CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> 0, %zu", blen, *pnread); 2040 return CURLE_OK; 2041 } 2042 2043 size_t Curl_wssl_version(char *buffer, size_t size) 2044 { 2045 #if LIBWOLFSSL_VERSION_HEX >= 0x03006000 2046 return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version()); 2047 #elif defined(WOLFSSL_VERSION) 2048 return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); 2049 #endif 2050 } 2051 2052 2053 static int wssl_init(void) 2054 { 2055 int ret; 2056 2057 #ifdef OPENSSL_EXTRA 2058 Curl_tls_keylog_open(); 2059 #endif 2060 ret = (wolfSSL_Init() == WOLFSSL_SUCCESS); 2061 wssl_bio_cf_init_methods(); 2062 return ret; 2063 } 2064 2065 2066 static void wssl_cleanup(void) 2067 { 2068 wssl_bio_cf_free_methods(); 2069 wolfSSL_Cleanup(); 2070 #ifdef OPENSSL_EXTRA 2071 Curl_tls_keylog_close(); 2072 #endif 2073 } 2074 2075 2076 static bool wssl_data_pending(struct Curl_cfilter *cf, 2077 const struct Curl_easy *data) 2078 { 2079 struct ssl_connect_data *ctx = cf->ctx; 2080 struct wssl_ctx *wssl; 2081 2082 (void)data; 2083 DEBUGASSERT(ctx && ctx->backend); 2084 2085 wssl = (struct wssl_ctx *)ctx->backend; 2086 if(wssl->ssl) /* wolfSSL is in use */ 2087 return wolfSSL_pending(wssl->ssl); 2088 else 2089 return FALSE; 2090 } 2091 2092 void Curl_wssl_report_handshake(struct Curl_easy *data, 2093 struct wssl_ctx *wssl) 2094 { 2095 #if (LIBWOLFSSL_VERSION_HEX >= 0x03009010) 2096 infof(data, "SSL connection using %s / %s", 2097 wolfSSL_get_version(wssl->ssl), 2098 wolfSSL_get_cipher_name(wssl->ssl)); 2099 #else 2100 infof(data, "SSL connected"); 2101 #endif 2102 } 2103 2104 static CURLcode wssl_connect(struct Curl_cfilter *cf, 2105 struct Curl_easy *data, 2106 bool *done) 2107 { 2108 struct ssl_connect_data *connssl = cf->ctx; 2109 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 2110 CURLcode result = CURLE_OK; 2111 2112 /* check if the connection has already been established */ 2113 if(ssl_connection_complete == connssl->state) { 2114 *done = TRUE; 2115 return CURLE_OK; 2116 } 2117 2118 *done = FALSE; 2119 connssl->io_need = CURL_SSL_IO_NEED_NONE; 2120 2121 if(ssl_connect_1 == connssl->connecting_state) { 2122 result = wssl_connect_step1(cf, data); 2123 if(result) 2124 return result; 2125 connssl->connecting_state = ssl_connect_2; 2126 } 2127 2128 if(ssl_connect_2 == connssl->connecting_state) { 2129 if(connssl->earlydata_state == ssl_earlydata_await) { 2130 /* We defer the handshake until request data arrives. */ 2131 DEBUGASSERT(connssl->state == ssl_connection_deferred); 2132 goto out; 2133 } 2134 result = wssl_handshake(cf, data); 2135 if(result == CURLE_AGAIN) 2136 goto out; 2137 wssl->hs_result = result; 2138 connssl->connecting_state = ssl_connect_3; 2139 } 2140 2141 if(ssl_connect_3 == connssl->connecting_state) { 2142 /* Once the handshake has errored, it stays in that state and will 2143 * error again on every call. */ 2144 if(wssl->hs_result) { 2145 result = wssl->hs_result; 2146 goto out; 2147 } 2148 result = Curl_wssl_verify_pinned(cf, data, wssl); 2149 if(result) { 2150 wssl->hs_result = result; 2151 goto out; 2152 } 2153 /* handhshake was done without errors */ 2154 #ifdef HAVE_ALPN 2155 if(connssl->alpn) { 2156 int rc; 2157 char *protocol = NULL; 2158 unsigned short protocol_len = 0; 2159 2160 rc = wolfSSL_ALPN_GetProtocol(wssl->ssl, &protocol, &protocol_len); 2161 2162 if(rc == WOLFSSL_SUCCESS) { 2163 Curl_alpn_set_negotiated(cf, data, connssl, 2164 (const unsigned char *)protocol, 2165 protocol_len); 2166 } 2167 else if(rc == WOLFSSL_ALPN_NOT_FOUND) 2168 Curl_alpn_set_negotiated(cf, data, connssl, NULL, 0); 2169 else { 2170 failf(data, "ALPN, failure getting protocol, error %d", rc); 2171 wssl->hs_result = result = CURLE_SSL_CONNECT_ERROR; 2172 goto out; 2173 } 2174 } 2175 #endif /* HAVE_ALPN */ 2176 2177 connssl->connecting_state = ssl_connect_done; 2178 connssl->state = ssl_connection_complete; 2179 Curl_wssl_report_handshake(data, wssl); 2180 2181 #ifdef WOLFSSL_EARLY_DATA 2182 if(connssl->earlydata_state > ssl_earlydata_none) { 2183 /* We should be in this state by now */ 2184 DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sent); 2185 connssl->earlydata_state = 2186 (wolfSSL_get_early_data_status(wssl->ssl) == 2187 WOLFSSL_EARLY_DATA_REJECTED) ? 2188 ssl_earlydata_rejected : ssl_earlydata_accepted; 2189 } 2190 #endif /* WOLFSSL_EARLY_DATA */ 2191 } 2192 2193 if((connssl->connecting_state == ssl_connect_done) || 2194 (connssl->state == ssl_connection_deferred)) { 2195 *done = TRUE; 2196 } 2197 2198 out: 2199 if(result) { 2200 *done = FALSE; 2201 if(result == CURLE_AGAIN) 2202 return CURLE_OK; 2203 } 2204 else if((connssl->connecting_state == ssl_connect_done) || 2205 (connssl->state == ssl_connection_deferred)) { 2206 *done = TRUE; 2207 } 2208 return result; 2209 } 2210 2211 static CURLcode wssl_random(struct Curl_easy *data, 2212 unsigned char *entropy, size_t length) 2213 { 2214 WC_RNG rng; 2215 (void)data; 2216 if(wc_InitRng(&rng)) 2217 return CURLE_FAILED_INIT; 2218 if(length > UINT_MAX) 2219 return CURLE_FAILED_INIT; 2220 if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length)) 2221 return CURLE_FAILED_INIT; 2222 if(wc_FreeRng(&rng)) 2223 return CURLE_FAILED_INIT; 2224 return CURLE_OK; 2225 } 2226 2227 static CURLcode wssl_sha256sum(const unsigned char *tmp, /* input */ 2228 size_t tmplen, 2229 unsigned char *sha256sum /* output */, 2230 size_t unused) 2231 { 2232 wc_Sha256 SHA256pw; 2233 (void)unused; 2234 if(wc_InitSha256(&SHA256pw)) 2235 return CURLE_FAILED_INIT; 2236 wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen); 2237 wc_Sha256Final(&SHA256pw, sha256sum); 2238 return CURLE_OK; 2239 } 2240 2241 static void *wssl_get_internals(struct ssl_connect_data *connssl, 2242 CURLINFO info UNUSED_PARAM) 2243 { 2244 struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; 2245 (void)info; 2246 DEBUGASSERT(wssl); 2247 return wssl->ssl; 2248 } 2249 2250 const struct Curl_ssl Curl_ssl_wolfssl = { 2251 { CURLSSLBACKEND_WOLFSSL, "wolfssl" }, /* info */ 2252 2253 #ifdef KEEP_PEER_CERT 2254 SSLSUPP_PINNEDPUBKEY | 2255 #endif 2256 #ifdef USE_BIO_CHAIN 2257 SSLSUPP_HTTPS_PROXY | 2258 #endif 2259 SSLSUPP_CA_PATH | 2260 SSLSUPP_CAINFO_BLOB | 2261 #ifdef USE_ECH_WOLFSSL 2262 SSLSUPP_ECH | 2263 #endif 2264 SSLSUPP_SSL_CTX | 2265 #ifdef WOLFSSL_TLS13 2266 SSLSUPP_TLS13_CIPHERSUITES | 2267 #endif 2268 SSLSUPP_CA_CACHE | 2269 SSLSUPP_CIPHER_LIST, 2270 2271 sizeof(struct wssl_ctx), 2272 2273 wssl_init, /* init */ 2274 wssl_cleanup, /* cleanup */ 2275 Curl_wssl_version, /* version */ 2276 wssl_shutdown, /* shutdown */ 2277 wssl_data_pending, /* data_pending */ 2278 wssl_random, /* random */ 2279 NULL, /* cert_status_request */ 2280 wssl_connect, /* connect */ 2281 Curl_ssl_adjust_pollset, /* adjust_pollset */ 2282 wssl_get_internals, /* get_internals */ 2283 wssl_close, /* close_one */ 2284 NULL, /* close_all */ 2285 NULL, /* set_engine */ 2286 NULL, /* set_engine_default */ 2287 NULL, /* engines_list */ 2288 wssl_sha256sum, /* sha256sum */ 2289 wssl_recv, /* recv decrypted data */ 2290 wssl_send, /* send data to encrypt */ 2291 NULL, /* get_channel_binding */ 2292 }; 2293 2294 #endif