1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2021, 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 ***************************************************************************/
22
23/*
24 * Source file for all wolfSSL specific code for the TLS/SSL layer. No code
25 * but vtls.c should ever call or use these functions.
26 *
27 */
28
29#include "curl_setup.h"
30
31#ifdef USE_WOLFSSL
32
33#define WOLFSSL_OPTIONS_IGNORE_SYS
34#include <wolfssl/version.h>
35#include <wolfssl/options.h>
36
37/* To determine what functions are available we rely on one or both of:
38 - the user's options.h generated by wolfSSL
39 - the symbols detected by curl's configure
40 Since they are markedly different from one another, and one or the other may
41 not be available, we do some checking below to bring things in sync. */
42
43/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
44#ifndef HAVE_ALPN
45#ifdef HAVE_WOLFSSL_USEALPN
46#define HAVE_ALPN
47#endif
48#endif
49
50#include <limits.h>
51
52#include "urldata.h"
53#include "sendf.h"
54#include "inet_pton.h"
55#include "vtls.h"
56#include "keylog.h"
57#include "parsedate.h"
58#include "connect.h" /* for the connect timeout */
59#include "select.h"
60#include "strcase.h"
61#include "x509asn1.h"
62#include "curl_printf.h"
63#include "multiif.h"
64
65#include <wolfssl/openssl/ssl.h>
66#include <wolfssl/ssl.h>
67#include <wolfssl/error-ssl.h>
68#include "wolfssl.h"
69
70/* The last #include files should be: */
71#include "curl_memory.h"
72#include "memdebug.h"
73
74/* KEEP_PEER_CERT is a product of the presence of build time symbol
75 OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
76 in wolfSSL's settings.h, and the latter two are build time symbols in
77 options.h. */
78#ifndef KEEP_PEER_CERT
79#if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
80 (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
81#define KEEP_PEER_CERT
82#endif
83#endif
84
85struct ssl_backend_data {
86 SSL_CTX* ctx;
87 SSL* handle;
88};
89
90static Curl_recv wolfssl_recv;
91static Curl_send wolfssl_send;
92
93#ifdef OPENSSL_EXTRA
94/*
95 * Availability note:
96 * The TLS 1.3 secret callback (wolfSSL_set_tls13_secret_cb) was added in
97 * WolfSSL 4.4.0, but requires the -DHAVE_SECRET_CALLBACK build option. If that
98 * option is not set, then TLS 1.3 will not be logged.
99 * For TLS 1.2 and before, we use wolfSSL_get_keys().
100 * SSL_get_client_random and wolfSSL_get_keys require OPENSSL_EXTRA
101 * (--enable-opensslextra or --enable-all).
102 */
103#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
104static int
105wolfssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret,
106 int secretSz, void *ctx)
107{
108 const char *label;
109 unsigned char client_random[SSL3_RANDOM_SIZE];
110 (void)ctx;
111
112 if(!ssl || !Curl_tls_keylog_enabled()) {
113 return 0;
114 }
115
116 switch(id) {
117 case CLIENT_EARLY_TRAFFIC_SECRET:
118 label = "CLIENT_EARLY_TRAFFIC_SECRET";
119 break;
120 case CLIENT_HANDSHAKE_TRAFFIC_SECRET:
121 label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
122 break;
123 case SERVER_HANDSHAKE_TRAFFIC_SECRET:
124 label = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
125 break;
126 case CLIENT_TRAFFIC_SECRET:
127 label = "CLIENT_TRAFFIC_SECRET_0";
128 break;
129 case SERVER_TRAFFIC_SECRET:
130 label = "SERVER_TRAFFIC_SECRET_0";
131 break;
132 case EARLY_EXPORTER_SECRET:
133 label = "EARLY_EXPORTER_SECRET";
134 break;
135 case EXPORTER_SECRET:
136 label = "EXPORTER_SECRET";
137 break;
138 default:
139 return 0;
140 }
141
142 if(SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE) == 0) {
143 /* Should never happen as wolfSSL_KeepArrays() was called before. */
144 return 0;
145 }
146
147 Curl_tls_keylog_write(label, client_random, secret, secretSz);
148 return 0;
149}
150#endif /* defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) */
151
152static void
153wolfssl_log_tls12_secret(SSL *ssl)
154{
155 unsigned char *ms, *sr, *cr;
156 unsigned int msLen, srLen, crLen, i, x = 0;
157
158#if LIBWOLFSSL_VERSION_HEX >= 0x0300d000 /* >= 3.13.0 */
159 /* wolfSSL_GetVersion is available since 3.13, we use it instead of
160 * SSL_version since the latter relies on OPENSSL_ALL (--enable-opensslall or
161 * --enable-all). Failing to perform this check could result in an unusable
162 * key log line when TLS 1.3 is actually negotiated. */
163 switch(wolfSSL_GetVersion(ssl)) {
164 case WOLFSSL_SSLV3:
165 case WOLFSSL_TLSV1:
166 case WOLFSSL_TLSV1_1:
167 case WOLFSSL_TLSV1_2:
168 break;
169 default:
170 /* TLS 1.3 does not use this mechanism, the "master secret" returned below
171 * is not directly usable. */
172 return;
173 }
174#endif
175
176 if(SSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) != SSL_SUCCESS) {
177 return;
178 }
179
180 /* Check for a missing master secret and skip logging. That can happen if
181 * curl rejects the server certificate and aborts the handshake.
182 */
183 for(i = 0; i < msLen; i++) {
184 x |= ms[i];
185 }
186 if(x == 0) {
187 return;
188 }
189
190 Curl_tls_keylog_write("CLIENT_RANDOM", cr, ms, msLen);
191}
192#endif /* OPENSSL_EXTRA */
193
194static int do_file_type(const char *type)
195{
196 if(!type || !type[0])
197 return SSL_FILETYPE_PEM;
198 if(strcasecompare(type, "PEM"))
199 return SSL_FILETYPE_PEM;
200 if(strcasecompare(type, "DER"))
201 return SSL_FILETYPE_ASN1;
202 return -1;
203}
204
205/*
206 * This function loads all the client/CA certificates and CRLs. Setup the TLS
207 * layer and do all necessary magic.
208 */
209static CURLcode
210wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
211 int sockindex)
212{
213 char *ciphers;
214 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
215 struct ssl_backend_data *backend = connssl->backend;
216 SSL_METHOD* req_method = NULL;
217 curl_socket_t sockfd = conn->sock[sockindex];
218#ifdef HAVE_SNI
219 bool sni = FALSE;
220#define use_sni(x) sni = (x)
221#else
222#define use_sni(x) Curl_nop_stmt
223#endif
224
225 if(connssl->state == ssl_connection_complete)
226 return CURLE_OK;
227
228 if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
229 failf(data, "wolfSSL does not support to set maximum SSL/TLS version");
230 return CURLE_SSL_CONNECT_ERROR;
231 }
232
233 /* check to see if we've been told to use an explicit SSL/TLS version */
234 switch(SSL_CONN_CONFIG(version)) {
235 case CURL_SSLVERSION_DEFAULT:
236 case CURL_SSLVERSION_TLSv1:
237#if LIBWOLFSSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
238 /* minimum protocol version is set later after the CTX object is created */
239 req_method = SSLv23_client_method();
240#else
241 infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
242 "TLS 1.0 is used exclusively");
243 req_method = TLSv1_client_method();
244#endif
245 use_sni(TRUE);
246 break;
247 case CURL_SSLVERSION_TLSv1_0:
248#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
249 req_method = TLSv1_client_method();
250 use_sni(TRUE);
251#else
252 failf(data, "wolfSSL does not support TLS 1.0");
253 return CURLE_NOT_BUILT_IN;
254#endif
255 break;
256 case CURL_SSLVERSION_TLSv1_1:
257#ifndef NO_OLD_TLS
258 req_method = TLSv1_1_client_method();
259 use_sni(TRUE);
260#else
261 failf(data, "wolfSSL does not support TLS 1.1");
262 return CURLE_NOT_BUILT_IN;
263#endif
264 break;
265 case CURL_SSLVERSION_TLSv1_2:
266 req_method = TLSv1_2_client_method();
267 use_sni(TRUE);
268 break;
269 case CURL_SSLVERSION_TLSv1_3:
270#ifdef WOLFSSL_TLS13
271 req_method = wolfTLSv1_3_client_method();
272 use_sni(TRUE);
273 break;
274#else
275 failf(data, "wolfSSL: TLS 1.3 is not yet supported");
276 return CURLE_SSL_CONNECT_ERROR;
277#endif
278 default:
279 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
280 return CURLE_SSL_CONNECT_ERROR;
281 }
282
283 if(!req_method) {
284 failf(data, "SSL: couldn't create a method!");
285 return CURLE_OUT_OF_MEMORY;
286 }
287
288 if(backend->ctx)
289 SSL_CTX_free(backend->ctx);
290 backend->ctx = SSL_CTX_new(req_method);
291
292 if(!backend->ctx) {
293 failf(data, "SSL: couldn't create a context!");
294 return CURLE_OUT_OF_MEMORY;
295 }
296
297 switch(SSL_CONN_CONFIG(version)) {
298 case CURL_SSLVERSION_DEFAULT:
299 case CURL_SSLVERSION_TLSv1:
300#if LIBWOLFSSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
301 /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is
302 * whatever minimum version of TLS was built in and at least TLS 1.0. For
303 * later library versions that could change (eg TLS 1.0 built in but
304 * defaults to TLS 1.1) so we have this short circuit evaluation to find
305 * the minimum supported TLS version.
306 */
307 if((wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1) != 1) &&
308 (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_1) != 1) &&
309 (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_2) != 1)
310#ifdef WOLFSSL_TLS13
311 && (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_3) != 1)
312#endif
313 ) {
314 failf(data, "SSL: couldn't set the minimum protocol version");
315 return CURLE_SSL_CONNECT_ERROR;
316 }
317#endif
318 break;
319 }
320
321 ciphers = SSL_CONN_CONFIG(cipher_list);
322 if(ciphers) {
323 if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
324 failf(data, "failed setting cipher list: %s", ciphers);
325 return CURLE_SSL_CIPHER;
326 }
327 infof(data, "Cipher selection: %s", ciphers);
328 }
329
330#ifndef NO_FILESYSTEM
331 /* load trusted cacert */
332 if(SSL_CONN_CONFIG(CAfile)) {
333 if(1 != SSL_CTX_load_verify_locations(backend->ctx,
334 SSL_CONN_CONFIG(CAfile),
335 SSL_CONN_CONFIG(CApath))) {
336 if(SSL_CONN_CONFIG(verifypeer)) {
337 /* Fail if we insist on successfully verifying the server. */
338 failf(data, "error setting certificate verify locations:"
339 " CAfile: %s CApath: %s",
340 SSL_CONN_CONFIG(CAfile)?
341 SSL_CONN_CONFIG(CAfile): "none",
342 SSL_CONN_CONFIG(CApath)?
343 SSL_CONN_CONFIG(CApath) : "none");
344 return CURLE_SSL_CACERT_BADFILE;
345 }
346 else {
347 /* Just continue with a warning if no strict certificate
348 verification is required. */
349 infof(data, "error setting certificate verify locations,"
350 " continuing anyway:");
351 }
352 }
353 else {
354 /* Everything is fine. */
355 infof(data, "successfully set certificate verify locations:");
356 }
357 infof(data, " CAfile: %s",
358 SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile) : "none");
359 infof(data, " CApath: %s",
360 SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath) : "none");
361 }
362
363 /* Load the client certificate, and private key */
364 if(SSL_SET_OPTION(primary.clientcert) && SSL_SET_OPTION(key)) {
365 int file_type = do_file_type(SSL_SET_OPTION(cert_type));
366
367 if(SSL_CTX_use_certificate_file(backend->ctx,
368 SSL_SET_OPTION(primary.clientcert),
369 file_type) != 1) {
370 failf(data, "unable to use client certificate (no key or wrong pass"
371 " phrase?)");
372 return CURLE_SSL_CONNECT_ERROR;
373 }
374
375 file_type = do_file_type(SSL_SET_OPTION(key_type));
376 if(SSL_CTX_use_PrivateKey_file(backend->ctx, SSL_SET_OPTION(key),
377 file_type) != 1) {
378 failf(data, "unable to set private key");
379 return CURLE_SSL_CONNECT_ERROR;
380 }
381 }
382#endif /* !NO_FILESYSTEM */
383
384 /* SSL always tries to verify the peer, this only says whether it should
385 * fail to connect if the verification fails, or if it should continue
386 * anyway. In the latter case the result of the verification is checked with
387 * SSL_get_verify_result() below. */
388 SSL_CTX_set_verify(backend->ctx,
389 SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
390 SSL_VERIFY_NONE,
391 NULL);
392
393#ifdef HAVE_SNI
394 if(sni) {
395 struct in_addr addr4;
396#ifdef ENABLE_IPV6
397 struct in6_addr addr6;
398#endif
399 const char * const hostname = SSL_HOST_NAME();
400 size_t hostname_len = strlen(hostname);
401 if((hostname_len < USHRT_MAX) &&
402 (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
403#ifdef ENABLE_IPV6
404 (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
405#endif
406 (wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, hostname,
407 (unsigned short)hostname_len) != 1)) {
408 infof(data, "WARNING: failed to configure server name indication (SNI) "
409 "TLS extension");
410 }
411 }
412#endif
413
414 /* give application a chance to interfere with SSL set up. */
415 if(data->set.ssl.fsslctx) {
416 CURLcode result = (*data->set.ssl.fsslctx)(data, backend->ctx,
417 data->set.ssl.fsslctxp);
418 if(result) {
419 failf(data, "error signaled by ssl ctx callback");
420 return result;
421 }
422 }
423#ifdef NO_FILESYSTEM
424 else if(SSL_CONN_CONFIG(verifypeer)) {
425 failf(data, "SSL: Certificates can't be loaded because wolfSSL was built"
426 " with \"no filesystem\". Either disable peer verification"
427 " (insecure) or if you are building an application with libcurl you"
428 " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
429 return CURLE_SSL_CONNECT_ERROR;
430 }
431#endif
432
433 /* Let's make an SSL structure */
434 if(backend->handle)
435 SSL_free(backend->handle);
436 backend->handle = SSL_new(backend->ctx);
437 if(!backend->handle) {
438 failf(data, "SSL: couldn't create a context (handle)!");
439 return CURLE_OUT_OF_MEMORY;
440 }
441
442#ifdef HAVE_ALPN
443 if(conn->bits.tls_enable_alpn) {
444 char protocols[128];
445 *protocols = '\0';
446
447 /* wolfSSL's ALPN protocol name list format is a comma separated string of
448 protocols in descending order of preference, eg: "h2,http/1.1" */
449
450#ifdef USE_HTTP2
451 if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
452 strcpy(protocols + strlen(protocols), ALPN_H2 ",");
453 infof(data, "ALPN, offering %s", ALPN_H2);
454 }
455#endif
456
457 strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
458 infof(data, "ALPN, offering %s", ALPN_HTTP_1_1);
459
460 if(wolfSSL_UseALPN(backend->handle, protocols,
461 (unsigned)strlen(protocols),
462 WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
463 failf(data, "SSL: failed setting ALPN protocols");
464 return CURLE_SSL_CONNECT_ERROR;
465 }
466 }
467#endif /* HAVE_ALPN */
468
469#ifdef OPENSSL_EXTRA
470 if(Curl_tls_keylog_enabled()) {
471 /* Ensure the Client Random is preserved. */
472 wolfSSL_KeepArrays(backend->handle);
473#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
474 wolfSSL_set_tls13_secret_cb(backend->handle,
475 wolfssl_tls13_secret_callback, NULL);
476#endif
477 }
478#endif /* OPENSSL_EXTRA */
479
480#ifdef HAVE_SECURE_RENEGOTIATION
481 if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) {
482 failf(data, "SSL: failed setting secure renegotiation");
483 return CURLE_SSL_CONNECT_ERROR;
484 }
485#endif /* HAVE_SECURE_RENEGOTIATION */
486
487 /* Check if there's a cached ID we can/should use here! */
488 if(SSL_SET_OPTION(primary.sessionid)) {
489 void *ssl_sessionid = NULL;
490
491 Curl_ssl_sessionid_lock(data);
492 if(!Curl_ssl_getsessionid(data, conn,
493 SSL_IS_PROXY() ? TRUE : FALSE,
494 &ssl_sessionid, NULL, sockindex)) {
495 /* we got a session id, use it! */
496 if(!SSL_set_session(backend->handle, ssl_sessionid)) {
497 Curl_ssl_delsessionid(data, ssl_sessionid);
498 infof(data, "Can't use session ID, going on without\n");
499 }
500 else
501 infof(data, "SSL re-using session ID");
502 }
503 Curl_ssl_sessionid_unlock(data);
504 }
505
506 /* pass the raw socket into the SSL layer */
507 if(!SSL_set_fd(backend->handle, (int)sockfd)) {
508 failf(data, "SSL: SSL_set_fd failed");
509 return CURLE_SSL_CONNECT_ERROR;
510 }
511
512 connssl->connecting_state = ssl_connect_2;
513 return CURLE_OK;
514}
515
516
517static CURLcode
518wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
519 int sockindex)
520{
521 int ret = -1;
522 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
523 struct ssl_backend_data *backend = connssl->backend;
524 const char * const hostname = SSL_HOST_NAME();
525 const char * const dispname = SSL_HOST_DISPNAME();
526 const char * const pinnedpubkey = SSL_PINNED_PUB_KEY();
527
528 ERR_clear_error();
529
530 conn->recv[sockindex] = wolfssl_recv;
531 conn->send[sockindex] = wolfssl_send;
532
533 /* Enable RFC2818 checks */
534 if(SSL_CONN_CONFIG(verifyhost)) {
535 ret = wolfSSL_check_domain_name(backend->handle, hostname);
536 if(ret == SSL_FAILURE)
537 return CURLE_OUT_OF_MEMORY;
538 }
539
540 ret = SSL_connect(backend->handle);
541
542#ifdef OPENSSL_EXTRA
543 if(Curl_tls_keylog_enabled()) {
544 /* If key logging is enabled, wait for the handshake to complete and then
545 * proceed with logging secrets (for TLS 1.2 or older).
546 *
547 * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
548 * for the server response. At that point the master secret is not yet
549 * available, so we must not try to read it.
550 * To log the secret on completion with a handshake failure, detect
551 * completion via the observation that there is nothing to read or write.
552 * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
553 * changes, the worst case is that no key is logged on error.
554 */
555 if(ret == SSL_SUCCESS ||
556 (!wolfSSL_want_read(backend->handle) &&
557 !wolfSSL_want_write(backend->handle))) {
558 wolfssl_log_tls12_secret(backend->handle);
559 /* Client Random and master secrets are no longer needed, erase these.
560 * Ignored while the handshake is still in progress. */
561 wolfSSL_FreeArrays(backend->handle);
562 }
563 }
564#endif /* OPENSSL_EXTRA */
565
566 if(ret != 1) {
567 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
568 int detail = SSL_get_error(backend->handle, ret);
569
570 if(SSL_ERROR_WANT_READ == detail) {
571 connssl->connecting_state = ssl_connect_2_reading;
572 return CURLE_OK;
573 }
574 else if(SSL_ERROR_WANT_WRITE == detail) {
575 connssl->connecting_state = ssl_connect_2_writing;
576 return CURLE_OK;
577 }
578 /* There is no easy way to override only the CN matching.
579 * This will enable the override of both mismatching SubjectAltNames
580 * as also mismatching CN fields */
581 else if(DOMAIN_NAME_MISMATCH == detail) {
582#if 1
583 failf(data, " subject alt name(s) or common name do not match \"%s\"",
584 dispname);
585 return CURLE_PEER_FAILED_VERIFICATION;
586#else
587 /* When the wolfssl_check_domain_name() is used and you desire to
588 * continue on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost
589 * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
590 * error. The only way to do this is currently to switch the
591 * Wolfssl_check_domain_name() in and out based on the
592 * 'conn->ssl_config.verifyhost' value. */
593 if(SSL_CONN_CONFIG(verifyhost)) {
594 failf(data,
595 " subject alt name(s) or common name do not match \"%s\"\n",
596 dispname);
597 return CURLE_PEER_FAILED_VERIFICATION;
598 }
599 else {
600 infof(data,
601 " subject alt name(s) and/or common name do not match \"%s\"",
602 dispname);
603 return CURLE_OK;
604 }
605#endif
606 }
607#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
608 else if(ASN_NO_SIGNER_E == detail) {
609 if(SSL_CONN_CONFIG(verifypeer)) {
610 failf(data, " CA signer not available for verification");
611 return CURLE_SSL_CACERT_BADFILE;
612 }
613 else {
614 /* Just continue with a warning if no strict certificate
615 verification is required. */
616 infof(data, "CA signer not available for verification, "
617 "continuing anyway");
618 }
619 }
620#endif
621 else {
622 failf(data, "SSL_connect failed with error %d: %s", detail,
623 ERR_error_string(detail, error_buffer));
624 return CURLE_SSL_CONNECT_ERROR;
625 }
626 }
627
628 if(pinnedpubkey) {
629#ifdef KEEP_PEER_CERT
630 X509 *x509;
631 const char *x509_der;
632 int x509_der_len;
633 struct Curl_X509certificate x509_parsed;
634 struct Curl_asn1Element *pubkey;
635 CURLcode result;
636
637 x509 = SSL_get_peer_certificate(backend->handle);
638 if(!x509) {
639 failf(data, "SSL: failed retrieving server certificate");
640 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
641 }
642
643 x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
644 if(!x509_der) {
645 failf(data, "SSL: failed retrieving ASN.1 server certificate");
646 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
647 }
648
649 memset(&x509_parsed, 0, sizeof(x509_parsed));
650 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
651 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
652
653 pubkey = &x509_parsed.subjectPublicKeyInfo;
654 if(!pubkey->header || pubkey->end <= pubkey->header) {
655 failf(data, "SSL: failed retrieving public key from server certificate");
656 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
657 }
658
659 result = Curl_pin_peer_pubkey(data,
660 pinnedpubkey,
661 (const unsigned char *)pubkey->header,
662 (size_t)(pubkey->end - pubkey->header));
663 if(result) {
664 failf(data, "SSL: public key does not match pinned public key!");
665 return result;
666 }
667#else
668 failf(data, "Library lacks pinning support built-in");
669 return CURLE_NOT_BUILT_IN;
670#endif
671 }
672
673#ifdef HAVE_ALPN
674 if(conn->bits.tls_enable_alpn) {
675 int rc;
676 char *protocol = NULL;
677 unsigned short protocol_len = 0;
678
679 rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
680
681 if(rc == SSL_SUCCESS) {
682 infof(data, "ALPN, server accepted to use %.*s", protocol_len,
683 protocol);
684
685 if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
686 !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
687 conn->negnpn = CURL_HTTP_VERSION_1_1;
688#ifdef USE_HTTP2
689 else if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
690 protocol_len == ALPN_H2_LENGTH &&
691 !memcmp(protocol, ALPN_H2, ALPN_H2_LENGTH))
692 conn->negnpn = CURL_HTTP_VERSION_2;
693#endif
694 else
695 infof(data, "ALPN, unrecognized protocol %.*s", protocol_len,
696 protocol);
697 Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
698 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
699 }
700 else if(rc == SSL_ALPN_NOT_FOUND)
701 infof(data, "ALPN, server did not agree to a protocol");
702 else {
703 failf(data, "ALPN, failure getting protocol, error %d", rc);
704 return CURLE_SSL_CONNECT_ERROR;
705 }
706 }
707#endif /* HAVE_ALPN */
708
709 connssl->connecting_state = ssl_connect_3;
710#if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
711 infof(data, "SSL connection using %s / %s",
712 wolfSSL_get_version(backend->handle),
713 wolfSSL_get_cipher_name(backend->handle));
714#else
715 infof(data, "SSL connected");
716#endif
717
718 return CURLE_OK;
719}
720
721
722static CURLcode
723wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
724 int sockindex)
725{
726 CURLcode result = CURLE_OK;
727 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
728 struct ssl_backend_data *backend = connssl->backend;
729
730 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
731
732 if(SSL_SET_OPTION(primary.sessionid)) {
733 bool incache;
734 void *old_ssl_sessionid = NULL;
735 SSL_SESSION *our_ssl_sessionid = SSL_get_session(backend->handle);
736 bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
737
738 if(our_ssl_sessionid) {
739 Curl_ssl_sessionid_lock(data);
740 incache = !(Curl_ssl_getsessionid(data, conn, isproxy,
741 &old_ssl_sessionid, NULL, sockindex));
742 if(incache) {
743 if(old_ssl_sessionid != our_ssl_sessionid) {
744 infof(data, "old SSL session ID is stale, removing");
745 Curl_ssl_delsessionid(data, old_ssl_sessionid);
746 incache = FALSE;
747 }
748 }
749
750 if(!incache) {
751 result = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid,
752 0, sockindex);
753 if(result) {
754 Curl_ssl_sessionid_unlock(data);
755 failf(data, "failed to store ssl session");
756 return result;
757 }
758 }
759 Curl_ssl_sessionid_unlock(data);
760 }
761 }
762
763 connssl->connecting_state = ssl_connect_done;
764
765 return result;
766}
767
768
769static ssize_t wolfssl_send(struct Curl_easy *data,
770 int sockindex,
771 const void *mem,
772 size_t len,
773 CURLcode *curlcode)
774{
775 struct connectdata *conn = data->conn;
776 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
777 struct ssl_backend_data *backend = connssl->backend;
778 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
779 int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
780 int rc;
781
782 ERR_clear_error();
783
784 rc = SSL_write(backend->handle, mem, memlen);
785
786 if(rc <= 0) {
787 int err = SSL_get_error(backend->handle, rc);
788
789 switch(err) {
790 case SSL_ERROR_WANT_READ:
791 case SSL_ERROR_WANT_WRITE:
792 /* there's data pending, re-invoke SSL_write() */
793 *curlcode = CURLE_AGAIN;
794 return -1;
795 default:
796 failf(data, "SSL write: %s, errno %d",
797 ERR_error_string(err, error_buffer),
798 SOCKERRNO);
799 *curlcode = CURLE_SEND_ERROR;
800 return -1;
801 }
802 }
803 return rc;
804}
805
806static void wolfssl_close(struct Curl_easy *data, struct connectdata *conn,
807 int sockindex)
808{
809 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
810 struct ssl_backend_data *backend = connssl->backend;
811
812 (void) data;
813
814 if(backend->handle) {
815 char buf[32];
816 /* Maybe the server has already sent a close notify alert.
817 Read it to avoid an RST on the TCP connection. */
818 (void)SSL_read(backend->handle, buf, (int)sizeof(buf));
819 (void)SSL_shutdown(backend->handle);
820 SSL_free(backend->handle);
821 backend->handle = NULL;
822 }
823 if(backend->ctx) {
824 SSL_CTX_free(backend->ctx);
825 backend->ctx = NULL;
826 }
827}
828
829static ssize_t wolfssl_recv(struct Curl_easy *data,
830 int num,
831 char *buf,
832 size_t buffersize,
833 CURLcode *curlcode)
834{
835 struct connectdata *conn = data->conn;
836 struct ssl_connect_data *connssl = &conn->ssl[num];
837 struct ssl_backend_data *backend = connssl->backend;
838 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
839 int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
840 int nread;
841
842 ERR_clear_error();
843
844 nread = SSL_read(backend->handle, buf, buffsize);
845
846 if(nread < 0) {
847 int err = SSL_get_error(backend->handle, nread);
848
849 switch(err) {
850 case SSL_ERROR_ZERO_RETURN: /* no more data */
851 break;
852 case SSL_ERROR_WANT_READ:
853 case SSL_ERROR_WANT_WRITE:
854 /* there's data pending, re-invoke SSL_read() */
855 *curlcode = CURLE_AGAIN;
856 return -1;
857 default:
858 failf(data, "SSL read: %s, errno %d",
859 ERR_error_string(err, error_buffer), SOCKERRNO);
860 *curlcode = CURLE_RECV_ERROR;
861 return -1;
862 }
863 }
864 return nread;
865}
866
867
868static void wolfssl_session_free(void *ptr)
869{
870 (void)ptr;
871 /* wolfSSL reuses sessions on own, no free */
872}
873
874
875static size_t wolfssl_version(char *buffer, size_t size)
876{
877#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
878 return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
879#elif defined(WOLFSSL_VERSION)
880 return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
881#endif
882}
883
884
885static int wolfssl_init(void)
886{
887#ifdef OPENSSL_EXTRA
888 Curl_tls_keylog_open();
889#endif
890 return (wolfSSL_Init() == SSL_SUCCESS);
891}
892
893
894static void wolfssl_cleanup(void)
895{
896 wolfSSL_Cleanup();
897#ifdef OPENSSL_EXTRA
898 Curl_tls_keylog_close();
899#endif
900}
901
902
903static bool wolfssl_data_pending(const struct connectdata *conn,
904 int connindex)
905{
906 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
907 struct ssl_backend_data *backend = connssl->backend;
908 if(backend->handle) /* SSL is in use */
909 return (0 != SSL_pending(backend->handle)) ? TRUE : FALSE;
910 else
911 return FALSE;
912}
913
914
915/*
916 * This function is called to shut down the SSL layer but keep the
917 * socket open (CCC - Clear Command Channel)
918 */
919static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
920 int sockindex)
921{
922 int retval = 0;
923 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
924 struct ssl_backend_data *backend = connssl->backend;
925
926 (void) data;
927
928 if(backend->handle) {
929 ERR_clear_error();
930 SSL_free(backend->handle);
931 backend->handle = NULL;
932 }
933 return retval;
934}
935
936
937static CURLcode
938wolfssl_connect_common(struct Curl_easy *data,
939 struct connectdata *conn,
940 int sockindex,
941 bool nonblocking,
942 bool *done)
943{
944 CURLcode result;
945 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
946 curl_socket_t sockfd = conn->sock[sockindex];
947 int what;
948
949 /* check if the connection has already been established */
950 if(ssl_connection_complete == connssl->state) {
951 *done = TRUE;
952 return CURLE_OK;
953 }
954
955 if(ssl_connect_1 == connssl->connecting_state) {
956 /* Find out how much more time we're allowed */
957 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
958
959 if(timeout_ms < 0) {
960 /* no need to continue if time already is up */
961 failf(data, "SSL connection timeout");
962 return CURLE_OPERATION_TIMEDOUT;
963 }
964
965 result = wolfssl_connect_step1(data, conn, sockindex);
966 if(result)
967 return result;
968 }
969
970 while(ssl_connect_2 == connssl->connecting_state ||
971 ssl_connect_2_reading == connssl->connecting_state ||
972 ssl_connect_2_writing == connssl->connecting_state) {
973
974 /* check allowed time left */
975 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
976
977 if(timeout_ms < 0) {
978 /* no need to continue if time already is up */
979 failf(data, "SSL connection timeout");
980 return CURLE_OPERATION_TIMEDOUT;
981 }
982
983 /* if ssl is expecting something, check if it's available. */
984 if(connssl->connecting_state == ssl_connect_2_reading
985 || connssl->connecting_state == ssl_connect_2_writing) {
986
987 curl_socket_t writefd = ssl_connect_2_writing ==
988 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
989 curl_socket_t readfd = ssl_connect_2_reading ==
990 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
991
992 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
993 nonblocking?0:timeout_ms);
994 if(what < 0) {
995 /* fatal error */
996 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
997 return CURLE_SSL_CONNECT_ERROR;
998 }
999 else if(0 == what) {
1000 if(nonblocking) {
1001 *done = FALSE;
1002 return CURLE_OK;
1003 }
1004 else {
1005 /* timeout */
1006 failf(data, "SSL connection timeout");
1007 return CURLE_OPERATION_TIMEDOUT;
1008 }
1009 }
1010 /* socket is readable or writable */
1011 }
1012
1013 /* Run transaction, and return to the caller if it failed or if
1014 * this connection is part of a multi handle and this loop would
1015 * execute again. This permits the owner of a multi handle to
1016 * abort a connection attempt before step2 has completed while
1017 * ensuring that a client using select() or epoll() will always
1018 * have a valid fdset to wait on.
1019 */
1020 result = wolfssl_connect_step2(data, conn, sockindex);
1021 if(result || (nonblocking &&
1022 (ssl_connect_2 == connssl->connecting_state ||
1023 ssl_connect_2_reading == connssl->connecting_state ||
1024 ssl_connect_2_writing == connssl->connecting_state)))
1025 return result;
1026 } /* repeat step2 until all transactions are done. */
1027
1028 if(ssl_connect_3 == connssl->connecting_state) {
1029 result = wolfssl_connect_step3(data, conn, sockindex);
1030 if(result)
1031 return result;
1032 }
1033
1034 if(ssl_connect_done == connssl->connecting_state) {
1035 connssl->state = ssl_connection_complete;
1036 conn->recv[sockindex] = wolfssl_recv;
1037 conn->send[sockindex] = wolfssl_send;
1038 *done = TRUE;
1039 }
1040 else
1041 *done = FALSE;
1042
1043 /* Reset our connect state machine */
1044 connssl->connecting_state = ssl_connect_1;
1045
1046 return CURLE_OK;
1047}
1048
1049
1050static CURLcode wolfssl_connect_nonblocking(struct Curl_easy *data,
1051 struct connectdata *conn,
1052 int sockindex, bool *done)
1053{
1054 return wolfssl_connect_common(data, conn, sockindex, TRUE, done);
1055}
1056
1057
1058static CURLcode wolfssl_connect(struct Curl_easy *data,
1059 struct connectdata *conn, int sockindex)
1060{
1061 CURLcode result;
1062 bool done = FALSE;
1063
1064 result = wolfssl_connect_common(data, conn, sockindex, FALSE, &done);
1065 if(result)
1066 return result;
1067
1068 DEBUGASSERT(done);
1069
1070 return CURLE_OK;
1071}
1072
1073static CURLcode wolfssl_random(struct Curl_easy *data,
1074 unsigned char *entropy, size_t length)
1075{
1076 WC_RNG rng;
1077 (void)data;
1078 if(wc_InitRng(&rng))
1079 return CURLE_FAILED_INIT;
1080 if(length > UINT_MAX)
1081 return CURLE_FAILED_INIT;
1082 if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
1083 return CURLE_FAILED_INIT;
1084 if(wc_FreeRng(&rng))
1085 return CURLE_FAILED_INIT;
1086 return CURLE_OK;
1087}
1088
1089static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
1090 size_t tmplen,
1091 unsigned char *sha256sum /* output */,
1092 size_t unused)
1093{
1094 wc_Sha256 SHA256pw;
1095 (void)unused;
1096 wc_InitSha256(&SHA256pw);
1097 wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
1098 wc_Sha256Final(&SHA256pw, sha256sum);
1099 return CURLE_OK;
1100}
1101
1102static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
1103 CURLINFO info UNUSED_PARAM)
1104{
1105 struct ssl_backend_data *backend = connssl->backend;
1106 (void)info;
1107 return backend->handle;
1108}
1109
1110const struct Curl_ssl Curl_ssl_wolfssl = {
1111 { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
1112
1113#ifdef KEEP_PEER_CERT
1114 SSLSUPP_PINNEDPUBKEY |
1115#endif
1116 SSLSUPP_SSL_CTX,
1117
1118 sizeof(struct ssl_backend_data),
1119
1120 wolfssl_init, /* init */
1121 wolfssl_cleanup, /* cleanup */
1122 wolfssl_version, /* version */
1123 Curl_none_check_cxn, /* check_cxn */
1124 wolfssl_shutdown, /* shutdown */
1125 wolfssl_data_pending, /* data_pending */
1126 wolfssl_random, /* random */
1127 Curl_none_cert_status_request, /* cert_status_request */
1128 wolfssl_connect, /* connect */
1129 wolfssl_connect_nonblocking, /* connect_nonblocking */
1130 Curl_ssl_getsock, /* getsock */
1131 wolfssl_get_internals, /* get_internals */
1132 wolfssl_close, /* close_one */
1133 Curl_none_close_all, /* close_all */
1134 wolfssl_session_free, /* session_free */
1135 Curl_none_set_engine, /* set_engine */
1136 Curl_none_set_engine_default, /* set_engine_default */
1137 Curl_none_engines_list, /* engines_list */
1138 Curl_none_false_start, /* false_start */
1139 wolfssl_sha256sum, /* sha256sum */
1140 NULL, /* associate_connection */
1141 NULL /* disassociate_connection */
1142};
1143
1144#endif
1145