VirtualBox

source: vbox/trunk/src/libs/curl-8.7.1/lib/vtls/wolfssl.c@ 104773

Last change on this file since 104773 was 104083, checked in by vboxsync, 9 months ago

curl-8.7.1: Applied and adjusted our curl changes to 8.4.0. bugref:10639

  • Property svn:eol-style set to native
File size: 42.7 KB
Line 
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_data(bio, NULL);
236 return 1;
237}
238
239static int wolfssl_bio_cf_destroy(WOLFSSL_BIO *bio)
240{
241 if(!bio)
242 return 0;
243 return 1;
244}
245
246static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
247{
248 struct Curl_cfilter *cf = BIO_get_data(bio);
249 long ret = 1;
250
251 (void)cf;
252 (void)ptr;
253 switch(cmd) {
254 case BIO_CTRL_GET_CLOSE:
255 ret = (long)wolfSSL_BIO_get_shutdown(bio);
256 break;
257 case BIO_CTRL_SET_CLOSE:
258 wolfSSL_BIO_set_shutdown(bio, (int)num);
259 break;
260 case BIO_CTRL_FLUSH:
261 /* we do no delayed writes, but if we ever would, this
262 * needs to trigger it. */
263 ret = 1;
264 break;
265 case BIO_CTRL_DUP:
266 ret = 1;
267 break;
268#ifdef BIO_CTRL_EOF
269 case BIO_CTRL_EOF:
270 /* EOF has been reached on input? */
271 return (!cf->next || !cf->next->connected);
272#endif
273 default:
274 ret = 0;
275 break;
276 }
277 return ret;
278}
279
280static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio,
281 const char *buf, int blen)
282{
283 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
284 struct ssl_connect_data *connssl = cf->ctx;
285 struct wolfssl_ssl_backend_data *backend =
286 (struct wolfssl_ssl_backend_data *)connssl->backend;
287 struct Curl_easy *data = CF_DATA_CURRENT(cf);
288 ssize_t nwritten;
289 CURLcode result = CURLE_OK;
290
291 DEBUGASSERT(data);
292 nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
293 backend->io_result = result;
294 CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
295 blen, nwritten, result);
296 wolfSSL_BIO_clear_retry_flags(bio);
297 if(nwritten < 0 && CURLE_AGAIN == result)
298 BIO_set_retry_write(bio);
299 return (int)nwritten;
300}
301
302static int wolfssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
303{
304 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
305 struct ssl_connect_data *connssl = cf->ctx;
306 struct wolfssl_ssl_backend_data *backend =
307 (struct wolfssl_ssl_backend_data *)connssl->backend;
308 struct Curl_easy *data = CF_DATA_CURRENT(cf);
309 ssize_t nread;
310 CURLcode result = CURLE_OK;
311
312 DEBUGASSERT(data);
313 /* OpenSSL catches this case, so should we. */
314 if(!buf)
315 return 0;
316
317 nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
318 backend->io_result = result;
319 CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %zd, %d", blen, nread, result);
320 wolfSSL_BIO_clear_retry_flags(bio);
321 if(nread < 0 && CURLE_AGAIN == result)
322 BIO_set_retry_read(bio);
323 else if(nread == 0)
324 connssl->peer_closed = TRUE;
325 return (int)nread;
326}
327
328static WOLFSSL_BIO_METHOD *wolfssl_bio_cf_method = NULL;
329
330static void wolfssl_bio_cf_init_methods(void)
331{
332 wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO");
333 wolfSSL_BIO_meth_set_write(wolfssl_bio_cf_method, &wolfssl_bio_cf_out_write);
334 wolfSSL_BIO_meth_set_read(wolfssl_bio_cf_method, &wolfssl_bio_cf_in_read);
335 wolfSSL_BIO_meth_set_ctrl(wolfssl_bio_cf_method, &wolfssl_bio_cf_ctrl);
336 wolfSSL_BIO_meth_set_create(wolfssl_bio_cf_method, &wolfssl_bio_cf_create);
337 wolfSSL_BIO_meth_set_destroy(wolfssl_bio_cf_method, &wolfssl_bio_cf_destroy);
338}
339
340static void wolfssl_bio_cf_free_methods(void)
341{
342 wolfSSL_BIO_meth_free(wolfssl_bio_cf_method);
343}
344
345#else /* USE_BIO_CHAIN */
346
347#define wolfssl_bio_cf_init_methods() Curl_nop_stmt
348#define wolfssl_bio_cf_free_methods() Curl_nop_stmt
349
350#endif /* !USE_BIO_CHAIN */
351
352/*
353 * This function loads all the client/CA certificates and CRLs. Setup the TLS
354 * layer and do all necessary magic.
355 */
356static CURLcode
357wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
358{
359 char *ciphers, *curves;
360 struct ssl_connect_data *connssl = cf->ctx;
361 struct wolfssl_ssl_backend_data *backend =
362 (struct wolfssl_ssl_backend_data *)connssl->backend;
363 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
364 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
365 const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
366 const char * const ssl_cafile =
367 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
368 (ca_info_blob ? NULL : conn_config->CAfile);
369 const char * const ssl_capath = conn_config->CApath;
370 WOLFSSL_METHOD* req_method = NULL;
371#ifdef HAVE_LIBOQS
372 word16 oqsAlg = 0;
373 size_t idx = 0;
374#endif
375#ifdef HAVE_SNI
376 bool sni = FALSE;
377#define use_sni(x) sni = (x)
378#else
379#define use_sni(x) Curl_nop_stmt
380#endif
381 bool imported_native_ca = false;
382 bool imported_ca_info_blob = false;
383
384 DEBUGASSERT(backend);
385
386 if(connssl->state == ssl_connection_complete)
387 return CURLE_OK;
388
389 if(conn_config->version_max != CURL_SSLVERSION_MAX_NONE) {
390 failf(data, "wolfSSL does not support to set maximum SSL/TLS version");
391 return CURLE_SSL_CONNECT_ERROR;
392 }
393
394 /* check to see if we've been told to use an explicit SSL/TLS version */
395 switch(conn_config->version) {
396 case CURL_SSLVERSION_DEFAULT:
397 case CURL_SSLVERSION_TLSv1:
398#if LIBWOLFSSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
399 /* minimum protocol version is set later after the CTX object is created */
400 req_method = SSLv23_client_method();
401#else
402 infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
403 "TLS 1.0 is used exclusively");
404 req_method = TLSv1_client_method();
405#endif
406 use_sni(TRUE);
407 break;
408 case CURL_SSLVERSION_TLSv1_0:
409#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
410 req_method = TLSv1_client_method();
411 use_sni(TRUE);
412#else
413 failf(data, "wolfSSL does not support TLS 1.0");
414 return CURLE_NOT_BUILT_IN;
415#endif
416 break;
417 case CURL_SSLVERSION_TLSv1_1:
418#ifndef NO_OLD_TLS
419 req_method = TLSv1_1_client_method();
420 use_sni(TRUE);
421#else
422 failf(data, "wolfSSL does not support TLS 1.1");
423 return CURLE_NOT_BUILT_IN;
424#endif
425 break;
426 case CURL_SSLVERSION_TLSv1_2:
427#ifndef WOLFSSL_NO_TLS12
428 req_method = TLSv1_2_client_method();
429 use_sni(TRUE);
430#else
431 failf(data, "wolfSSL does not support TLS 1.2");
432 return CURLE_NOT_BUILT_IN;
433#endif
434 break;
435 case CURL_SSLVERSION_TLSv1_3:
436#ifdef WOLFSSL_TLS13
437 req_method = wolfTLSv1_3_client_method();
438 use_sni(TRUE);
439 break;
440#else
441 failf(data, "wolfSSL: TLS 1.3 is not yet supported");
442 return CURLE_SSL_CONNECT_ERROR;
443#endif
444 default:
445 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
446 return CURLE_SSL_CONNECT_ERROR;
447 }
448
449 if(!req_method) {
450 failf(data, "SSL: couldn't create a method");
451 return CURLE_OUT_OF_MEMORY;
452 }
453
454 if(backend->ctx)
455 wolfSSL_CTX_free(backend->ctx);
456 backend->ctx = wolfSSL_CTX_new(req_method);
457
458 if(!backend->ctx) {
459 failf(data, "SSL: couldn't create a context");
460 return CURLE_OUT_OF_MEMORY;
461 }
462
463 switch(conn_config->version) {
464 case CURL_SSLVERSION_DEFAULT:
465 case CURL_SSLVERSION_TLSv1:
466#if LIBWOLFSSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
467 /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is
468 * whatever minimum version of TLS was built in and at least TLS 1.0. For
469 * later library versions that could change (eg TLS 1.0 built in but
470 * defaults to TLS 1.1) so we have this short circuit evaluation to find
471 * the minimum supported TLS version.
472 */
473 if((wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1) != 1) &&
474 (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_1) != 1) &&
475 (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_2) != 1)
476#ifdef WOLFSSL_TLS13
477 && (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_3) != 1)
478#endif
479 ) {
480 failf(data, "SSL: couldn't set the minimum protocol version");
481 return CURLE_SSL_CONNECT_ERROR;
482 }
483#endif
484 default:
485 break;
486 }
487
488 ciphers = conn_config->cipher_list;
489 if(ciphers) {
490 if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
491 failf(data, "failed setting cipher list: %s", ciphers);
492 return CURLE_SSL_CIPHER;
493 }
494 infof(data, "Cipher selection: %s", ciphers);
495 }
496
497 curves = conn_config->curves;
498 if(curves) {
499
500#ifdef HAVE_LIBOQS
501 for(idx = 0; gnm[idx].name != NULL; idx++) {
502 if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) {
503 oqsAlg = gnm[idx].group;
504 break;
505 }
506 }
507
508 if(oqsAlg == 0)
509#endif
510 {
511 if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) {
512 failf(data, "failed setting curves list: '%s'", curves);
513 return CURLE_SSL_CIPHER;
514 }
515 }
516 }
517
518#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS)
519 /* load native CA certificates */
520 if(ssl_config->native_ca_store) {
521 if(wolfSSL_CTX_load_system_CA_certs(backend->ctx) != WOLFSSL_SUCCESS) {
522 infof(data, "error importing native CA store, continuing anyway");
523 }
524 else {
525 imported_native_ca = true;
526 infof(data, "successfully imported native CA store");
527 }
528 }
529#endif /* !NO_FILESYSTEM */
530
531 /* load certificate blob */
532 if(ca_info_blob) {
533 if(wolfSSL_CTX_load_verify_buffer(backend->ctx, ca_info_blob->data,
534 ca_info_blob->len,
535 SSL_FILETYPE_PEM) != SSL_SUCCESS) {
536 if(imported_native_ca) {
537 infof(data, "error importing CA certificate blob, continuing anyway");
538 }
539 else {
540 failf(data, "error importing CA certificate blob");
541 return CURLE_SSL_CACERT_BADFILE;
542 }
543 }
544 else {
545 imported_ca_info_blob = true;
546 infof(data, "successfully imported CA certificate blob");
547 }
548 }
549
550#ifndef NO_FILESYSTEM
551 /* load trusted cacert from file if not blob */
552 if(ssl_cafile || ssl_capath) {
553 int rc =
554 wolfSSL_CTX_load_verify_locations_ex(backend->ctx,
555 ssl_cafile,
556 ssl_capath,
557 WOLFSSL_LOAD_FLAG_IGNORE_ERR);
558 if(SSL_SUCCESS != rc) {
559 if(conn_config->verifypeer && !imported_ca_info_blob &&
560 !imported_native_ca) {
561 /* Fail if we insist on successfully verifying the server. */
562 failf(data, "error setting certificate verify locations:"
563 " CAfile: %s CApath: %s",
564 ssl_cafile ? ssl_cafile : "none",
565 ssl_capath ? ssl_capath : "none");
566 return CURLE_SSL_CACERT_BADFILE;
567 }
568 else {
569 /* Just continue with a warning if no strict certificate
570 verification is required. */
571 infof(data, "error setting certificate verify locations,"
572 " continuing anyway:");
573 }
574 }
575 else {
576 /* Everything is fine. */
577 infof(data, "successfully set certificate verify locations:");
578 }
579 infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
580 infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
581 }
582
583 /* Load the client certificate, and private key */
584 if(ssl_config->primary.clientcert && ssl_config->key) {
585 int file_type = do_file_type(ssl_config->cert_type);
586
587 if(file_type == WOLFSSL_FILETYPE_PEM) {
588 if(wolfSSL_CTX_use_certificate_chain_file(backend->ctx,
589 ssl_config->primary.clientcert)
590 != 1) {
591 failf(data, "unable to use client certificate");
592 return CURLE_SSL_CONNECT_ERROR;
593 }
594 }
595 else if(file_type == WOLFSSL_FILETYPE_ASN1) {
596 if(wolfSSL_CTX_use_certificate_file(backend->ctx,
597 ssl_config->primary.clientcert,
598 file_type) != 1) {
599 failf(data, "unable to use client certificate");
600 return CURLE_SSL_CONNECT_ERROR;
601 }
602 }
603 else {
604 failf(data, "unknown cert type");
605 return CURLE_BAD_FUNCTION_ARGUMENT;
606 }
607
608 file_type = do_file_type(ssl_config->key_type);
609 if(wolfSSL_CTX_use_PrivateKey_file(backend->ctx, ssl_config->key,
610 file_type) != 1) {
611 failf(data, "unable to set private key");
612 return CURLE_SSL_CONNECT_ERROR;
613 }
614 }
615#endif /* !NO_FILESYSTEM */
616
617 /* SSL always tries to verify the peer, this only says whether it should
618 * fail to connect if the verification fails, or if it should continue
619 * anyway. In the latter case the result of the verification is checked with
620 * SSL_get_verify_result() below. */
621 wolfSSL_CTX_set_verify(backend->ctx,
622 conn_config->verifypeer?SSL_VERIFY_PEER:
623 SSL_VERIFY_NONE, NULL);
624
625#ifdef HAVE_SNI
626 if(sni && connssl->peer.sni) {
627 size_t sni_len = strlen(connssl->peer.sni);
628 if((sni_len < USHRT_MAX)) {
629 if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME,
630 connssl->peer.sni,
631 (unsigned short)sni_len) != 1) {
632 failf(data, "Failed to set SNI");
633 return CURLE_SSL_CONNECT_ERROR;
634 }
635 }
636 }
637#endif
638
639 /* give application a chance to interfere with SSL set up. */
640 if(data->set.ssl.fsslctx) {
641 CURLcode result = (*data->set.ssl.fsslctx)(data, backend->ctx,
642 data->set.ssl.fsslctxp);
643 if(result) {
644 failf(data, "error signaled by ssl ctx callback");
645 return result;
646 }
647 }
648#ifdef NO_FILESYSTEM
649 else if(conn_config->verifypeer) {
650 failf(data, "SSL: Certificates can't be loaded because wolfSSL was built"
651 " with \"no filesystem\". Either disable peer verification"
652 " (insecure) or if you are building an application with libcurl you"
653 " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
654 return CURLE_SSL_CONNECT_ERROR;
655 }
656#endif
657
658 /* Let's make an SSL structure */
659 if(backend->handle)
660 wolfSSL_free(backend->handle);
661 backend->handle = wolfSSL_new(backend->ctx);
662 if(!backend->handle) {
663 failf(data, "SSL: couldn't create a handle");
664 return CURLE_OUT_OF_MEMORY;
665 }
666
667#ifdef HAVE_LIBOQS
668 if(oqsAlg) {
669 if(wolfSSL_UseKeyShare(backend->handle, oqsAlg) != WOLFSSL_SUCCESS) {
670 failf(data, "unable to use oqs KEM");
671 }
672 }
673#endif
674
675#ifdef HAVE_ALPN
676 if(connssl->alpn) {
677 struct alpn_proto_buf proto;
678 CURLcode result;
679
680 result = Curl_alpn_to_proto_str(&proto, connssl->alpn);
681 if(result ||
682 wolfSSL_UseALPN(backend->handle, (char *)proto.data, proto.len,
683 WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
684 failf(data, "SSL: failed setting ALPN protocols");
685 return CURLE_SSL_CONNECT_ERROR;
686 }
687 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
688 }
689#endif /* HAVE_ALPN */
690
691#ifdef OPENSSL_EXTRA
692 if(Curl_tls_keylog_enabled()) {
693 /* Ensure the Client Random is preserved. */
694 wolfSSL_KeepArrays(backend->handle);
695#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
696 wolfSSL_set_tls13_secret_cb(backend->handle,
697 wolfssl_tls13_secret_callback, NULL);
698#endif
699 }
700#endif /* OPENSSL_EXTRA */
701
702#ifdef HAVE_SECURE_RENEGOTIATION
703 if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) {
704 failf(data, "SSL: failed setting secure renegotiation");
705 return CURLE_SSL_CONNECT_ERROR;
706 }
707#endif /* HAVE_SECURE_RENEGOTIATION */
708
709 /* Check if there's a cached ID we can/should use here! */
710 if(ssl_config->primary.sessionid) {
711 void *ssl_sessionid = NULL;
712
713 Curl_ssl_sessionid_lock(data);
714 if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
715 /* we got a session id, use it! */
716 if(!SSL_set_session(backend->handle, ssl_sessionid)) {
717 Curl_ssl_delsessionid(data, ssl_sessionid);
718 infof(data, "Can't use session ID, going on without");
719 }
720 else
721 infof(data, "SSL reusing session ID");
722 }
723 Curl_ssl_sessionid_unlock(data);
724 }
725
726#ifdef USE_BIO_CHAIN
727 {
728 WOLFSSL_BIO *bio;
729
730 bio = BIO_new(wolfssl_bio_cf_method);
731 if(!bio)
732 return CURLE_OUT_OF_MEMORY;
733
734 wolfSSL_BIO_set_data(bio, cf);
735 wolfSSL_set_bio(backend->handle, bio, bio);
736 }
737#else /* USE_BIO_CHAIN */
738 /* pass the raw socket into the SSL layer */
739 if(!wolfSSL_set_fd(backend->handle,
740 (int)Curl_conn_cf_get_socket(cf, data))) {
741 failf(data, "SSL: SSL_set_fd failed");
742 return CURLE_SSL_CONNECT_ERROR;
743 }
744#endif /* !USE_BIO_CHAIN */
745
746 connssl->connecting_state = ssl_connect_2;
747 return CURLE_OK;
748}
749
750
751static CURLcode
752wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
753{
754 int ret = -1;
755 struct ssl_connect_data *connssl = cf->ctx;
756 struct wolfssl_ssl_backend_data *backend =
757 (struct wolfssl_ssl_backend_data *)connssl->backend;
758 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
759 const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
760 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
761 data->set.str[STRING_SSL_PINNEDPUBLICKEY];
762
763 DEBUGASSERT(backend);
764
765 wolfSSL_ERR_clear_error();
766
767 /* Enable RFC2818 checks */
768 if(conn_config->verifyhost) {
769 char *snihost = connssl->peer.sni?
770 connssl->peer.sni : connssl->peer.hostname;
771 if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE)
772 return CURLE_SSL_CONNECT_ERROR;
773 }
774
775 ret = wolfSSL_connect(backend->handle);
776
777#ifdef OPENSSL_EXTRA
778 if(Curl_tls_keylog_enabled()) {
779 /* If key logging is enabled, wait for the handshake to complete and then
780 * proceed with logging secrets (for TLS 1.2 or older).
781 *
782 * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
783 * for the server response. At that point the master secret is not yet
784 * available, so we must not try to read it.
785 * To log the secret on completion with a handshake failure, detect
786 * completion via the observation that there is nothing to read or write.
787 * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
788 * changes, the worst case is that no key is logged on error.
789 */
790 if(ret == SSL_SUCCESS ||
791 (!wolfSSL_want_read(backend->handle) &&
792 !wolfSSL_want_write(backend->handle))) {
793 wolfssl_log_tls12_secret(backend->handle);
794 /* Client Random and master secrets are no longer needed, erase these.
795 * Ignored while the handshake is still in progress. */
796 wolfSSL_FreeArrays(backend->handle);
797 }
798 }
799#endif /* OPENSSL_EXTRA */
800
801 if(ret != 1) {
802 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
803 int detail = wolfSSL_get_error(backend->handle, ret);
804
805 if(SSL_ERROR_WANT_READ == detail) {
806 connssl->connecting_state = ssl_connect_2_reading;
807 return CURLE_OK;
808 }
809 else if(SSL_ERROR_WANT_WRITE == detail) {
810 connssl->connecting_state = ssl_connect_2_writing;
811 return CURLE_OK;
812 }
813 /* There is no easy way to override only the CN matching.
814 * This will enable the override of both mismatching SubjectAltNames
815 * as also mismatching CN fields */
816 else if(DOMAIN_NAME_MISMATCH == detail) {
817#if 1
818 failf(data, " subject alt name(s) or common name do not match \"%s\"",
819 connssl->peer.dispname);
820 return CURLE_PEER_FAILED_VERIFICATION;
821#else
822 /* When the wolfssl_check_domain_name() is used and you desire to
823 * continue on a DOMAIN_NAME_MISMATCH, i.e. 'ssl_config.verifyhost
824 * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
825 * error. The only way to do this is currently to switch the
826 * Wolfssl_check_domain_name() in and out based on the
827 * 'ssl_config.verifyhost' value. */
828 if(conn_config->verifyhost) {
829 failf(data,
830 " subject alt name(s) or common name do not match \"%s\"\n",
831 connssl->dispname);
832 return CURLE_PEER_FAILED_VERIFICATION;
833 }
834 else {
835 infof(data,
836 " subject alt name(s) and/or common name do not match \"%s\"",
837 connssl->dispname);
838 return CURLE_OK;
839 }
840#endif
841 }
842#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
843 else if(ASN_NO_SIGNER_E == detail) {
844 if(conn_config->verifypeer) {
845 failf(data, " CA signer not available for verification");
846 return CURLE_SSL_CACERT_BADFILE;
847 }
848 else {
849 /* Just continue with a warning if no strict certificate
850 verification is required. */
851 infof(data, "CA signer not available for verification, "
852 "continuing anyway");
853 }
854 }
855#endif
856 else if(backend->io_result == CURLE_AGAIN) {
857 return CURLE_OK;
858 }
859 else {
860 failf(data, "SSL_connect failed with error %d: %s", detail,
861 wolfSSL_ERR_error_string(detail, error_buffer));
862 return CURLE_SSL_CONNECT_ERROR;
863 }
864 }
865
866 if(pinnedpubkey) {
867#ifdef KEEP_PEER_CERT
868 X509 *x509;
869 const char *x509_der;
870 int x509_der_len;
871 struct Curl_X509certificate x509_parsed;
872 struct Curl_asn1Element *pubkey;
873 CURLcode result;
874
875 x509 = wolfSSL_get_peer_certificate(backend->handle);
876 if(!x509) {
877 failf(data, "SSL: failed retrieving server certificate");
878 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
879 }
880
881 x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
882 if(!x509_der) {
883 failf(data, "SSL: failed retrieving ASN.1 server certificate");
884 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
885 }
886
887 memset(&x509_parsed, 0, sizeof(x509_parsed));
888 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
889 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
890
891 pubkey = &x509_parsed.subjectPublicKeyInfo;
892 if(!pubkey->header || pubkey->end <= pubkey->header) {
893 failf(data, "SSL: failed retrieving public key from server certificate");
894 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
895 }
896
897 result = Curl_pin_peer_pubkey(data,
898 pinnedpubkey,
899 (const unsigned char *)pubkey->header,
900 (size_t)(pubkey->end - pubkey->header));
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 if(!connssl->peer_closed)
1064 (void)wolfSSL_shutdown(backend->handle);
1065 wolfSSL_free(backend->handle);
1066 backend->handle = NULL;
1067 }
1068 if(backend->ctx) {
1069 wolfSSL_CTX_free(backend->ctx);
1070 backend->ctx = NULL;
1071 }
1072}
1073
1074static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
1075 struct Curl_easy *data,
1076 char *buf, size_t blen,
1077 CURLcode *curlcode)
1078{
1079 struct ssl_connect_data *connssl = cf->ctx;
1080 struct wolfssl_ssl_backend_data *backend =
1081 (struct wolfssl_ssl_backend_data *)connssl->backend;
1082 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
1083 int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen;
1084 int nread;
1085
1086 DEBUGASSERT(backend);
1087
1088 wolfSSL_ERR_clear_error();
1089 *curlcode = CURLE_OK;
1090
1091 nread = wolfSSL_read(backend->handle, buf, buffsize);
1092
1093 if(nread <= 0) {
1094 int err = wolfSSL_get_error(backend->handle, nread);
1095
1096 switch(err) {
1097 case SSL_ERROR_ZERO_RETURN: /* no more data */
1098 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1099 *curlcode = CURLE_OK;
1100 return 0;
1101 case SSL_ERROR_NONE:
1102 case SSL_ERROR_WANT_READ:
1103 case SSL_ERROR_WANT_WRITE:
1104 /* there's data pending, re-invoke wolfSSL_read() */
1105 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
1106 *curlcode = CURLE_AGAIN;
1107 return -1;
1108 default:
1109 if(backend->io_result == CURLE_AGAIN) {
1110 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
1111 *curlcode = CURLE_AGAIN;
1112 return -1;
1113 }
1114 failf(data, "SSL read: %s, errno %d",
1115 wolfSSL_ERR_error_string(err, error_buffer), SOCKERRNO);
1116 *curlcode = CURLE_RECV_ERROR;
1117 return -1;
1118 }
1119 }
1120 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread);
1121 return nread;
1122}
1123
1124
1125static void wolfssl_session_free(void *ptr)
1126{
1127 wolfSSL_SESSION_free(ptr);
1128}
1129
1130
1131static size_t wolfssl_version(char *buffer, size_t size)
1132{
1133#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
1134 return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
1135#elif defined(WOLFSSL_VERSION)
1136 return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
1137#endif
1138}
1139
1140
1141static int wolfssl_init(void)
1142{
1143 int ret;
1144
1145#ifdef OPENSSL_EXTRA
1146 Curl_tls_keylog_open();
1147#endif
1148 ret = (wolfSSL_Init() == SSL_SUCCESS);
1149 wolfssl_bio_cf_init_methods();
1150 return ret;
1151}
1152
1153
1154static void wolfssl_cleanup(void)
1155{
1156 wolfssl_bio_cf_free_methods();
1157 wolfSSL_Cleanup();
1158#ifdef OPENSSL_EXTRA
1159 Curl_tls_keylog_close();
1160#endif
1161}
1162
1163
1164static bool wolfssl_data_pending(struct Curl_cfilter *cf,
1165 const struct Curl_easy *data)
1166{
1167 struct ssl_connect_data *ctx = cf->ctx;
1168 struct wolfssl_ssl_backend_data *backend;
1169
1170 (void)data;
1171 DEBUGASSERT(ctx && ctx->backend);
1172
1173 backend = (struct wolfssl_ssl_backend_data *)ctx->backend;
1174 if(backend->handle) /* SSL is in use */
1175 return (0 != wolfSSL_pending(backend->handle)) ? TRUE : FALSE;
1176 else
1177 return FALSE;
1178}
1179
1180
1181/*
1182 * This function is called to shut down the SSL layer but keep the
1183 * socket open (CCC - Clear Command Channel)
1184 */
1185static int wolfssl_shutdown(struct Curl_cfilter *cf,
1186 struct Curl_easy *data)
1187{
1188 struct ssl_connect_data *ctx = cf->ctx;
1189 struct wolfssl_ssl_backend_data *backend;
1190 int retval = 0;
1191
1192 (void)data;
1193 DEBUGASSERT(ctx && ctx->backend);
1194
1195 backend = (struct wolfssl_ssl_backend_data *)ctx->backend;
1196 if(backend->handle) {
1197 wolfSSL_ERR_clear_error();
1198 wolfSSL_free(backend->handle);
1199 backend->handle = NULL;
1200 }
1201 return retval;
1202}
1203
1204
1205static CURLcode
1206wolfssl_connect_common(struct Curl_cfilter *cf,
1207 struct Curl_easy *data,
1208 bool nonblocking,
1209 bool *done)
1210{
1211 CURLcode result;
1212 struct ssl_connect_data *connssl = cf->ctx;
1213 curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
1214 int what;
1215
1216 /* check if the connection has already been established */
1217 if(ssl_connection_complete == connssl->state) {
1218 *done = TRUE;
1219 return CURLE_OK;
1220 }
1221
1222 if(ssl_connect_1 == connssl->connecting_state) {
1223 /* Find out how much more time we're allowed */
1224 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1225
1226 if(timeout_ms < 0) {
1227 /* no need to continue if time already is up */
1228 failf(data, "SSL connection timeout");
1229 return CURLE_OPERATION_TIMEDOUT;
1230 }
1231
1232 result = wolfssl_connect_step1(cf, data);
1233 if(result)
1234 return result;
1235 }
1236
1237 while(ssl_connect_2 == connssl->connecting_state ||
1238 ssl_connect_2_reading == connssl->connecting_state ||
1239 ssl_connect_2_writing == connssl->connecting_state) {
1240
1241 /* check allowed time left */
1242 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1243
1244 if(timeout_ms < 0) {
1245 /* no need to continue if time already is up */
1246 failf(data, "SSL connection timeout");
1247 return CURLE_OPERATION_TIMEDOUT;
1248 }
1249
1250 /* if ssl is expecting something, check if it's available. */
1251 if(connssl->connecting_state == ssl_connect_2_reading
1252 || connssl->connecting_state == ssl_connect_2_writing) {
1253
1254 curl_socket_t writefd = ssl_connect_2_writing ==
1255 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
1256 curl_socket_t readfd = ssl_connect_2_reading ==
1257 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
1258
1259 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
1260 nonblocking?0:timeout_ms);
1261 if(what < 0) {
1262 /* fatal error */
1263 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1264 return CURLE_SSL_CONNECT_ERROR;
1265 }
1266 else if(0 == what) {
1267 if(nonblocking) {
1268 *done = FALSE;
1269 return CURLE_OK;
1270 }
1271 else {
1272 /* timeout */
1273 failf(data, "SSL connection timeout");
1274 return CURLE_OPERATION_TIMEDOUT;
1275 }
1276 }
1277 /* socket is readable or writable */
1278 }
1279
1280 /* Run transaction, and return to the caller if it failed or if
1281 * this connection is part of a multi handle and this loop would
1282 * execute again. This permits the owner of a multi handle to
1283 * abort a connection attempt before step2 has completed while
1284 * ensuring that a client using select() or epoll() will always
1285 * have a valid fdset to wait on.
1286 */
1287 result = wolfssl_connect_step2(cf, data);
1288 if(result || (nonblocking &&
1289 (ssl_connect_2 == connssl->connecting_state ||
1290 ssl_connect_2_reading == connssl->connecting_state ||
1291 ssl_connect_2_writing == connssl->connecting_state)))
1292 return result;
1293 } /* repeat step2 until all transactions are done. */
1294
1295 if(ssl_connect_3 == connssl->connecting_state) {
1296 result = wolfssl_connect_step3(cf, data);
1297 if(result)
1298 return result;
1299 }
1300
1301 if(ssl_connect_done == connssl->connecting_state) {
1302 connssl->state = ssl_connection_complete;
1303 *done = TRUE;
1304 }
1305 else
1306 *done = FALSE;
1307
1308 /* Reset our connect state machine */
1309 connssl->connecting_state = ssl_connect_1;
1310
1311 return CURLE_OK;
1312}
1313
1314
1315static CURLcode wolfssl_connect_nonblocking(struct Curl_cfilter *cf,
1316 struct Curl_easy *data,
1317 bool *done)
1318{
1319 return wolfssl_connect_common(cf, data, TRUE, done);
1320}
1321
1322
1323static CURLcode wolfssl_connect(struct Curl_cfilter *cf,
1324 struct Curl_easy *data)
1325{
1326 CURLcode result;
1327 bool done = FALSE;
1328
1329 result = wolfssl_connect_common(cf, data, FALSE, &done);
1330 if(result)
1331 return result;
1332
1333 DEBUGASSERT(done);
1334
1335 return CURLE_OK;
1336}
1337
1338static CURLcode wolfssl_random(struct Curl_easy *data,
1339 unsigned char *entropy, size_t length)
1340{
1341 WC_RNG rng;
1342 (void)data;
1343 if(wc_InitRng(&rng))
1344 return CURLE_FAILED_INIT;
1345 if(length > UINT_MAX)
1346 return CURLE_FAILED_INIT;
1347 if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
1348 return CURLE_FAILED_INIT;
1349 if(wc_FreeRng(&rng))
1350 return CURLE_FAILED_INIT;
1351 return CURLE_OK;
1352}
1353
1354static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
1355 size_t tmplen,
1356 unsigned char *sha256sum /* output */,
1357 size_t unused)
1358{
1359 wc_Sha256 SHA256pw;
1360 (void)unused;
1361 if(wc_InitSha256(&SHA256pw))
1362 return CURLE_FAILED_INIT;
1363 wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
1364 wc_Sha256Final(&SHA256pw, sha256sum);
1365 return CURLE_OK;
1366}
1367
1368static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
1369 CURLINFO info UNUSED_PARAM)
1370{
1371 struct wolfssl_ssl_backend_data *backend =
1372 (struct wolfssl_ssl_backend_data *)connssl->backend;
1373 (void)info;
1374 DEBUGASSERT(backend);
1375 return backend->handle;
1376}
1377
1378const struct Curl_ssl Curl_ssl_wolfssl = {
1379 { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
1380
1381#ifdef KEEP_PEER_CERT
1382 SSLSUPP_PINNEDPUBKEY |
1383#endif
1384#ifdef USE_BIO_CHAIN
1385 SSLSUPP_HTTPS_PROXY |
1386#endif
1387 SSLSUPP_CA_PATH |
1388 SSLSUPP_CAINFO_BLOB |
1389 SSLSUPP_SSL_CTX,
1390
1391 sizeof(struct wolfssl_ssl_backend_data),
1392
1393 wolfssl_init, /* init */
1394 wolfssl_cleanup, /* cleanup */
1395 wolfssl_version, /* version */
1396 Curl_none_check_cxn, /* check_cxn */
1397 wolfssl_shutdown, /* shutdown */
1398 wolfssl_data_pending, /* data_pending */
1399 wolfssl_random, /* random */
1400 Curl_none_cert_status_request, /* cert_status_request */
1401 wolfssl_connect, /* connect */
1402 wolfssl_connect_nonblocking, /* connect_nonblocking */
1403 Curl_ssl_adjust_pollset, /* adjust_pollset */
1404 wolfssl_get_internals, /* get_internals */
1405 wolfssl_close, /* close_one */
1406 Curl_none_close_all, /* close_all */
1407 wolfssl_session_free, /* session_free */
1408 Curl_none_set_engine, /* set_engine */
1409 Curl_none_set_engine_default, /* set_engine_default */
1410 Curl_none_engines_list, /* engines_list */
1411 Curl_none_false_start, /* false_start */
1412 wolfssl_sha256sum, /* sha256sum */
1413 NULL, /* associate_connection */
1414 NULL, /* disassociate_connection */
1415 NULL, /* free_multi_ssl_backend_data */
1416 wolfssl_recv, /* recv decrypted data */
1417 wolfssl_send, /* send data to encrypt */
1418};
1419
1420#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette