VirtualBox

source: vbox/trunk/src/libs/curl-8.0.1/lib/vtls/wolfssl.c@ 100347

Last change on this file since 100347 was 99344, checked in by vboxsync, 2 years ago

curl-8.0.1: Applied and adjusted our curl changes to 7.87.0 bugref:10417

  • Property svn:eol-style set to native
File size: 39.9 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 ssl_backend_data {
95 SSL_CTX* ctx;
96 SSL* 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(SSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) != SSL_SUCCESS) {
184 return;
185 }
186
187 /* Check for a missing master secret and skip logging. That can happen if
188 * curl rejects the server certificate and aborts the handshake.
189 */
190 for(i = 0; i < msLen; i++) {
191 x |= ms[i];
192 }
193 if(x == 0) {
194 return;
195 }
196
197 Curl_tls_keylog_write("CLIENT_RANDOM", cr, ms, msLen);
198}
199#endif /* OPENSSL_EXTRA */
200
201static int do_file_type(const char *type)
202{
203 if(!type || !type[0])
204 return SSL_FILETYPE_PEM;
205 if(strcasecompare(type, "PEM"))
206 return SSL_FILETYPE_PEM;
207 if(strcasecompare(type, "DER"))
208 return SSL_FILETYPE_ASN1;
209 return -1;
210}
211
212#ifdef HAVE_LIBOQS
213struct group_name_map {
214 const word16 group;
215 const char *name;
216};
217
218static const struct group_name_map gnm[] = {
219 { WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" },
220 { WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" },
221 { WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" },
222 { WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" },
223 { WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" },
224 { WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" },
225 { 0, NULL }
226};
227#endif
228
229#ifdef USE_BIO_CHAIN
230
231static int bio_cf_create(WOLFSSL_BIO *bio)
232{
233 wolfSSL_BIO_set_shutdown(bio, 1);
234 wolfSSL_BIO_set_init(bio, 1);
235 wolfSSL_BIO_set_data(bio, NULL);
236 return 1;
237}
238
239static int bio_cf_destroy(WOLFSSL_BIO *bio)
240{
241 if(!bio)
242 return 0;
243 return 1;
244}
245
246static long 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 bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen)
281{
282 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
283 struct ssl_connect_data *connssl = cf->ctx;
284 struct Curl_easy *data = CF_DATA_CURRENT(cf);
285 ssize_t nwritten;
286 CURLcode result = CURLE_OK;
287
288 DEBUGASSERT(data);
289 nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
290 connssl->backend->io_result = result;
291 DEBUGF(LOG_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
292 blen, nwritten, result));
293 wolfSSL_BIO_clear_retry_flags(bio);
294 if(nwritten < 0 && CURLE_AGAIN == result)
295 BIO_set_retry_read(bio);
296 return (int)nwritten;
297}
298
299static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
300{
301 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
302 struct ssl_connect_data *connssl = cf->ctx;
303 struct Curl_easy *data = CF_DATA_CURRENT(cf);
304 ssize_t nread;
305 CURLcode result = CURLE_OK;
306
307 DEBUGASSERT(data);
308 /* OpenSSL catches this case, so should we. */
309 if(!buf)
310 return 0;
311
312 nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
313 connssl->backend->io_result = result;
314 DEBUGF(LOG_CF(data, cf, "bio_read(len=%d) -> %zd, %d",
315 blen, nread, result));
316 wolfSSL_BIO_clear_retry_flags(bio);
317 if(nread < 0 && CURLE_AGAIN == result)
318 BIO_set_retry_read(bio);
319 return (int)nread;
320}
321
322static WOLFSSL_BIO_METHOD *bio_cf_method = NULL;
323
324static void bio_cf_init_methods(void)
325{
326 bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO");
327 wolfSSL_BIO_meth_set_write(bio_cf_method, &bio_cf_out_write);
328 wolfSSL_BIO_meth_set_read(bio_cf_method, &bio_cf_in_read);
329 wolfSSL_BIO_meth_set_ctrl(bio_cf_method, &bio_cf_ctrl);
330 wolfSSL_BIO_meth_set_create(bio_cf_method, &bio_cf_create);
331 wolfSSL_BIO_meth_set_destroy(bio_cf_method, &bio_cf_destroy);
332}
333
334static void bio_cf_free_methods(void)
335{
336 wolfSSL_BIO_meth_free(bio_cf_method);
337}
338
339#else /* USE_BIO_CHAIN */
340
341#define bio_cf_init_methods() Curl_nop_stmt
342#define bio_cf_free_methods() Curl_nop_stmt
343
344#endif /* !USE_BIO_CHAIN */
345
346/*
347 * This function loads all the client/CA certificates and CRLs. Setup the TLS
348 * layer and do all necessary magic.
349 */
350static CURLcode
351wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
352{
353 char *ciphers, *curves;
354 struct ssl_connect_data *connssl = cf->ctx;
355 struct ssl_backend_data *backend = connssl->backend;
356 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
357 const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
358 SSL_METHOD* req_method = NULL;
359#ifdef HAVE_LIBOQS
360 word16 oqsAlg = 0;
361 size_t idx = 0;
362#endif
363#ifdef HAVE_SNI
364 bool sni = FALSE;
365#define use_sni(x) sni = (x)
366#else
367#define use_sni(x) Curl_nop_stmt
368#endif
369
370 DEBUGASSERT(backend);
371
372 if(connssl->state == ssl_connection_complete)
373 return CURLE_OK;
374
375 if(conn_config->version_max != CURL_SSLVERSION_MAX_NONE) {
376 failf(data, "wolfSSL does not support to set maximum SSL/TLS version");
377 return CURLE_SSL_CONNECT_ERROR;
378 }
379
380 /* check to see if we've been told to use an explicit SSL/TLS version */
381 switch(conn_config->version) {
382 case CURL_SSLVERSION_DEFAULT:
383 case CURL_SSLVERSION_TLSv1:
384#if LIBWOLFSSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
385 /* minimum protocol version is set later after the CTX object is created */
386 req_method = SSLv23_client_method();
387#else
388 infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
389 "TLS 1.0 is used exclusively");
390 req_method = TLSv1_client_method();
391#endif
392 use_sni(TRUE);
393 break;
394 case CURL_SSLVERSION_TLSv1_0:
395#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
396 req_method = TLSv1_client_method();
397 use_sni(TRUE);
398#else
399 failf(data, "wolfSSL does not support TLS 1.0");
400 return CURLE_NOT_BUILT_IN;
401#endif
402 break;
403 case CURL_SSLVERSION_TLSv1_1:
404#ifndef NO_OLD_TLS
405 req_method = TLSv1_1_client_method();
406 use_sni(TRUE);
407#else
408 failf(data, "wolfSSL does not support TLS 1.1");
409 return CURLE_NOT_BUILT_IN;
410#endif
411 break;
412 case CURL_SSLVERSION_TLSv1_2:
413 req_method = TLSv1_2_client_method();
414 use_sni(TRUE);
415 break;
416 case CURL_SSLVERSION_TLSv1_3:
417#ifdef WOLFSSL_TLS13
418 req_method = wolfTLSv1_3_client_method();
419 use_sni(TRUE);
420 break;
421#else
422 failf(data, "wolfSSL: TLS 1.3 is not yet supported");
423 return CURLE_SSL_CONNECT_ERROR;
424#endif
425 default:
426 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
427 return CURLE_SSL_CONNECT_ERROR;
428 }
429
430 if(!req_method) {
431 failf(data, "SSL: couldn't create a method");
432 return CURLE_OUT_OF_MEMORY;
433 }
434
435 if(backend->ctx)
436 SSL_CTX_free(backend->ctx);
437 backend->ctx = SSL_CTX_new(req_method);
438
439 if(!backend->ctx) {
440 failf(data, "SSL: couldn't create a context");
441 return CURLE_OUT_OF_MEMORY;
442 }
443
444 switch(conn_config->version) {
445 case CURL_SSLVERSION_DEFAULT:
446 case CURL_SSLVERSION_TLSv1:
447#if LIBWOLFSSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
448 /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is
449 * whatever minimum version of TLS was built in and at least TLS 1.0. For
450 * later library versions that could change (eg TLS 1.0 built in but
451 * defaults to TLS 1.1) so we have this short circuit evaluation to find
452 * the minimum supported TLS version.
453 */
454 if((wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1) != 1) &&
455 (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_1) != 1) &&
456 (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_2) != 1)
457#ifdef WOLFSSL_TLS13
458 && (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_3) != 1)
459#endif
460 ) {
461 failf(data, "SSL: couldn't set the minimum protocol version");
462 return CURLE_SSL_CONNECT_ERROR;
463 }
464#endif
465 break;
466 }
467
468 ciphers = conn_config->cipher_list;
469 if(ciphers) {
470 if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
471 failf(data, "failed setting cipher list: %s", ciphers);
472 return CURLE_SSL_CIPHER;
473 }
474 infof(data, "Cipher selection: %s", ciphers);
475 }
476
477 curves = conn_config->curves;
478 if(curves) {
479
480#ifdef HAVE_LIBOQS
481 for(idx = 0; gnm[idx].name != NULL; idx++) {
482 if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) {
483 oqsAlg = gnm[idx].group;
484 break;
485 }
486 }
487
488 if(oqsAlg == 0)
489#endif
490 {
491 if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) {
492 failf(data, "failed setting curves list: '%s'", curves);
493 return CURLE_SSL_CIPHER;
494 }
495 }
496 }
497#ifndef NO_FILESYSTEM
498 /* load trusted cacert */
499 if(conn_config->CAfile) {
500 if(1 != SSL_CTX_load_verify_locations(backend->ctx,
501 conn_config->CAfile,
502 conn_config->CApath)) {
503 if(conn_config->verifypeer) {
504 /* Fail if we insist on successfully verifying the server. */
505 failf(data, "error setting certificate verify locations:"
506 " CAfile: %s CApath: %s",
507 conn_config->CAfile?
508 conn_config->CAfile: "none",
509 conn_config->CApath?
510 conn_config->CApath : "none");
511 return CURLE_SSL_CACERT_BADFILE;
512 }
513 else {
514 /* Just continue with a warning if no strict certificate
515 verification is required. */
516 infof(data, "error setting certificate verify locations,"
517 " continuing anyway:");
518 }
519 }
520 else {
521 /* Everything is fine. */
522 infof(data, "successfully set certificate verify locations:");
523 }
524 infof(data, " CAfile: %s",
525 conn_config->CAfile ? conn_config->CAfile : "none");
526 infof(data, " CApath: %s",
527 conn_config->CApath ? conn_config->CApath : "none");
528 }
529
530 /* Load the client certificate, and private key */
531 if(ssl_config->primary.clientcert && ssl_config->key) {
532 int file_type = do_file_type(ssl_config->cert_type);
533
534 if(SSL_CTX_use_certificate_file(backend->ctx,
535 ssl_config->primary.clientcert,
536 file_type) != 1) {
537 failf(data, "unable to use client certificate (no key or wrong pass"
538 " phrase?)");
539 return CURLE_SSL_CONNECT_ERROR;
540 }
541
542 file_type = do_file_type(ssl_config->key_type);
543 if(SSL_CTX_use_PrivateKey_file(backend->ctx, ssl_config->key,
544 file_type) != 1) {
545 failf(data, "unable to set private key");
546 return CURLE_SSL_CONNECT_ERROR;
547 }
548 }
549#endif /* !NO_FILESYSTEM */
550
551 /* SSL always tries to verify the peer, this only says whether it should
552 * fail to connect if the verification fails, or if it should continue
553 * anyway. In the latter case the result of the verification is checked with
554 * SSL_get_verify_result() below. */
555 SSL_CTX_set_verify(backend->ctx,
556 conn_config->verifypeer?SSL_VERIFY_PEER:
557 SSL_VERIFY_NONE,
558 NULL);
559
560#ifdef HAVE_SNI
561 if(sni) {
562 struct in_addr addr4;
563#ifdef ENABLE_IPV6
564 struct in6_addr addr6;
565#endif
566 size_t hostname_len = strlen(connssl->hostname);
567
568 if((hostname_len < USHRT_MAX) &&
569 !Curl_inet_pton(AF_INET, connssl->hostname, &addr4)
570#ifdef ENABLE_IPV6
571 && !Curl_inet_pton(AF_INET6, connssl->hostname, &addr6)
572#endif
573 ) {
574 size_t snilen;
575 char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
576 if(!snihost ||
577 wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, snihost,
578 (unsigned short)snilen) != 1) {
579 failf(data, "Failed to set SNI");
580 return CURLE_SSL_CONNECT_ERROR;
581 }
582 }
583 }
584#endif
585
586 /* give application a chance to interfere with SSL set up. */
587 if(data->set.ssl.fsslctx) {
588 CURLcode result = (*data->set.ssl.fsslctx)(data, backend->ctx,
589 data->set.ssl.fsslctxp);
590 if(result) {
591 failf(data, "error signaled by ssl ctx callback");
592 return result;
593 }
594 }
595#ifdef NO_FILESYSTEM
596 else if(conn_config->verifypeer) {
597 failf(data, "SSL: Certificates can't be loaded because wolfSSL was built"
598 " with \"no filesystem\". Either disable peer verification"
599 " (insecure) or if you are building an application with libcurl you"
600 " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
601 return CURLE_SSL_CONNECT_ERROR;
602 }
603#endif
604
605 /* Let's make an SSL structure */
606 if(backend->handle)
607 SSL_free(backend->handle);
608 backend->handle = SSL_new(backend->ctx);
609 if(!backend->handle) {
610 failf(data, "SSL: couldn't create a handle");
611 return CURLE_OUT_OF_MEMORY;
612 }
613
614#ifdef HAVE_LIBOQS
615 if(oqsAlg) {
616 if(wolfSSL_UseKeyShare(backend->handle, oqsAlg) != WOLFSSL_SUCCESS) {
617 failf(data, "unable to use oqs KEM");
618 }
619 }
620#endif
621
622#ifdef HAVE_ALPN
623 if(connssl->alpn) {
624 struct alpn_proto_buf proto;
625 CURLcode result;
626
627 result = Curl_alpn_to_proto_str(&proto, connssl->alpn);
628 if(result ||
629 wolfSSL_UseALPN(backend->handle, (char *)proto.data, proto.len,
630 WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
631 failf(data, "SSL: failed setting ALPN protocols");
632 return CURLE_SSL_CONNECT_ERROR;
633 }
634 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
635 }
636#endif /* HAVE_ALPN */
637
638#ifdef OPENSSL_EXTRA
639 if(Curl_tls_keylog_enabled()) {
640 /* Ensure the Client Random is preserved. */
641 wolfSSL_KeepArrays(backend->handle);
642#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
643 wolfSSL_set_tls13_secret_cb(backend->handle,
644 wolfssl_tls13_secret_callback, NULL);
645#endif
646 }
647#endif /* OPENSSL_EXTRA */
648
649#ifdef HAVE_SECURE_RENEGOTIATION
650 if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) {
651 failf(data, "SSL: failed setting secure renegotiation");
652 return CURLE_SSL_CONNECT_ERROR;
653 }
654#endif /* HAVE_SECURE_RENEGOTIATION */
655
656 /* Check if there's a cached ID we can/should use here! */
657 if(ssl_config->primary.sessionid) {
658 void *ssl_sessionid = NULL;
659
660 Curl_ssl_sessionid_lock(data);
661 if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
662 /* we got a session id, use it! */
663 if(!SSL_set_session(backend->handle, ssl_sessionid)) {
664 Curl_ssl_delsessionid(data, ssl_sessionid);
665 infof(data, "Can't use session ID, going on without");
666 }
667 else
668 infof(data, "SSL re-using session ID");
669 }
670 Curl_ssl_sessionid_unlock(data);
671 }
672
673#ifdef USE_BIO_CHAIN
674 {
675 WOLFSSL_BIO *bio;
676
677 bio = BIO_new(bio_cf_method);
678 if(!bio)
679 return CURLE_OUT_OF_MEMORY;
680
681 wolfSSL_BIO_set_data(bio, cf);
682 wolfSSL_set_bio(backend->handle, bio, bio);
683 }
684#else /* USE_BIO_CHAIN */
685 /* pass the raw socket into the SSL layer */
686 if(!SSL_set_fd(backend->handle, (int)Curl_conn_cf_get_socket(cf, data))) {
687 failf(data, "SSL: SSL_set_fd failed");
688 return CURLE_SSL_CONNECT_ERROR;
689 }
690#endif /* !USE_BIO_CHAIN */
691
692 connssl->connecting_state = ssl_connect_2;
693 return CURLE_OK;
694}
695
696
697static CURLcode
698wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
699{
700 int ret = -1;
701 struct ssl_connect_data *connssl = cf->ctx;
702 struct ssl_backend_data *backend = connssl->backend;
703 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
704 const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
705 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
706 data->set.str[STRING_SSL_PINNEDPUBLICKEY];
707
708 DEBUGASSERT(backend);
709
710 ERR_clear_error();
711
712 /* Enable RFC2818 checks */
713 if(conn_config->verifyhost) {
714 char *snihost = Curl_ssl_snihost(data, connssl->hostname, NULL);
715 if(!snihost ||
716 (wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE))
717 return CURLE_SSL_CONNECT_ERROR;
718 }
719
720 ret = SSL_connect(backend->handle);
721
722#ifdef OPENSSL_EXTRA
723 if(Curl_tls_keylog_enabled()) {
724 /* If key logging is enabled, wait for the handshake to complete and then
725 * proceed with logging secrets (for TLS 1.2 or older).
726 *
727 * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
728 * for the server response. At that point the master secret is not yet
729 * available, so we must not try to read it.
730 * To log the secret on completion with a handshake failure, detect
731 * completion via the observation that there is nothing to read or write.
732 * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
733 * changes, the worst case is that no key is logged on error.
734 */
735 if(ret == SSL_SUCCESS ||
736 (!wolfSSL_want_read(backend->handle) &&
737 !wolfSSL_want_write(backend->handle))) {
738 wolfssl_log_tls12_secret(backend->handle);
739 /* Client Random and master secrets are no longer needed, erase these.
740 * Ignored while the handshake is still in progress. */
741 wolfSSL_FreeArrays(backend->handle);
742 }
743 }
744#endif /* OPENSSL_EXTRA */
745
746 if(ret != 1) {
747 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
748 int detail = SSL_get_error(backend->handle, ret);
749
750 if(SSL_ERROR_WANT_READ == detail) {
751 connssl->connecting_state = ssl_connect_2_reading;
752 return CURLE_OK;
753 }
754 else if(SSL_ERROR_WANT_WRITE == detail) {
755 connssl->connecting_state = ssl_connect_2_writing;
756 return CURLE_OK;
757 }
758 /* There is no easy way to override only the CN matching.
759 * This will enable the override of both mismatching SubjectAltNames
760 * as also mismatching CN fields */
761 else if(DOMAIN_NAME_MISMATCH == detail) {
762#if 1
763 failf(data, " subject alt name(s) or common name do not match \"%s\"",
764 connssl->dispname);
765 return CURLE_PEER_FAILED_VERIFICATION;
766#else
767 /* When the wolfssl_check_domain_name() is used and you desire to
768 * continue on a DOMAIN_NAME_MISMATCH, i.e. 'ssl_config.verifyhost
769 * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
770 * error. The only way to do this is currently to switch the
771 * Wolfssl_check_domain_name() in and out based on the
772 * 'ssl_config.verifyhost' value. */
773 if(conn_config->verifyhost) {
774 failf(data,
775 " subject alt name(s) or common name do not match \"%s\"\n",
776 connssl->dispname);
777 return CURLE_PEER_FAILED_VERIFICATION;
778 }
779 else {
780 infof(data,
781 " subject alt name(s) and/or common name do not match \"%s\"",
782 connssl->dispname);
783 return CURLE_OK;
784 }
785#endif
786 }
787#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
788 else if(ASN_NO_SIGNER_E == detail) {
789 if(conn_config->verifypeer) {
790 failf(data, " CA signer not available for verification");
791 return CURLE_SSL_CACERT_BADFILE;
792 }
793 else {
794 /* Just continue with a warning if no strict certificate
795 verification is required. */
796 infof(data, "CA signer not available for verification, "
797 "continuing anyway");
798 }
799 }
800#endif
801 else if(backend->io_result == CURLE_AGAIN) {
802 return CURLE_OK;
803 }
804 else {
805 failf(data, "SSL_connect failed with error %d: %s", detail,
806 ERR_error_string(detail, error_buffer));
807 return CURLE_SSL_CONNECT_ERROR;
808 }
809 }
810
811 if(pinnedpubkey) {
812#ifdef KEEP_PEER_CERT
813 X509 *x509;
814 const char *x509_der;
815 int x509_der_len;
816 struct Curl_X509certificate x509_parsed;
817 struct Curl_asn1Element *pubkey;
818 CURLcode result;
819
820 x509 = SSL_get_peer_certificate(backend->handle);
821 if(!x509) {
822 failf(data, "SSL: failed retrieving server certificate");
823 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
824 }
825
826 x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
827 if(!x509_der) {
828 failf(data, "SSL: failed retrieving ASN.1 server certificate");
829 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
830 }
831
832 memset(&x509_parsed, 0, sizeof(x509_parsed));
833 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
834 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
835
836 pubkey = &x509_parsed.subjectPublicKeyInfo;
837 if(!pubkey->header || pubkey->end <= pubkey->header) {
838 failf(data, "SSL: failed retrieving public key from server certificate");
839 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
840 }
841
842 result = Curl_pin_peer_pubkey(data,
843 pinnedpubkey,
844 (const unsigned char *)pubkey->header,
845 (size_t)(pubkey->end - pubkey->header));
846 if(result) {
847 failf(data, "SSL: public key does not match pinned public key");
848 return result;
849 }
850#else
851 failf(data, "Library lacks pinning support built-in");
852 return CURLE_NOT_BUILT_IN;
853#endif
854 }
855
856#ifdef HAVE_ALPN
857 if(cf->conn->bits.tls_enable_alpn) {
858 int rc;
859 char *protocol = NULL;
860 unsigned short protocol_len = 0;
861
862 rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
863
864 if(rc == SSL_SUCCESS) {
865 Curl_alpn_set_negotiated(cf, data, (const unsigned char *)protocol,
866 protocol_len);
867 }
868 else if(rc == SSL_ALPN_NOT_FOUND)
869 Curl_alpn_set_negotiated(cf, data, NULL, 0);
870 else {
871 failf(data, "ALPN, failure getting protocol, error %d", rc);
872 return CURLE_SSL_CONNECT_ERROR;
873 }
874 }
875#endif /* HAVE_ALPN */
876
877 connssl->connecting_state = ssl_connect_3;
878#if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
879 infof(data, "SSL connection using %s / %s",
880 wolfSSL_get_version(backend->handle),
881 wolfSSL_get_cipher_name(backend->handle));
882#else
883 infof(data, "SSL connected");
884#endif
885
886 return CURLE_OK;
887}
888
889
890static CURLcode
891wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
892{
893 CURLcode result = CURLE_OK;
894 struct ssl_connect_data *connssl = cf->ctx;
895 struct ssl_backend_data *backend = connssl->backend;
896 const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
897
898 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
899 DEBUGASSERT(backend);
900
901 if(ssl_config->primary.sessionid) {
902 bool incache;
903 bool added = FALSE;
904 void *old_ssl_sessionid = NULL;
905 /* SSL_get1_session allocates memory that has to be freed. */
906 SSL_SESSION *our_ssl_sessionid = SSL_get1_session(backend->handle);
907
908 if(our_ssl_sessionid) {
909 Curl_ssl_sessionid_lock(data);
910 incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL));
911 if(incache) {
912 if(old_ssl_sessionid != our_ssl_sessionid) {
913 infof(data, "old SSL session ID is stale, removing");
914 Curl_ssl_delsessionid(data, old_ssl_sessionid);
915 incache = FALSE;
916 }
917 }
918
919 if(!incache) {
920 result = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid, 0, NULL);
921 if(result) {
922 Curl_ssl_sessionid_unlock(data);
923 SSL_SESSION_free(our_ssl_sessionid);
924 failf(data, "failed to store ssl session");
925 return result;
926 }
927 else {
928 added = TRUE;
929 }
930 }
931 Curl_ssl_sessionid_unlock(data);
932
933 if(!added) {
934 /* If the session info wasn't added to the cache, free our copy. */
935 SSL_SESSION_free(our_ssl_sessionid);
936 }
937 }
938 }
939
940 connssl->connecting_state = ssl_connect_done;
941
942 return result;
943}
944
945
946static ssize_t wolfssl_send(struct Curl_cfilter *cf,
947 struct Curl_easy *data,
948 const void *mem,
949 size_t len,
950 CURLcode *curlcode)
951{
952 struct ssl_connect_data *connssl = cf->ctx;
953 struct ssl_backend_data *backend = connssl->backend;
954 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
955 int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
956 int rc;
957
958 DEBUGASSERT(backend);
959
960 ERR_clear_error();
961
962 rc = SSL_write(backend->handle, mem, memlen);
963 if(rc <= 0) {
964 int err = SSL_get_error(backend->handle, rc);
965
966 switch(err) {
967 case SSL_ERROR_WANT_READ:
968 case SSL_ERROR_WANT_WRITE:
969 /* there's data pending, re-invoke SSL_write() */
970 DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len));
971 *curlcode = CURLE_AGAIN;
972 return -1;
973 default:
974 if(backend->io_result == CURLE_AGAIN) {
975 DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len));
976 *curlcode = CURLE_AGAIN;
977 return -1;
978 }
979 DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> %d, %d",
980 len, rc, err));
981 failf(data, "SSL write: %s, errno %d",
982 ERR_error_string(err, error_buffer),
983 SOCKERRNO);
984 *curlcode = CURLE_SEND_ERROR;
985 return -1;
986 }
987 }
988 DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> %d", len, rc));
989 return rc;
990}
991
992static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
993{
994 struct ssl_connect_data *connssl = cf->ctx;
995 struct ssl_backend_data *backend = connssl->backend;
996
997 (void) data;
998
999 DEBUGASSERT(backend);
1000
1001 if(backend->handle) {
1002 char buf[32];
1003 /* Maybe the server has already sent a close notify alert.
1004 Read it to avoid an RST on the TCP connection. */
1005 (void)SSL_read(backend->handle, buf, (int)sizeof(buf));
1006 (void)SSL_shutdown(backend->handle);
1007 SSL_free(backend->handle);
1008 backend->handle = NULL;
1009 }
1010 if(backend->ctx) {
1011 SSL_CTX_free(backend->ctx);
1012 backend->ctx = NULL;
1013 }
1014}
1015
1016static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
1017 struct Curl_easy *data,
1018 char *buf, size_t blen,
1019 CURLcode *curlcode)
1020{
1021 struct ssl_connect_data *connssl = cf->ctx;
1022 struct ssl_backend_data *backend = connssl->backend;
1023 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
1024 int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen;
1025 int nread;
1026
1027 DEBUGASSERT(backend);
1028
1029 ERR_clear_error();
1030 *curlcode = CURLE_OK;
1031
1032 nread = SSL_read(backend->handle, buf, buffsize);
1033
1034 if(nread <= 0) {
1035 int err = SSL_get_error(backend->handle, nread);
1036
1037 switch(err) {
1038 case SSL_ERROR_ZERO_RETURN: /* no more data */
1039 DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen));
1040 *curlcode = CURLE_OK;
1041 return 0;
1042 case SSL_ERROR_NONE:
1043 /* FALLTHROUGH */
1044 case SSL_ERROR_WANT_READ:
1045 /* FALLTHROUGH */
1046 case SSL_ERROR_WANT_WRITE:
1047 /* there's data pending, re-invoke SSL_read() */
1048 DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen));
1049 *curlcode = CURLE_AGAIN;
1050 return -1;
1051 default:
1052 if(backend->io_result == CURLE_AGAIN) {
1053 DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen));
1054 *curlcode = CURLE_AGAIN;
1055 return -1;
1056 }
1057 failf(data, "SSL read: %s, errno %d",
1058 ERR_error_string(err, error_buffer), SOCKERRNO);
1059 *curlcode = CURLE_RECV_ERROR;
1060 return -1;
1061 }
1062 }
1063 DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread));
1064 return nread;
1065}
1066
1067
1068static void wolfssl_session_free(void *ptr)
1069{
1070 SSL_SESSION_free(ptr);
1071}
1072
1073
1074static size_t wolfssl_version(char *buffer, size_t size)
1075{
1076#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
1077 return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
1078#elif defined(WOLFSSL_VERSION)
1079 return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
1080#endif
1081}
1082
1083
1084static int wolfssl_init(void)
1085{
1086 int ret;
1087
1088#ifdef OPENSSL_EXTRA
1089 Curl_tls_keylog_open();
1090#endif
1091 ret = (wolfSSL_Init() == SSL_SUCCESS);
1092 bio_cf_init_methods();
1093 return ret;
1094}
1095
1096
1097static void wolfssl_cleanup(void)
1098{
1099 bio_cf_free_methods();
1100 wolfSSL_Cleanup();
1101#ifdef OPENSSL_EXTRA
1102 Curl_tls_keylog_close();
1103#endif
1104}
1105
1106
1107static bool wolfssl_data_pending(struct Curl_cfilter *cf,
1108 const struct Curl_easy *data)
1109{
1110 struct ssl_connect_data *ctx = cf->ctx;
1111
1112 (void)data;
1113 DEBUGASSERT(ctx && ctx->backend);
1114 if(ctx->backend->handle) /* SSL is in use */
1115 return (0 != SSL_pending(ctx->backend->handle)) ? TRUE : FALSE;
1116 else
1117 return FALSE;
1118}
1119
1120
1121/*
1122 * This function is called to shut down the SSL layer but keep the
1123 * socket open (CCC - Clear Command Channel)
1124 */
1125static int wolfssl_shutdown(struct Curl_cfilter *cf,
1126 struct Curl_easy *data)
1127{
1128 struct ssl_connect_data *ctx = cf->ctx;
1129 int retval = 0;
1130
1131 (void)data;
1132 DEBUGASSERT(ctx && ctx->backend);
1133
1134 if(ctx->backend->handle) {
1135 ERR_clear_error();
1136 SSL_free(ctx->backend->handle);
1137 ctx->backend->handle = NULL;
1138 }
1139 return retval;
1140}
1141
1142
1143static CURLcode
1144wolfssl_connect_common(struct Curl_cfilter *cf,
1145 struct Curl_easy *data,
1146 bool nonblocking,
1147 bool *done)
1148{
1149 CURLcode result;
1150 struct ssl_connect_data *connssl = cf->ctx;
1151 curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
1152 int what;
1153
1154 /* check if the connection has already been established */
1155 if(ssl_connection_complete == connssl->state) {
1156 *done = TRUE;
1157 return CURLE_OK;
1158 }
1159
1160 if(ssl_connect_1 == connssl->connecting_state) {
1161 /* Find out how much more time we're allowed */
1162 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1163
1164 if(timeout_ms < 0) {
1165 /* no need to continue if time already is up */
1166 failf(data, "SSL connection timeout");
1167 return CURLE_OPERATION_TIMEDOUT;
1168 }
1169
1170 result = wolfssl_connect_step1(cf, data);
1171 if(result)
1172 return result;
1173 }
1174
1175 while(ssl_connect_2 == connssl->connecting_state ||
1176 ssl_connect_2_reading == connssl->connecting_state ||
1177 ssl_connect_2_writing == connssl->connecting_state) {
1178
1179 /* check allowed time left */
1180 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1181
1182 if(timeout_ms < 0) {
1183 /* no need to continue if time already is up */
1184 failf(data, "SSL connection timeout");
1185 return CURLE_OPERATION_TIMEDOUT;
1186 }
1187
1188 /* if ssl is expecting something, check if it's available. */
1189 if(connssl->connecting_state == ssl_connect_2_reading
1190 || connssl->connecting_state == ssl_connect_2_writing) {
1191
1192 curl_socket_t writefd = ssl_connect_2_writing ==
1193 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
1194 curl_socket_t readfd = ssl_connect_2_reading ==
1195 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
1196
1197 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
1198 nonblocking?0:timeout_ms);
1199 if(what < 0) {
1200 /* fatal error */
1201 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1202 return CURLE_SSL_CONNECT_ERROR;
1203 }
1204 else if(0 == what) {
1205 if(nonblocking) {
1206 *done = FALSE;
1207 return CURLE_OK;
1208 }
1209 else {
1210 /* timeout */
1211 failf(data, "SSL connection timeout");
1212 return CURLE_OPERATION_TIMEDOUT;
1213 }
1214 }
1215 /* socket is readable or writable */
1216 }
1217
1218 /* Run transaction, and return to the caller if it failed or if
1219 * this connection is part of a multi handle and this loop would
1220 * execute again. This permits the owner of a multi handle to
1221 * abort a connection attempt before step2 has completed while
1222 * ensuring that a client using select() or epoll() will always
1223 * have a valid fdset to wait on.
1224 */
1225 result = wolfssl_connect_step2(cf, data);
1226 if(result || (nonblocking &&
1227 (ssl_connect_2 == connssl->connecting_state ||
1228 ssl_connect_2_reading == connssl->connecting_state ||
1229 ssl_connect_2_writing == connssl->connecting_state)))
1230 return result;
1231 } /* repeat step2 until all transactions are done. */
1232
1233 if(ssl_connect_3 == connssl->connecting_state) {
1234 result = wolfssl_connect_step3(cf, data);
1235 if(result)
1236 return result;
1237 }
1238
1239 if(ssl_connect_done == connssl->connecting_state) {
1240 connssl->state = ssl_connection_complete;
1241 *done = TRUE;
1242 }
1243 else
1244 *done = FALSE;
1245
1246 /* Reset our connect state machine */
1247 connssl->connecting_state = ssl_connect_1;
1248
1249 return CURLE_OK;
1250}
1251
1252
1253static CURLcode wolfssl_connect_nonblocking(struct Curl_cfilter *cf,
1254 struct Curl_easy *data,
1255 bool *done)
1256{
1257 return wolfssl_connect_common(cf, data, TRUE, done);
1258}
1259
1260
1261static CURLcode wolfssl_connect(struct Curl_cfilter *cf,
1262 struct Curl_easy *data)
1263{
1264 CURLcode result;
1265 bool done = FALSE;
1266
1267 result = wolfssl_connect_common(cf, data, FALSE, &done);
1268 if(result)
1269 return result;
1270
1271 DEBUGASSERT(done);
1272
1273 return CURLE_OK;
1274}
1275
1276static CURLcode wolfssl_random(struct Curl_easy *data,
1277 unsigned char *entropy, size_t length)
1278{
1279 WC_RNG rng;
1280 (void)data;
1281 if(wc_InitRng(&rng))
1282 return CURLE_FAILED_INIT;
1283 if(length > UINT_MAX)
1284 return CURLE_FAILED_INIT;
1285 if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
1286 return CURLE_FAILED_INIT;
1287 if(wc_FreeRng(&rng))
1288 return CURLE_FAILED_INIT;
1289 return CURLE_OK;
1290}
1291
1292static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
1293 size_t tmplen,
1294 unsigned char *sha256sum /* output */,
1295 size_t unused)
1296{
1297 wc_Sha256 SHA256pw;
1298 (void)unused;
1299 wc_InitSha256(&SHA256pw);
1300 wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
1301 wc_Sha256Final(&SHA256pw, sha256sum);
1302 return CURLE_OK;
1303}
1304
1305static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
1306 CURLINFO info UNUSED_PARAM)
1307{
1308 struct ssl_backend_data *backend = connssl->backend;
1309 (void)info;
1310 DEBUGASSERT(backend);
1311 return backend->handle;
1312}
1313
1314const struct Curl_ssl Curl_ssl_wolfssl = {
1315 { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
1316
1317#ifdef KEEP_PEER_CERT
1318 SSLSUPP_PINNEDPUBKEY |
1319#endif
1320#ifdef USE_BIO_CHAIN
1321 SSLSUPP_HTTPS_PROXY |
1322#endif
1323 SSLSUPP_SSL_CTX,
1324
1325 sizeof(struct ssl_backend_data),
1326
1327 wolfssl_init, /* init */
1328 wolfssl_cleanup, /* cleanup */
1329 wolfssl_version, /* version */
1330 Curl_none_check_cxn, /* check_cxn */
1331 wolfssl_shutdown, /* shutdown */
1332 wolfssl_data_pending, /* data_pending */
1333 wolfssl_random, /* random */
1334 Curl_none_cert_status_request, /* cert_status_request */
1335 wolfssl_connect, /* connect */
1336 wolfssl_connect_nonblocking, /* connect_nonblocking */
1337 Curl_ssl_get_select_socks, /* getsock */
1338 wolfssl_get_internals, /* get_internals */
1339 wolfssl_close, /* close_one */
1340 Curl_none_close_all, /* close_all */
1341 wolfssl_session_free, /* session_free */
1342 Curl_none_set_engine, /* set_engine */
1343 Curl_none_set_engine_default, /* set_engine_default */
1344 Curl_none_engines_list, /* engines_list */
1345 Curl_none_false_start, /* false_start */
1346 wolfssl_sha256sum, /* sha256sum */
1347 NULL, /* associate_connection */
1348 NULL, /* disassociate_connection */
1349 NULL, /* free_multi_ssl_backend_data */
1350 wolfssl_recv, /* recv decrypted data */
1351 wolfssl_send, /* send data to encrypt */
1352};
1353
1354#endif
Note: See TracBrowser for help on using the repository browser.

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