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
85 struct ssl_backend_data {
86 SSL_CTX* ctx;
87 SSL* handle;
88 };
89
90 static Curl_recv wolfssl_recv;
91 static 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)
104 static int
wolfssl_tls13_secret_callback(SSL * ssl,int id,const unsigned char * secret,int secretSz,void * ctx)105 wolfssl_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
152 static void
wolfssl_log_tls12_secret(SSL * ssl)153 wolfssl_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
do_file_type(const char * type)194 static 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 */
209 static CURLcode
wolfssl_connect_step1(struct Curl_easy * data,struct connectdata * conn,int sockindex)210 wolfssl_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
517 static CURLcode
wolfssl_connect_step2(struct Curl_easy * data,struct connectdata * conn,int sockindex)518 wolfssl_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 conn->recv[sockindex] = wolfssl_recv;
529 conn->send[sockindex] = wolfssl_send;
530
531 /* Enable RFC2818 checks */
532 if(SSL_CONN_CONFIG(verifyhost)) {
533 ret = wolfSSL_check_domain_name(backend->handle, hostname);
534 if(ret == SSL_FAILURE)
535 return CURLE_OUT_OF_MEMORY;
536 }
537
538 ret = SSL_connect(backend->handle);
539
540 #ifdef OPENSSL_EXTRA
541 if(Curl_tls_keylog_enabled()) {
542 /* If key logging is enabled, wait for the handshake to complete and then
543 * proceed with logging secrets (for TLS 1.2 or older).
544 *
545 * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
546 * for the server response. At that point the master secret is not yet
547 * available, so we must not try to read it.
548 * To log the secret on completion with a handshake failure, detect
549 * completion via the observation that there is nothing to read or write.
550 * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
551 * changes, the worst case is that no key is logged on error.
552 */
553 if(ret == SSL_SUCCESS ||
554 (!wolfSSL_want_read(backend->handle) &&
555 !wolfSSL_want_write(backend->handle))) {
556 wolfssl_log_tls12_secret(backend->handle);
557 /* Client Random and master secrets are no longer needed, erase these.
558 * Ignored while the handshake is still in progress. */
559 wolfSSL_FreeArrays(backend->handle);
560 }
561 }
562 #endif /* OPENSSL_EXTRA */
563
564 if(ret != 1) {
565 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
566 int detail = SSL_get_error(backend->handle, ret);
567
568 if(SSL_ERROR_WANT_READ == detail) {
569 connssl->connecting_state = ssl_connect_2_reading;
570 return CURLE_OK;
571 }
572 else if(SSL_ERROR_WANT_WRITE == detail) {
573 connssl->connecting_state = ssl_connect_2_writing;
574 return CURLE_OK;
575 }
576 /* There is no easy way to override only the CN matching.
577 * This will enable the override of both mismatching SubjectAltNames
578 * as also mismatching CN fields */
579 else if(DOMAIN_NAME_MISMATCH == detail) {
580 #if 1
581 failf(data, " subject alt name(s) or common name do not match \"%s\"",
582 dispname);
583 return CURLE_PEER_FAILED_VERIFICATION;
584 #else
585 /* When the wolfssl_check_domain_name() is used and you desire to
586 * continue on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost
587 * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
588 * error. The only way to do this is currently to switch the
589 * Wolfssl_check_domain_name() in and out based on the
590 * 'conn->ssl_config.verifyhost' value. */
591 if(SSL_CONN_CONFIG(verifyhost)) {
592 failf(data,
593 " subject alt name(s) or common name do not match \"%s\"\n",
594 dispname);
595 return CURLE_PEER_FAILED_VERIFICATION;
596 }
597 else {
598 infof(data,
599 " subject alt name(s) and/or common name do not match \"%s\"",
600 dispname);
601 return CURLE_OK;
602 }
603 #endif
604 }
605 #if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
606 else if(ASN_NO_SIGNER_E == detail) {
607 if(SSL_CONN_CONFIG(verifypeer)) {
608 failf(data, " CA signer not available for verification");
609 return CURLE_SSL_CACERT_BADFILE;
610 }
611 else {
612 /* Just continue with a warning if no strict certificate
613 verification is required. */
614 infof(data, "CA signer not available for verification, "
615 "continuing anyway");
616 }
617 }
618 #endif
619 else {
620 failf(data, "SSL_connect failed with error %d: %s", detail,
621 ERR_error_string(detail, error_buffer));
622 return CURLE_SSL_CONNECT_ERROR;
623 }
624 }
625
626 if(pinnedpubkey) {
627 #ifdef KEEP_PEER_CERT
628 X509 *x509;
629 const char *x509_der;
630 int x509_der_len;
631 struct Curl_X509certificate x509_parsed;
632 struct Curl_asn1Element *pubkey;
633 CURLcode result;
634
635 x509 = SSL_get_peer_certificate(backend->handle);
636 if(!x509) {
637 failf(data, "SSL: failed retrieving server certificate");
638 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
639 }
640
641 x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
642 if(!x509_der) {
643 failf(data, "SSL: failed retrieving ASN.1 server certificate");
644 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
645 }
646
647 memset(&x509_parsed, 0, sizeof(x509_parsed));
648 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
649 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
650
651 pubkey = &x509_parsed.subjectPublicKeyInfo;
652 if(!pubkey->header || pubkey->end <= pubkey->header) {
653 failf(data, "SSL: failed retrieving public key from server certificate");
654 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
655 }
656
657 result = Curl_pin_peer_pubkey(data,
658 pinnedpubkey,
659 (const unsigned char *)pubkey->header,
660 (size_t)(pubkey->end - pubkey->header));
661 if(result) {
662 failf(data, "SSL: public key does not match pinned public key!");
663 return result;
664 }
665 #else
666 failf(data, "Library lacks pinning support built-in");
667 return CURLE_NOT_BUILT_IN;
668 #endif
669 }
670
671 #ifdef HAVE_ALPN
672 if(conn->bits.tls_enable_alpn) {
673 int rc;
674 char *protocol = NULL;
675 unsigned short protocol_len = 0;
676
677 rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
678
679 if(rc == SSL_SUCCESS) {
680 infof(data, "ALPN, server accepted to use %.*s", protocol_len,
681 protocol);
682
683 if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
684 !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
685 conn->negnpn = CURL_HTTP_VERSION_1_1;
686 #ifdef USE_HTTP2
687 else if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
688 protocol_len == ALPN_H2_LENGTH &&
689 !memcmp(protocol, ALPN_H2, ALPN_H2_LENGTH))
690 conn->negnpn = CURL_HTTP_VERSION_2;
691 #endif
692 else
693 infof(data, "ALPN, unrecognized protocol %.*s", protocol_len,
694 protocol);
695 Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
696 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
697 }
698 else if(rc == SSL_ALPN_NOT_FOUND)
699 infof(data, "ALPN, server did not agree to a protocol");
700 else {
701 failf(data, "ALPN, failure getting protocol, error %d", rc);
702 return CURLE_SSL_CONNECT_ERROR;
703 }
704 }
705 #endif /* HAVE_ALPN */
706
707 connssl->connecting_state = ssl_connect_3;
708 #if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
709 infof(data, "SSL connection using %s / %s",
710 wolfSSL_get_version(backend->handle),
711 wolfSSL_get_cipher_name(backend->handle));
712 #else
713 infof(data, "SSL connected");
714 #endif
715
716 return CURLE_OK;
717 }
718
719
720 static CURLcode
wolfssl_connect_step3(struct Curl_easy * data,struct connectdata * conn,int sockindex)721 wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
722 int sockindex)
723 {
724 CURLcode result = CURLE_OK;
725 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
726 struct ssl_backend_data *backend = connssl->backend;
727
728 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
729
730 if(SSL_SET_OPTION(primary.sessionid)) {
731 bool incache;
732 void *old_ssl_sessionid = NULL;
733 SSL_SESSION *our_ssl_sessionid = SSL_get_session(backend->handle);
734 bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
735
736 if(our_ssl_sessionid) {
737 Curl_ssl_sessionid_lock(data);
738 incache = !(Curl_ssl_getsessionid(data, conn, isproxy,
739 &old_ssl_sessionid, NULL, sockindex));
740 if(incache) {
741 if(old_ssl_sessionid != our_ssl_sessionid) {
742 infof(data, "old SSL session ID is stale, removing");
743 Curl_ssl_delsessionid(data, old_ssl_sessionid);
744 incache = FALSE;
745 }
746 }
747
748 if(!incache) {
749 result = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid,
750 0, sockindex);
751 if(result) {
752 Curl_ssl_sessionid_unlock(data);
753 failf(data, "failed to store ssl session");
754 return result;
755 }
756 }
757 Curl_ssl_sessionid_unlock(data);
758 }
759 }
760
761 connssl->connecting_state = ssl_connect_done;
762
763 return result;
764 }
765
766
wolfssl_send(struct Curl_easy * data,int sockindex,const void * mem,size_t len,CURLcode * curlcode)767 static ssize_t wolfssl_send(struct Curl_easy *data,
768 int sockindex,
769 const void *mem,
770 size_t len,
771 CURLcode *curlcode)
772 {
773 struct connectdata *conn = data->conn;
774 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
775 struct ssl_backend_data *backend = connssl->backend;
776 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
777 int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
778 int rc = SSL_write(backend->handle, mem, memlen);
779
780 if(rc <= 0) {
781 int err = SSL_get_error(backend->handle, rc);
782
783 switch(err) {
784 case SSL_ERROR_WANT_READ:
785 case SSL_ERROR_WANT_WRITE:
786 /* there's data pending, re-invoke SSL_write() */
787 *curlcode = CURLE_AGAIN;
788 return -1;
789 default:
790 failf(data, "SSL write: %s, errno %d",
791 ERR_error_string(err, error_buffer),
792 SOCKERRNO);
793 *curlcode = CURLE_SEND_ERROR;
794 return -1;
795 }
796 }
797 return rc;
798 }
799
wolfssl_close(struct Curl_easy * data,struct connectdata * conn,int sockindex)800 static void wolfssl_close(struct Curl_easy *data, struct connectdata *conn,
801 int sockindex)
802 {
803 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
804 struct ssl_backend_data *backend = connssl->backend;
805
806 (void) data;
807
808 if(backend->handle) {
809 char buf[32];
810 /* Maybe the server has already sent a close notify alert.
811 Read it to avoid an RST on the TCP connection. */
812 (void)SSL_read(backend->handle, buf, (int)sizeof(buf));
813 (void)SSL_shutdown(backend->handle);
814 SSL_free(backend->handle);
815 backend->handle = NULL;
816 }
817 if(backend->ctx) {
818 SSL_CTX_free(backend->ctx);
819 backend->ctx = NULL;
820 }
821 }
822
wolfssl_recv(struct Curl_easy * data,int num,char * buf,size_t buffersize,CURLcode * curlcode)823 static ssize_t wolfssl_recv(struct Curl_easy *data,
824 int num,
825 char *buf,
826 size_t buffersize,
827 CURLcode *curlcode)
828 {
829 struct connectdata *conn = data->conn;
830 struct ssl_connect_data *connssl = &conn->ssl[num];
831 struct ssl_backend_data *backend = connssl->backend;
832 char error_buffer[WOLFSSL_MAX_ERROR_SZ];
833 int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
834 int nread = SSL_read(backend->handle, buf, buffsize);
835
836 if(nread < 0) {
837 int err = SSL_get_error(backend->handle, nread);
838
839 switch(err) {
840 case SSL_ERROR_ZERO_RETURN: /* no more data */
841 break;
842 case SSL_ERROR_WANT_READ:
843 case SSL_ERROR_WANT_WRITE:
844 /* there's data pending, re-invoke SSL_read() */
845 *curlcode = CURLE_AGAIN;
846 return -1;
847 default:
848 failf(data, "SSL read: %s, errno %d",
849 ERR_error_string(err, error_buffer), SOCKERRNO);
850 *curlcode = CURLE_RECV_ERROR;
851 return -1;
852 }
853 }
854 return nread;
855 }
856
857
wolfssl_session_free(void * ptr)858 static void wolfssl_session_free(void *ptr)
859 {
860 (void)ptr;
861 /* wolfSSL reuses sessions on own, no free */
862 }
863
864
wolfssl_version(char * buffer,size_t size)865 static size_t wolfssl_version(char *buffer, size_t size)
866 {
867 #if LIBWOLFSSL_VERSION_HEX >= 0x03006000
868 return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
869 #elif defined(WOLFSSL_VERSION)
870 return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
871 #endif
872 }
873
874
wolfssl_init(void)875 static int wolfssl_init(void)
876 {
877 #ifdef OPENSSL_EXTRA
878 Curl_tls_keylog_open();
879 #endif
880 return (wolfSSL_Init() == SSL_SUCCESS);
881 }
882
883
wolfssl_cleanup(void)884 static void wolfssl_cleanup(void)
885 {
886 wolfSSL_Cleanup();
887 #ifdef OPENSSL_EXTRA
888 Curl_tls_keylog_close();
889 #endif
890 }
891
892
wolfssl_data_pending(const struct connectdata * conn,int connindex)893 static bool wolfssl_data_pending(const struct connectdata *conn,
894 int connindex)
895 {
896 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
897 struct ssl_backend_data *backend = connssl->backend;
898 if(backend->handle) /* SSL is in use */
899 return (0 != SSL_pending(backend->handle)) ? TRUE : FALSE;
900 else
901 return FALSE;
902 }
903
904
905 /*
906 * This function is called to shut down the SSL layer but keep the
907 * socket open (CCC - Clear Command Channel)
908 */
wolfssl_shutdown(struct Curl_easy * data,struct connectdata * conn,int sockindex)909 static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
910 int sockindex)
911 {
912 int retval = 0;
913 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
914 struct ssl_backend_data *backend = connssl->backend;
915
916 (void) data;
917
918 if(backend->handle) {
919 SSL_free(backend->handle);
920 backend->handle = NULL;
921 }
922 return retval;
923 }
924
925
926 static CURLcode
wolfssl_connect_common(struct Curl_easy * data,struct connectdata * conn,int sockindex,bool nonblocking,bool * done)927 wolfssl_connect_common(struct Curl_easy *data,
928 struct connectdata *conn,
929 int sockindex,
930 bool nonblocking,
931 bool *done)
932 {
933 CURLcode result;
934 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
935 curl_socket_t sockfd = conn->sock[sockindex];
936 int what;
937
938 /* check if the connection has already been established */
939 if(ssl_connection_complete == connssl->state) {
940 *done = TRUE;
941 return CURLE_OK;
942 }
943
944 if(ssl_connect_1 == connssl->connecting_state) {
945 /* Find out how much more time we're allowed */
946 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
947
948 if(timeout_ms < 0) {
949 /* no need to continue if time already is up */
950 failf(data, "SSL connection timeout");
951 return CURLE_OPERATION_TIMEDOUT;
952 }
953
954 result = wolfssl_connect_step1(data, conn, sockindex);
955 if(result)
956 return result;
957 }
958
959 while(ssl_connect_2 == connssl->connecting_state ||
960 ssl_connect_2_reading == connssl->connecting_state ||
961 ssl_connect_2_writing == connssl->connecting_state) {
962
963 /* check allowed time left */
964 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
965
966 if(timeout_ms < 0) {
967 /* no need to continue if time already is up */
968 failf(data, "SSL connection timeout");
969 return CURLE_OPERATION_TIMEDOUT;
970 }
971
972 /* if ssl is expecting something, check if it's available. */
973 if(connssl->connecting_state == ssl_connect_2_reading
974 || connssl->connecting_state == ssl_connect_2_writing) {
975
976 curl_socket_t writefd = ssl_connect_2_writing ==
977 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
978 curl_socket_t readfd = ssl_connect_2_reading ==
979 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
980
981 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
982 nonblocking?0:timeout_ms);
983 if(what < 0) {
984 /* fatal error */
985 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
986 return CURLE_SSL_CONNECT_ERROR;
987 }
988 else if(0 == what) {
989 if(nonblocking) {
990 *done = FALSE;
991 return CURLE_OK;
992 }
993 else {
994 /* timeout */
995 failf(data, "SSL connection timeout");
996 return CURLE_OPERATION_TIMEDOUT;
997 }
998 }
999 /* socket is readable or writable */
1000 }
1001
1002 /* Run transaction, and return to the caller if it failed or if
1003 * this connection is part of a multi handle and this loop would
1004 * execute again. This permits the owner of a multi handle to
1005 * abort a connection attempt before step2 has completed while
1006 * ensuring that a client using select() or epoll() will always
1007 * have a valid fdset to wait on.
1008 */
1009 result = wolfssl_connect_step2(data, conn, sockindex);
1010 if(result || (nonblocking &&
1011 (ssl_connect_2 == connssl->connecting_state ||
1012 ssl_connect_2_reading == connssl->connecting_state ||
1013 ssl_connect_2_writing == connssl->connecting_state)))
1014 return result;
1015 } /* repeat step2 until all transactions are done. */
1016
1017 if(ssl_connect_3 == connssl->connecting_state) {
1018 result = wolfssl_connect_step3(data, conn, sockindex);
1019 if(result)
1020 return result;
1021 }
1022
1023 if(ssl_connect_done == connssl->connecting_state) {
1024 connssl->state = ssl_connection_complete;
1025 conn->recv[sockindex] = wolfssl_recv;
1026 conn->send[sockindex] = wolfssl_send;
1027 *done = TRUE;
1028 }
1029 else
1030 *done = FALSE;
1031
1032 /* Reset our connect state machine */
1033 connssl->connecting_state = ssl_connect_1;
1034
1035 return CURLE_OK;
1036 }
1037
1038
wolfssl_connect_nonblocking(struct Curl_easy * data,struct connectdata * conn,int sockindex,bool * done)1039 static CURLcode wolfssl_connect_nonblocking(struct Curl_easy *data,
1040 struct connectdata *conn,
1041 int sockindex, bool *done)
1042 {
1043 return wolfssl_connect_common(data, conn, sockindex, TRUE, done);
1044 }
1045
1046
wolfssl_connect(struct Curl_easy * data,struct connectdata * conn,int sockindex)1047 static CURLcode wolfssl_connect(struct Curl_easy *data,
1048 struct connectdata *conn, int sockindex)
1049 {
1050 CURLcode result;
1051 bool done = FALSE;
1052
1053 result = wolfssl_connect_common(data, conn, sockindex, FALSE, &done);
1054 if(result)
1055 return result;
1056
1057 DEBUGASSERT(done);
1058
1059 return CURLE_OK;
1060 }
1061
wolfssl_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1062 static CURLcode wolfssl_random(struct Curl_easy *data,
1063 unsigned char *entropy, size_t length)
1064 {
1065 WC_RNG rng;
1066 (void)data;
1067 if(wc_InitRng(&rng))
1068 return CURLE_FAILED_INIT;
1069 if(length > UINT_MAX)
1070 return CURLE_FAILED_INIT;
1071 if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
1072 return CURLE_FAILED_INIT;
1073 if(wc_FreeRng(&rng))
1074 return CURLE_FAILED_INIT;
1075 return CURLE_OK;
1076 }
1077
wolfssl_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t unused)1078 static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
1079 size_t tmplen,
1080 unsigned char *sha256sum /* output */,
1081 size_t unused)
1082 {
1083 wc_Sha256 SHA256pw;
1084 (void)unused;
1085 wc_InitSha256(&SHA256pw);
1086 wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
1087 wc_Sha256Final(&SHA256pw, sha256sum);
1088 return CURLE_OK;
1089 }
1090
wolfssl_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)1091 static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
1092 CURLINFO info UNUSED_PARAM)
1093 {
1094 struct ssl_backend_data *backend = connssl->backend;
1095 (void)info;
1096 return backend->handle;
1097 }
1098
1099 const struct Curl_ssl Curl_ssl_wolfssl = {
1100 { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
1101
1102 #ifdef KEEP_PEER_CERT
1103 SSLSUPP_PINNEDPUBKEY |
1104 #endif
1105 SSLSUPP_SSL_CTX,
1106
1107 sizeof(struct ssl_backend_data),
1108
1109 wolfssl_init, /* init */
1110 wolfssl_cleanup, /* cleanup */
1111 wolfssl_version, /* version */
1112 Curl_none_check_cxn, /* check_cxn */
1113 wolfssl_shutdown, /* shutdown */
1114 wolfssl_data_pending, /* data_pending */
1115 wolfssl_random, /* random */
1116 Curl_none_cert_status_request, /* cert_status_request */
1117 wolfssl_connect, /* connect */
1118 wolfssl_connect_nonblocking, /* connect_nonblocking */
1119 Curl_ssl_getsock, /* getsock */
1120 wolfssl_get_internals, /* get_internals */
1121 wolfssl_close, /* close_one */
1122 Curl_none_close_all, /* close_all */
1123 wolfssl_session_free, /* session_free */
1124 Curl_none_set_engine, /* set_engine */
1125 Curl_none_set_engine_default, /* set_engine_default */
1126 Curl_none_engines_list, /* engines_list */
1127 Curl_none_false_start, /* false_start */
1128 wolfssl_sha256sum, /* sha256sum */
1129 NULL, /* associate_connection */
1130 NULL /* disassociate_connection */
1131 };
1132
1133 #endif
1134