VirtualBox

source: vbox/trunk/src/libs/curl-7.83.1/lib/vtls/wolfssl.c@ 97623

Last change on this file since 97623 was 95312, checked in by vboxsync, 3 years ago

libs/{curl,libxml2}: OSE export fixes, bugref:8515

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