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