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