xref: /curl/lib/vtls/wolfssl.c (revision 3a35901a)
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 #if LIBWOLFSSL_VERSION_HEX < 0x03004006 /* wolfSSL 3.4.6 (2015) */
40 #error "wolfSSL version should be at least 3.4.6"
41 #endif
42 
43 /* To determine what functions are available we rely on one or both of:
44    - the user's options.h generated by wolfSSL
45    - the symbols detected by curl's configure
46    Since they are markedly different from one another, and one or the other may
47    not be available, we do some checking below to bring things in sync. */
48 
49 /* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
50 #ifndef HAVE_ALPN
51 #ifdef HAVE_WOLFSSL_USEALPN
52 #define HAVE_ALPN
53 #endif
54 #endif
55 
56 #include <limits.h>
57 
58 #include "urldata.h"
59 #include "sendf.h"
60 #include "inet_pton.h"
61 #include "vtls.h"
62 #include "vtls_int.h"
63 #include "keylog.h"
64 #include "parsedate.h"
65 #include "connect.h" /* for the connect timeout */
66 #include "select.h"
67 #include "strcase.h"
68 #include "x509asn1.h"
69 #include "curl_printf.h"
70 #include "multiif.h"
71 
72 #include <wolfssl/openssl/ssl.h>
73 #include <wolfssl/ssl.h>
74 #include <wolfssl/error-ssl.h>
75 #include "wolfssl.h"
76 
77 /* The last #include files should be: */
78 #include "curl_memory.h"
79 #include "memdebug.h"
80 
81 #ifdef USE_ECH
82 # include "curl_base64.h"
83 # define ECH_ENABLED(__data__) \
84     (__data__->set.tls_ech && \
85      !(__data__->set.tls_ech & CURLECH_DISABLE)\
86     )
87 #endif /* USE_ECH */
88 
89 /* KEEP_PEER_CERT is a product of the presence of build time symbol
90    OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
91    in wolfSSL's settings.h, and the latter two are build time symbols in
92    options.h. */
93 #ifndef KEEP_PEER_CERT
94 #if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
95     (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
96 #define KEEP_PEER_CERT
97 #endif
98 #endif
99 
100 #ifdef HAVE_WOLFSSL_BIO
101 #define USE_BIO_CHAIN
102 #ifdef HAVE_WOLFSSL_FULL_BIO
103 #define USE_FULL_BIO
104 #else /* HAVE_WOLFSSL_FULL_BIO */
105 #undef USE_FULL_BIO
106 #endif
107 /* wolfSSL 5.7.4 and older do not have these symbols, but only the
108  * OpenSSL ones. */
109 #ifndef WOLFSSL_BIO_CTRL_GET_CLOSE
110 #define WOLFSSL_BIO_CTRL_GET_CLOSE    BIO_CTRL_GET_CLOSE
111 #define WOLFSSL_BIO_CTRL_SET_CLOSE    BIO_CTRL_SET_CLOSE
112 #define WOLFSSL_BIO_CTRL_FLUSH        BIO_CTRL_FLUSH
113 #define WOLFSSL_BIO_CTRL_DUP          BIO_CTRL_DUP
114 #define wolfSSL_BIO_set_retry_write   BIO_set_retry_write
115 #define wolfSSL_BIO_set_retry_read    BIO_set_retry_read
116 #endif /* !WOLFSSL_BIO_CTRL_GET_CLOSE */
117 
118 #else /* HAVE_WOLFSSL_BIO */
119 #undef USE_BIO_CHAIN
120 #endif
121 
122 #ifdef OPENSSL_EXTRA
123 /*
124  * Availability note:
125  * The TLS 1.3 secret callback (wolfSSL_set_tls13_secret_cb) was added in
126  * wolfSSL 4.4.0, but requires the -DHAVE_SECRET_CALLBACK build option. If that
127  * option is not set, then TLS 1.3 will not be logged.
128  * For TLS 1.2 and before, we use wolfSSL_get_keys().
129  * SSL_get_client_random and wolfSSL_get_keys require OPENSSL_EXTRA
130  * (--enable-opensslextra or --enable-all).
131  */
132 #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
133 static int
wolfssl_tls13_secret_callback(SSL * ssl,int id,const unsigned char * secret,int secretSz,void * ctx)134 wolfssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret,
135                               int secretSz, void *ctx)
136 {
137   const char *label;
138   unsigned char client_random[SSL3_RANDOM_SIZE];
139   (void)ctx;
140 
141   if(!ssl || !Curl_tls_keylog_enabled()) {
142     return 0;
143   }
144 
145   switch(id) {
146   case CLIENT_EARLY_TRAFFIC_SECRET:
147     label = "CLIENT_EARLY_TRAFFIC_SECRET";
148     break;
149   case CLIENT_HANDSHAKE_TRAFFIC_SECRET:
150     label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
151     break;
152   case SERVER_HANDSHAKE_TRAFFIC_SECRET:
153     label = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
154     break;
155   case CLIENT_TRAFFIC_SECRET:
156     label = "CLIENT_TRAFFIC_SECRET_0";
157     break;
158   case SERVER_TRAFFIC_SECRET:
159     label = "SERVER_TRAFFIC_SECRET_0";
160     break;
161   case EARLY_EXPORTER_SECRET:
162     label = "EARLY_EXPORTER_SECRET";
163     break;
164   case EXPORTER_SECRET:
165     label = "EXPORTER_SECRET";
166     break;
167   default:
168     return 0;
169   }
170 
171   if(SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE) == 0) {
172     /* Should never happen as wolfSSL_KeepArrays() was called before. */
173     return 0;
174   }
175 
176   Curl_tls_keylog_write(label, client_random, secret, secretSz);
177   return 0;
178 }
179 #endif /* defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) */
180 
181 static void
wolfssl_log_tls12_secret(WOLFSSL * ssl)182 wolfssl_log_tls12_secret(WOLFSSL *ssl)
183 {
184   unsigned char *ms, *sr, *cr;
185   unsigned int msLen, srLen, crLen, i, x = 0;
186 
187 #if LIBWOLFSSL_VERSION_HEX >= 0x0300d000 /* >= 3.13.0 */
188   /* wolfSSL_GetVersion is available since 3.13, we use it instead of
189    * SSL_version since the latter relies on OPENSSL_ALL (--enable-opensslall or
190    * --enable-all). Failing to perform this check could result in an unusable
191    * key log line when TLS 1.3 is actually negotiated. */
192   switch(wolfSSL_GetVersion(ssl)) {
193   case WOLFSSL_SSLV3:
194   case WOLFSSL_TLSV1:
195   case WOLFSSL_TLSV1_1:
196   case WOLFSSL_TLSV1_2:
197     break;
198   default:
199     /* TLS 1.3 does not use this mechanism, the "master secret" returned below
200      * is not directly usable. */
201     return;
202   }
203 #endif
204 
205   if(wolfSSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) !=
206      WOLFSSL_SUCCESS) {
207     return;
208   }
209 
210   /* Check for a missing master secret and skip logging. That can happen if
211    * curl rejects the server certificate and aborts the handshake.
212    */
213   for(i = 0; i < msLen; i++) {
214     x |= ms[i];
215   }
216   if(x == 0) {
217     return;
218   }
219 
220   Curl_tls_keylog_write("CLIENT_RANDOM", cr, ms, msLen);
221 }
222 #endif /* OPENSSL_EXTRA */
223 
wolfssl_do_file_type(const char * type)224 static int wolfssl_do_file_type(const char *type)
225 {
226   if(!type || !type[0])
227     return WOLFSSL_FILETYPE_PEM;
228   if(strcasecompare(type, "PEM"))
229     return WOLFSSL_FILETYPE_PEM;
230   if(strcasecompare(type, "DER"))
231     return WOLFSSL_FILETYPE_ASN1;
232   return -1;
233 }
234 
235 #ifdef WOLFSSL_HAVE_KYBER
236 struct group_name_map {
237   const word16 group;
238   const char   *name;
239 };
240 
241 static const struct group_name_map gnm[] = {
242   { WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" },
243   { WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" },
244   { WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" },
245   { WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" },
246   { WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" },
247   { WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" },
248   { 0, NULL }
249 };
250 #endif
251 
252 #ifdef USE_BIO_CHAIN
253 
wolfssl_bio_cf_create(WOLFSSL_BIO * bio)254 static int wolfssl_bio_cf_create(WOLFSSL_BIO *bio)
255 {
256 #ifdef USE_FULL_BIO
257   wolfSSL_BIO_set_shutdown(bio, 1);
258 #endif
259   wolfSSL_BIO_set_data(bio, NULL);
260   return 1;
261 }
262 
wolfssl_bio_cf_destroy(WOLFSSL_BIO * bio)263 static int wolfssl_bio_cf_destroy(WOLFSSL_BIO *bio)
264 {
265   if(!bio)
266     return 0;
267   return 1;
268 }
269 
wolfssl_bio_cf_ctrl(WOLFSSL_BIO * bio,int cmd,long num,void * ptr)270 static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
271 {
272   struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
273   long ret = 1;
274 
275   (void)cf;
276   (void)ptr;
277   (void)num;
278   switch(cmd) {
279   case WOLFSSL_BIO_CTRL_GET_CLOSE:
280 #ifdef USE_FULL_BIO
281     ret = (long)wolfSSL_BIO_get_shutdown(bio);
282 #else
283     ret = 0;
284 #endif
285     break;
286   case WOLFSSL_BIO_CTRL_SET_CLOSE:
287 #ifdef USE_FULL_BIO
288     wolfSSL_BIO_set_shutdown(bio, (int)num);
289 #endif
290     break;
291   case WOLFSSL_BIO_CTRL_FLUSH:
292     /* we do no delayed writes, but if we ever would, this
293      * needs to trigger it. */
294     ret = 1;
295     break;
296   case WOLFSSL_BIO_CTRL_DUP:
297     ret = 1;
298     break;
299 #ifdef WOLFSSL_BIO_CTRL_EOF
300   case WOLFSSL_BIO_CTRL_EOF:
301     /* EOF has been reached on input? */
302     return (!cf->next || !cf->next->connected);
303 #endif
304   default:
305     ret = 0;
306     break;
307   }
308   return ret;
309 }
310 
wolfssl_bio_cf_out_write(WOLFSSL_BIO * bio,const char * buf,int blen)311 static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio,
312                                     const char *buf, int blen)
313 {
314   struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
315   struct ssl_connect_data *connssl = cf->ctx;
316   struct wolfssl_ctx *backend =
317     (struct wolfssl_ctx *)connssl->backend;
318   struct Curl_easy *data = CF_DATA_CURRENT(cf);
319   ssize_t nwritten, skiplen = 0;
320   CURLcode result = CURLE_OK;
321 
322   DEBUGASSERT(data);
323   if(backend->shutting_down && backend->io_send_blocked_len &&
324      (backend->io_send_blocked_len < blen)) {
325     /* bug in wolfSSL: <https://github.com/wolfSSL/wolfssl/issues/7784>
326      * It adds the close notify message again every time we retry
327      * sending during shutdown. */
328     CURL_TRC_CF(data, cf, "bio_write, shutdown restrict send of %d"
329                 " to %d bytes", blen, backend->io_send_blocked_len);
330     skiplen = (ssize_t)(blen - backend->io_send_blocked_len);
331     blen = backend->io_send_blocked_len;
332   }
333   nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &result);
334   backend->io_result = result;
335   CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
336               blen, nwritten, result);
337 #ifdef USE_FULL_BIO
338   wolfSSL_BIO_clear_retry_flags(bio);
339 #endif
340   if(nwritten < 0 && CURLE_AGAIN == result) {
341     wolfSSL_BIO_set_retry_write(bio);
342     if(backend->shutting_down && !backend->io_send_blocked_len)
343       backend->io_send_blocked_len = blen;
344   }
345   else if(!result && skiplen)
346     nwritten += skiplen;
347   return (int)nwritten;
348 }
349 
wolfssl_bio_cf_in_read(WOLFSSL_BIO * bio,char * buf,int blen)350 static int wolfssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
351 {
352   struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
353   struct ssl_connect_data *connssl = cf->ctx;
354   struct wolfssl_ctx *backend =
355     (struct wolfssl_ctx *)connssl->backend;
356   struct Curl_easy *data = CF_DATA_CURRENT(cf);
357   ssize_t nread;
358   CURLcode result = CURLE_OK;
359 
360   DEBUGASSERT(data);
361   /* OpenSSL catches this case, so should we. */
362   if(!buf)
363     return 0;
364 
365   nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
366   backend->io_result = result;
367   CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %zd, %d", blen, nread, result);
368 #ifdef USE_FULL_BIO
369   wolfSSL_BIO_clear_retry_flags(bio);
370 #endif
371   if(nread < 0 && CURLE_AGAIN == result)
372     wolfSSL_BIO_set_retry_read(bio);
373   else if(nread == 0)
374     connssl->peer_closed = TRUE;
375   return (int)nread;
376 }
377 
378 static WOLFSSL_BIO_METHOD *wolfssl_bio_cf_method = NULL;
379 
wolfssl_bio_cf_init_methods(void)380 static void wolfssl_bio_cf_init_methods(void)
381 {
382   wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(WOLFSSL_BIO_MEMORY,
383                                                "wolfSSL CF BIO");
384   wolfSSL_BIO_meth_set_write(wolfssl_bio_cf_method, &wolfssl_bio_cf_out_write);
385   wolfSSL_BIO_meth_set_read(wolfssl_bio_cf_method, &wolfssl_bio_cf_in_read);
386   wolfSSL_BIO_meth_set_ctrl(wolfssl_bio_cf_method, &wolfssl_bio_cf_ctrl);
387   wolfSSL_BIO_meth_set_create(wolfssl_bio_cf_method, &wolfssl_bio_cf_create);
388   wolfSSL_BIO_meth_set_destroy(wolfssl_bio_cf_method, &wolfssl_bio_cf_destroy);
389 }
390 
wolfssl_bio_cf_free_methods(void)391 static void wolfssl_bio_cf_free_methods(void)
392 {
393   wolfSSL_BIO_meth_free(wolfssl_bio_cf_method);
394 }
395 
396 #else /* USE_BIO_CHAIN */
397 
398 #define wolfssl_bio_cf_init_methods() Curl_nop_stmt
399 #define wolfssl_bio_cf_free_methods() Curl_nop_stmt
400 
401 #endif /* !USE_BIO_CHAIN */
402 
wolfssl_session_free(void * sdata,size_t slen)403 static void wolfssl_session_free(void *sdata, size_t slen)
404 {
405   (void)slen;
406   free(sdata);
407 }
408 
wssl_cache_session(struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,WOLFSSL_SESSION * session)409 CURLcode wssl_cache_session(struct Curl_cfilter *cf,
410                             struct Curl_easy *data,
411                             struct ssl_peer *peer,
412                             WOLFSSL_SESSION *session)
413 {
414   CURLcode result = CURLE_OK;
415   unsigned char *sdata = NULL;
416   unsigned int slen;
417 
418   if(!session)
419     goto out;
420 
421   slen = wolfSSL_i2d_SSL_SESSION(session, NULL);
422   if(slen <= 0) {
423     CURL_TRC_CF(data, cf, "fail to assess session length: %u", slen);
424     result = CURLE_FAILED_INIT;
425     goto out;
426   }
427   sdata = calloc(1, slen);
428   if(!sdata) {
429     failf(data, "unable to allocate session buffer of %u bytes", slen);
430     result = CURLE_OUT_OF_MEMORY;
431     goto out;
432   }
433   slen = wolfSSL_i2d_SSL_SESSION(session, &sdata);
434   if(slen <= 0) {
435     CURL_TRC_CF(data, cf, "fail to serialize session: %u", slen);
436     result = CURLE_FAILED_INIT;
437     goto out;
438   }
439 
440   Curl_ssl_sessionid_lock(data);
441   result = Curl_ssl_set_sessionid(cf, data, peer, NULL,
442                                   sdata, slen, wolfssl_session_free);
443   Curl_ssl_sessionid_unlock(data);
444   if(result)
445     failf(data, "failed to add new ssl session to cache (%d)", result);
446   else {
447     CURL_TRC_CF(data, cf, "added new session to cache");
448     sdata = NULL;
449   }
450 
451 out:
452   free(sdata);
453   return 0;
454 }
455 
wssl_vtls_new_session_cb(WOLFSSL * ssl,WOLFSSL_SESSION * session)456 static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session)
457 {
458   struct Curl_cfilter *cf;
459 
460   cf = (struct Curl_cfilter*)wolfSSL_get_app_data(ssl);
461   DEBUGASSERT(cf != NULL);
462   if(cf && session) {
463     struct ssl_connect_data *connssl = cf->ctx;
464     struct Curl_easy *data = CF_DATA_CURRENT(cf);
465     DEBUGASSERT(connssl);
466     DEBUGASSERT(data);
467     if(connssl && data) {
468       (void)wssl_cache_session(cf, data, &connssl->peer, session);
469     }
470   }
471   return 0;
472 }
473 
wssl_setup_session(struct Curl_cfilter * cf,struct Curl_easy * data,struct wolfssl_ctx * wss,struct ssl_peer * peer)474 CURLcode wssl_setup_session(struct Curl_cfilter *cf,
475                             struct Curl_easy *data,
476                             struct wolfssl_ctx *wss,
477                             struct ssl_peer *peer)
478 {
479   void *psdata;
480   const unsigned char *sdata = NULL;
481   size_t slen = 0;
482   CURLcode result = CURLE_OK;
483 
484   Curl_ssl_sessionid_lock(data);
485   if(!Curl_ssl_getsessionid(cf, data, peer, &psdata, &slen, NULL)) {
486     WOLFSSL_SESSION *session;
487     sdata = psdata;
488     session = wolfSSL_d2i_SSL_SESSION(NULL, &sdata, (long)slen);
489     if(session) {
490       int ret = wolfSSL_set_session(wss->handle, session);
491       if(ret != WOLFSSL_SUCCESS) {
492         Curl_ssl_delsessionid(data, psdata);
493         infof(data, "previous session not accepted (%d), "
494               "removing from cache", ret);
495       }
496       else
497         infof(data, "SSL reusing session ID");
498       wolfSSL_SESSION_free(session);
499     }
500     else {
501       failf(data, "could not decode previous session");
502     }
503   }
504   Curl_ssl_sessionid_unlock(data);
505   return result;
506 }
507 
populate_x509_store(struct Curl_cfilter * cf,struct Curl_easy * data,WOLFSSL_X509_STORE * store,struct wolfssl_ctx * wssl)508 static CURLcode populate_x509_store(struct Curl_cfilter *cf,
509                                     struct Curl_easy *data,
510                                     WOLFSSL_X509_STORE *store,
511                                     struct wolfssl_ctx *wssl)
512 {
513   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
514   const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
515   const char * const ssl_cafile =
516     /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
517     (ca_info_blob ? NULL : conn_config->CAfile);
518   const char * const ssl_capath = conn_config->CApath;
519   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
520   bool imported_native_ca = FALSE;
521 
522 #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS)
523   /* load native CA certificates */
524   if(ssl_config->native_ca_store) {
525     if(wolfSSL_CTX_load_system_CA_certs(wssl->ctx) != WOLFSSL_SUCCESS) {
526       infof(data, "error importing native CA store, continuing anyway");
527     }
528     else {
529       imported_native_ca = TRUE;
530       infof(data, "successfully imported native CA store");
531       wssl->x509_store_setup = TRUE;
532     }
533   }
534 #endif /* !NO_FILESYSTEM */
535 
536   /* load certificate blob */
537   if(ca_info_blob) {
538     if(wolfSSL_CTX_load_verify_buffer(wssl->ctx, ca_info_blob->data,
539                                       (long)ca_info_blob->len,
540                                       WOLFSSL_FILETYPE_PEM) !=
541        WOLFSSL_SUCCESS) {
542       if(imported_native_ca) {
543         infof(data, "error importing CA certificate blob, continuing anyway");
544       }
545       else {
546         failf(data, "error importing CA certificate blob");
547         return CURLE_SSL_CACERT_BADFILE;
548       }
549     }
550     else {
551       infof(data, "successfully imported CA certificate blob");
552       wssl->x509_store_setup = TRUE;
553     }
554   }
555 
556 #ifndef NO_FILESYSTEM
557   /* load trusted cacert from file if not blob */
558 
559   CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d",
560               ssl_cafile ? ssl_cafile : "none", !!ca_info_blob);
561   if(!store)
562     return CURLE_OUT_OF_MEMORY;
563 
564   if((ssl_cafile || ssl_capath) && (!wssl->x509_store_setup)) {
565     int rc =
566       wolfSSL_CTX_load_verify_locations_ex(wssl->ctx,
567                                            ssl_cafile,
568                                            ssl_capath,
569                                            WOLFSSL_LOAD_FLAG_IGNORE_ERR);
570     if(WOLFSSL_SUCCESS != rc) {
571       if(conn_config->verifypeer) {
572         /* Fail if we insist on successfully verifying the server. */
573         failf(data, "error setting certificate verify locations:"
574               " CAfile: %s CApath: %s",
575               ssl_cafile ? ssl_cafile : "none",
576               ssl_capath ? ssl_capath : "none");
577         return CURLE_SSL_CACERT_BADFILE;
578       }
579       else {
580         /* Just continue with a warning if no strict certificate
581            verification is required. */
582         infof(data, "error setting certificate verify locations,"
583               " continuing anyway:");
584       }
585     }
586     else {
587       /* Everything is fine. */
588       infof(data, "successfully set certificate verify locations:");
589     }
590     infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
591     infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
592   }
593 #endif
594   (void)store;
595   wssl->x509_store_setup = TRUE;
596   return CURLE_OK;
597 }
598 
599 /* key to use at `multi->proto_hash` */
600 #define MPROTO_WSSL_X509_KEY   "tls:wssl:x509:share"
601 
602 struct wssl_x509_share {
603   char *CAfile;         /* CAfile path used to generate X509 store */
604   WOLFSSL_X509_STORE *store; /* cached X509 store or NULL if none */
605   struct curltime time; /* when the cached store was created */
606 };
607 
wssl_x509_share_free(void * key,size_t key_len,void * p)608 static void wssl_x509_share_free(void *key, size_t key_len, void *p)
609 {
610   struct wssl_x509_share *share = p;
611   DEBUGASSERT(key_len == (sizeof(MPROTO_WSSL_X509_KEY)-1));
612   DEBUGASSERT(!memcmp(MPROTO_WSSL_X509_KEY, key, key_len));
613   (void)key;
614   (void)key_len;
615   if(share->store) {
616     wolfSSL_X509_STORE_free(share->store);
617   }
618   free(share->CAfile);
619   free(share);
620 }
621 
622 static bool
cached_x509_store_expired(const struct Curl_easy * data,const struct wssl_x509_share * mb)623 cached_x509_store_expired(const struct Curl_easy *data,
624                           const struct wssl_x509_share *mb)
625 {
626   const struct ssl_general_config *cfg = &data->set.general_ssl;
627   struct curltime now = Curl_now();
628   timediff_t elapsed_ms = Curl_timediff(now, mb->time);
629   timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
630 
631   if(timeout_ms < 0)
632     return FALSE;
633 
634   return elapsed_ms >= timeout_ms;
635 }
636 
637 static bool
cached_x509_store_different(struct Curl_cfilter * cf,const struct wssl_x509_share * mb)638 cached_x509_store_different(struct Curl_cfilter *cf,
639                             const struct wssl_x509_share *mb)
640 {
641   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
642   if(!mb->CAfile || !conn_config->CAfile)
643     return mb->CAfile != conn_config->CAfile;
644 
645   return strcmp(mb->CAfile, conn_config->CAfile);
646 }
647 
get_cached_x509_store(struct Curl_cfilter * cf,const struct Curl_easy * data)648 static WOLFSSL_X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
649                                                  const struct Curl_easy *data)
650 {
651   struct Curl_multi *multi = data->multi;
652   struct wssl_x509_share *share;
653   WOLFSSL_X509_STORE *store = NULL;
654 
655   DEBUGASSERT(multi);
656   share = multi ? Curl_hash_pick(&multi->proto_hash,
657                                  (void *)MPROTO_WSSL_X509_KEY,
658                                  sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL;
659   if(share && share->store &&
660      !cached_x509_store_expired(data, share) &&
661      !cached_x509_store_different(cf, share)) {
662     store = share->store;
663   }
664 
665   return store;
666 }
667 
set_cached_x509_store(struct Curl_cfilter * cf,const struct Curl_easy * data,WOLFSSL_X509_STORE * store)668 static void set_cached_x509_store(struct Curl_cfilter *cf,
669                                   const struct Curl_easy *data,
670                                   WOLFSSL_X509_STORE *store)
671 {
672   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
673   struct Curl_multi *multi = data->multi;
674   struct wssl_x509_share *share;
675 
676   DEBUGASSERT(multi);
677   if(!multi)
678     return;
679   share = Curl_hash_pick(&multi->proto_hash,
680                          (void *)MPROTO_WSSL_X509_KEY,
681                          sizeof(MPROTO_WSSL_X509_KEY)-1);
682 
683   if(!share) {
684     share = calloc(1, sizeof(*share));
685     if(!share)
686       return;
687     if(!Curl_hash_add2(&multi->proto_hash,
688                        (void *)MPROTO_WSSL_X509_KEY,
689                        sizeof(MPROTO_WSSL_X509_KEY)-1,
690                        share, wssl_x509_share_free)) {
691       free(share);
692       return;
693     }
694   }
695 
696   if(wolfSSL_X509_STORE_up_ref(store)) {
697     char *CAfile = NULL;
698 
699     if(conn_config->CAfile) {
700       CAfile = strdup(conn_config->CAfile);
701       if(!CAfile) {
702         wolfSSL_X509_STORE_free(store);
703         return;
704       }
705     }
706 
707     if(share->store) {
708       wolfSSL_X509_STORE_free(share->store);
709       free(share->CAfile);
710     }
711 
712     share->time = Curl_now();
713     share->store = store;
714     share->CAfile = CAfile;
715   }
716 }
717 
Curl_wssl_setup_x509_store(struct Curl_cfilter * cf,struct Curl_easy * data,struct wolfssl_ctx * wssl)718 CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf,
719                                     struct Curl_easy *data,
720                                     struct wolfssl_ctx *wssl)
721 {
722   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
723   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
724   CURLcode result = CURLE_OK;
725   WOLFSSL_X509_STORE *cached_store;
726   bool cache_criteria_met;
727 
728   /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
729      or no source is provided and we are falling back to wolfSSL's built-in
730      default. */
731   cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
732     conn_config->verifypeer &&
733     !conn_config->CApath &&
734     !conn_config->ca_info_blob &&
735     !ssl_config->primary.CRLfile &&
736     !ssl_config->native_ca_store;
737 
738   cached_store = cache_criteria_met ? get_cached_x509_store(cf, data) : NULL;
739   if(cached_store && wolfSSL_CTX_get_cert_store(wssl->ctx) == cached_store) {
740     /* The cached store is already in use, do nothing. */
741   }
742   else if(cached_store && wolfSSL_X509_STORE_up_ref(cached_store)) {
743     wolfSSL_CTX_set_cert_store(wssl->ctx, cached_store);
744   }
745   else if(cache_criteria_met) {
746     /* wolfSSL's initial store in CTX is not shareable by default.
747      * Make a new one, suitable for adding to the cache. See #14278 */
748     WOLFSSL_X509_STORE *store = wolfSSL_X509_STORE_new();
749     if(!store) {
750       failf(data, "SSL: could not create a X509 store");
751       return CURLE_OUT_OF_MEMORY;
752     }
753     wolfSSL_CTX_set_cert_store(wssl->ctx, store);
754 
755     result = populate_x509_store(cf, data, store, wssl);
756     if(!result) {
757       set_cached_x509_store(cf, data, store);
758     }
759   }
760   else {
761    /* We never share the CTX's store, use it. */
762    WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx);
763    result = populate_x509_store(cf, data, store, wssl);
764   }
765 
766   return result;
767 }
768 
769 #ifdef WOLFSSL_TLS13
770 static CURLcode
wssl_add_default_ciphers(bool tls13,struct dynbuf * buf)771 wssl_add_default_ciphers(bool tls13, struct dynbuf *buf)
772 {
773   int i;
774   char *str;
775 
776   for(i = 0; (str = wolfSSL_get_cipher_list(i)); i++) {
777     size_t n;
778     if((strncmp(str, "TLS13", 5) == 0) != tls13)
779       continue;
780 
781     /* if there already is data in the string, add colon separator */
782     if(Curl_dyn_len(buf)) {
783       CURLcode result = Curl_dyn_addn(buf, ":", 1);
784       if(result)
785         return result;
786     }
787 
788     n = strlen(str);
789     if(Curl_dyn_addn(buf, str, n))
790       return CURLE_OUT_OF_MEMORY;
791   }
792 
793   return CURLE_OK;
794 }
795 #endif
796 
797 /* 4.2.0 (2019) */
798 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 || !defined(OPENSSL_EXTRA)
799 static int
wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX * ctx,int version)800 wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version)
801 {
802   int res;
803   switch(version) {
804   default:
805   case TLS1_VERSION:
806     res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1);
807     if(res == WOLFSSL_SUCCESS)
808       return res;
809     FALLTHROUGH();
810   case TLS1_1_VERSION:
811     res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_1);
812     if(res == WOLFSSL_SUCCESS)
813       return res;
814     FALLTHROUGH();
815   case TLS1_2_VERSION:
816     res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_2);
817 #ifdef WOLFSSL_TLS13
818     if(res == WOLFSSL_SUCCESS)
819       return res;
820     FALLTHROUGH();
821   case TLS1_3_VERSION:
822     res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_3);
823 #endif
824   }
825   return res;
826 }
827 static int
wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX * ctx,int version)828 wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int version)
829 {
830   (void) ctx, (void) version;
831   return WOLFSSL_NOT_IMPLEMENTED;
832 }
833 #define wolfSSL_CTX_set_min_proto_version wssl_legacy_CTX_set_min_proto_version
834 #define wolfSSL_CTX_set_max_proto_version wssl_legacy_CTX_set_max_proto_version
835 #endif
836 
837 /*
838  * This function loads all the client/CA certificates and CRLs. Setup the TLS
839  * layer and do all necessary magic.
840  */
841 static CURLcode
wolfssl_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)842 wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
843 {
844   int res;
845   char *curves;
846   struct ssl_connect_data *connssl = cf->ctx;
847   struct wolfssl_ctx *backend =
848     (struct wolfssl_ctx *)connssl->backend;
849   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
850   const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
851   WOLFSSL_METHOD* req_method = NULL;
852 #ifdef WOLFSSL_HAVE_KYBER
853   word16 pqkem = 0;
854   size_t idx = 0;
855 #endif
856 
857   DEBUGASSERT(backend);
858 
859   if(connssl->state == ssl_connection_complete)
860     return CURLE_OK;
861 
862 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 /* 4.2.0 (2019) */
863   req_method = wolfSSLv23_client_method();
864 #else
865   req_method = wolfTLS_client_method();
866 #endif
867   if(!req_method) {
868     failf(data, "wolfSSL: could not create a client method");
869     return CURLE_OUT_OF_MEMORY;
870   }
871 
872   if(backend->ctx)
873     wolfSSL_CTX_free(backend->ctx);
874 
875   backend->ctx = wolfSSL_CTX_new(req_method);
876   if(!backend->ctx) {
877     failf(data, "wolfSSL: could not create a context");
878     return CURLE_OUT_OF_MEMORY;
879   }
880 
881   switch(conn_config->version) {
882   case CURL_SSLVERSION_DEFAULT:
883   case CURL_SSLVERSION_TLSv1:
884   case CURL_SSLVERSION_TLSv1_0:
885     res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_VERSION);
886     break;
887   case CURL_SSLVERSION_TLSv1_1:
888     res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_1_VERSION);
889     break;
890   case CURL_SSLVERSION_TLSv1_2:
891     res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_2_VERSION);
892     break;
893 #ifdef WOLFSSL_TLS13
894   case CURL_SSLVERSION_TLSv1_3:
895     res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_3_VERSION);
896     break;
897 #endif
898   default:
899     failf(data, "wolfSSL: unsupported minimum TLS version value");
900     return CURLE_SSL_CONNECT_ERROR;
901   }
902   if(res != WOLFSSL_SUCCESS) {
903     failf(data, "wolfSSL: failed set the minimum TLS version");
904     return CURLE_SSL_CONNECT_ERROR;
905   }
906 
907   switch(conn_config->version_max) {
908 #ifdef WOLFSSL_TLS13
909   case CURL_SSLVERSION_MAX_TLSv1_3:
910     res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);
911     break;
912 #endif
913   case CURL_SSLVERSION_MAX_TLSv1_2:
914     res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_2_VERSION);
915     break;
916   case CURL_SSLVERSION_MAX_TLSv1_1:
917     res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_1_VERSION);
918     break;
919   case CURL_SSLVERSION_MAX_TLSv1_0:
920     res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_VERSION);
921     break;
922   case CURL_SSLVERSION_MAX_DEFAULT:
923   case CURL_SSLVERSION_MAX_NONE:
924     res = WOLFSSL_SUCCESS;
925     break;
926   default:
927     failf(data, "wolfSSL: unsupported maximum TLS version value");
928     return CURLE_SSL_CONNECT_ERROR;
929   }
930   if(res != WOLFSSL_SUCCESS) {
931     failf(data, "wolfSSL: failed set the maximum TLS version");
932     return CURLE_SSL_CONNECT_ERROR;
933   }
934 
935 #ifndef WOLFSSL_TLS13
936   {
937     char *ciphers = conn_config->cipher_list;
938     if(ciphers) {
939       if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
940         failf(data, "failed setting cipher list: %s", ciphers);
941         return CURLE_SSL_CIPHER;
942       }
943       infof(data, "Cipher selection: %s", ciphers);
944     }
945   }
946 #else
947 #define MAX_CIPHER_LEN 4096
948   if(conn_config->cipher_list || conn_config->cipher_list13) {
949     const char *ciphers12 = conn_config->cipher_list;
950     const char *ciphers13 = conn_config->cipher_list13;
951     struct dynbuf c;
952     CURLcode result;
953     Curl_dyn_init(&c, MAX_CIPHER_LEN);
954 
955     if(ciphers13)
956       result = Curl_dyn_add(&c, ciphers13);
957     else
958       result = wssl_add_default_ciphers(TRUE, &c);
959 
960     if(!result) {
961       if(ciphers12) {
962         if(Curl_dyn_len(&c))
963           result = Curl_dyn_addn(&c, ":", 1);
964         if(!result)
965           result = Curl_dyn_add(&c, ciphers12);
966       }
967       else
968         result = wssl_add_default_ciphers(FALSE, &c);
969     }
970     if(result)
971       return result;
972 
973     if(!wolfSSL_CTX_set_cipher_list(backend->ctx, Curl_dyn_ptr(&c))) {
974       failf(data, "failed setting cipher list: %s", Curl_dyn_ptr(&c));
975       Curl_dyn_free(&c);
976       return CURLE_SSL_CIPHER;
977     }
978     infof(data, "Cipher selection: %s", Curl_dyn_ptr(&c));
979     Curl_dyn_free(&c);
980   }
981 #endif
982 
983   curves = conn_config->curves;
984   if(curves) {
985 
986 #ifdef WOLFSSL_HAVE_KYBER
987     for(idx = 0; gnm[idx].name != NULL; idx++) {
988       if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) {
989         pqkem = gnm[idx].group;
990         break;
991       }
992     }
993 
994     if(pqkem == 0)
995 #endif
996     {
997       if(!wolfSSL_CTX_set1_curves_list(backend->ctx, curves)) {
998         failf(data, "failed setting curves list: '%s'", curves);
999         return CURLE_SSL_CIPHER;
1000       }
1001     }
1002   }
1003 
1004   /* Load the client certificate, and private key */
1005 #ifndef NO_FILESYSTEM
1006   if(ssl_config->primary.cert_blob || ssl_config->primary.clientcert) {
1007     const char *cert_file = ssl_config->primary.clientcert;
1008     const char *key_file = ssl_config->key;
1009     const struct curl_blob *cert_blob = ssl_config->primary.cert_blob;
1010     const struct curl_blob *key_blob = ssl_config->key_blob;
1011     int file_type = wolfssl_do_file_type(ssl_config->cert_type);
1012     int rc;
1013 
1014     switch(file_type) {
1015     case WOLFSSL_FILETYPE_PEM:
1016       rc = cert_blob ?
1017         wolfSSL_CTX_use_certificate_chain_buffer(backend->ctx,
1018                                                  cert_blob->data,
1019                                                  (long)cert_blob->len) :
1020         wolfSSL_CTX_use_certificate_chain_file(backend->ctx, cert_file);
1021       break;
1022     case WOLFSSL_FILETYPE_ASN1:
1023       rc = cert_blob ?
1024         wolfSSL_CTX_use_certificate_buffer(backend->ctx, cert_blob->data,
1025                                            (long)cert_blob->len, file_type) :
1026         wolfSSL_CTX_use_certificate_file(backend->ctx, cert_file, file_type);
1027       break;
1028     default:
1029       failf(data, "unknown cert type");
1030       return CURLE_BAD_FUNCTION_ARGUMENT;
1031     }
1032     if(rc != 1) {
1033       failf(data, "unable to use client certificate");
1034       return CURLE_SSL_CONNECT_ERROR;
1035     }
1036 
1037     if(!key_blob && !key_file) {
1038       key_blob = cert_blob;
1039       key_file = cert_file;
1040     }
1041     else
1042       file_type = wolfssl_do_file_type(ssl_config->key_type);
1043 
1044     rc = key_blob ?
1045       wolfSSL_CTX_use_PrivateKey_buffer(backend->ctx, key_blob->data,
1046                                         (long)key_blob->len, file_type) :
1047       wolfSSL_CTX_use_PrivateKey_file(backend->ctx, key_file, file_type);
1048     if(rc != 1) {
1049       failf(data, "unable to set private key");
1050       return CURLE_SSL_CONNECT_ERROR;
1051     }
1052   }
1053 #else /* NO_FILESYSTEM */
1054   if(ssl_config->primary.cert_blob) {
1055     const struct curl_blob *cert_blob = ssl_config->primary.cert_blob;
1056     const struct curl_blob *key_blob = ssl_config->key_blob;
1057     int file_type = wolfssl_do_file_type(ssl_config->cert_type);
1058     int rc;
1059 
1060     switch(file_type) {
1061     case WOLFSSL_FILETYPE_PEM:
1062       rc = wolfSSL_CTX_use_certificate_chain_buffer(backend->ctx,
1063                                                     cert_blob->data,
1064                                                     (long)cert_blob->len);
1065       break;
1066     case WOLFSSL_FILETYPE_ASN1:
1067       rc = wolfSSL_CTX_use_certificate_buffer(backend->ctx, cert_blob->data,
1068                                               (long)cert_blob->len, file_type);
1069       break;
1070     default:
1071       failf(data, "unknown cert type");
1072       return CURLE_BAD_FUNCTION_ARGUMENT;
1073     }
1074     if(rc != 1) {
1075       failf(data, "unable to use client certificate");
1076       return CURLE_SSL_CONNECT_ERROR;
1077     }
1078 
1079     if(!key_blob)
1080       key_blob = cert_blob;
1081     else
1082       file_type = wolfssl_do_file_type(ssl_config->key_type);
1083 
1084     if(wolfSSL_CTX_use_PrivateKey_buffer(backend->ctx, key_blob->data,
1085                                          (long)key_blob->len,
1086                                          file_type) != 1) {
1087       failf(data, "unable to set private key");
1088       return CURLE_SSL_CONNECT_ERROR;
1089     }
1090   }
1091 #endif /* !NO_FILESYSTEM */
1092 
1093   /* SSL always tries to verify the peer, this only says whether it should
1094    * fail to connect if the verification fails, or if it should continue
1095    * anyway. In the latter case the result of the verification is checked with
1096    * SSL_get_verify_result() below. */
1097   wolfSSL_CTX_set_verify(backend->ctx,
1098                          conn_config->verifypeer ? WOLFSSL_VERIFY_PEER :
1099                          WOLFSSL_VERIFY_NONE, NULL);
1100 
1101 #ifdef HAVE_SNI
1102   if(connssl->peer.sni) {
1103     size_t sni_len = strlen(connssl->peer.sni);
1104     if((sni_len < USHRT_MAX)) {
1105       if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME,
1106                             connssl->peer.sni,
1107                             (unsigned short)sni_len) != 1) {
1108         failf(data, "Failed to set SNI");
1109         return CURLE_SSL_CONNECT_ERROR;
1110       }
1111     }
1112   }
1113 #endif
1114 
1115   /* give application a chance to interfere with SSL set up. */
1116   if(data->set.ssl.fsslctx) {
1117     CURLcode result;
1118     if(!backend->x509_store_setup) {
1119       result = Curl_wssl_setup_x509_store(cf, data, backend);
1120       if(result)
1121         return result;
1122     }
1123     result = (*data->set.ssl.fsslctx)(data, backend->ctx,
1124                                       data->set.ssl.fsslctxp);
1125     if(result) {
1126       failf(data, "error signaled by ssl ctx callback");
1127       return result;
1128     }
1129   }
1130 #ifdef NO_FILESYSTEM
1131   else if(conn_config->verifypeer) {
1132     failf(data, "SSL: Certificates cannot be loaded because wolfSSL was built"
1133           " with \"no filesystem\". Either disable peer verification"
1134           " (insecure) or if you are building an application with libcurl you"
1135           " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
1136     return CURLE_SSL_CONNECT_ERROR;
1137   }
1138 #endif
1139 
1140   /* Let's make an SSL structure */
1141   if(backend->handle)
1142     wolfSSL_free(backend->handle);
1143   backend->handle = wolfSSL_new(backend->ctx);
1144   if(!backend->handle) {
1145     failf(data, "SSL: could not create a handle");
1146     return CURLE_OUT_OF_MEMORY;
1147   }
1148 
1149 #ifdef WOLFSSL_HAVE_KYBER
1150   if(pqkem) {
1151     if(wolfSSL_UseKeyShare(backend->handle, pqkem) != WOLFSSL_SUCCESS) {
1152       failf(data, "unable to use PQ KEM");
1153     }
1154   }
1155 #endif
1156 
1157 #ifdef HAVE_ALPN
1158   if(connssl->alpn) {
1159     struct alpn_proto_buf proto;
1160     CURLcode result;
1161 
1162     result = Curl_alpn_to_proto_str(&proto, connssl->alpn);
1163     if(result ||
1164        wolfSSL_UseALPN(backend->handle,
1165                        (char *)proto.data, (unsigned int)proto.len,
1166                        WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != WOLFSSL_SUCCESS) {
1167       failf(data, "SSL: failed setting ALPN protocols");
1168       return CURLE_SSL_CONNECT_ERROR;
1169     }
1170     infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
1171   }
1172 #endif /* HAVE_ALPN */
1173 
1174 #ifdef OPENSSL_EXTRA
1175   if(Curl_tls_keylog_enabled()) {
1176     /* Ensure the Client Random is preserved. */
1177     wolfSSL_KeepArrays(backend->handle);
1178 #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
1179     wolfSSL_set_tls13_secret_cb(backend->handle,
1180                                 wolfssl_tls13_secret_callback, NULL);
1181 #endif
1182   }
1183 #endif /* OPENSSL_EXTRA */
1184 
1185 #ifdef HAVE_SECURE_RENEGOTIATION
1186   if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) {
1187     failf(data, "SSL: failed setting secure renegotiation");
1188     return CURLE_SSL_CONNECT_ERROR;
1189   }
1190 #endif /* HAVE_SECURE_RENEGOTIATION */
1191 
1192   /* Check if there is a cached ID we can/should use here! */
1193   if(ssl_config->primary.cache_session) {
1194     /* Set session from cache if there is one */
1195     (void)wssl_setup_session(cf, data, backend, &connssl->peer);
1196     /* Register to get notified when a new session is received */
1197     wolfSSL_set_app_data(backend->handle, cf);
1198     wolfSSL_CTX_sess_set_new_cb(backend->ctx, wssl_vtls_new_session_cb);
1199   }
1200 
1201 #ifdef USE_ECH
1202   if(ECH_ENABLED(data)) {
1203     int trying_ech_now = 0;
1204 
1205     if(data->set.str[STRING_ECH_PUBLIC]) {
1206       infof(data, "ECH: outername not (yet) supported with wolfSSL");
1207       return CURLE_SSL_CONNECT_ERROR;
1208     }
1209     if(data->set.tls_ech == CURLECH_GREASE) {
1210       infof(data, "ECH: GREASE'd ECH not yet supported for wolfSSL");
1211       return CURLE_SSL_CONNECT_ERROR;
1212     }
1213     if(data->set.tls_ech & CURLECH_CLA_CFG
1214        && data->set.str[STRING_ECH_CONFIG]) {
1215       char *b64val = data->set.str[STRING_ECH_CONFIG];
1216       word32 b64len = 0;
1217 
1218       b64len = (word32) strlen(b64val);
1219       if(b64len
1220          && wolfSSL_SetEchConfigsBase64(backend->handle, b64val, b64len)
1221               != WOLFSSL_SUCCESS) {
1222         if(data->set.tls_ech & CURLECH_HARD)
1223           return CURLE_SSL_CONNECT_ERROR;
1224       }
1225       else {
1226        trying_ech_now = 1;
1227        infof(data, "ECH: ECHConfig from command line");
1228       }
1229     }
1230     else {
1231       struct Curl_dns_entry *dns = NULL;
1232 
1233       dns = Curl_fetch_addr(data, connssl->peer.hostname, connssl->peer.port);
1234       if(!dns) {
1235         infof(data, "ECH: requested but no DNS info available");
1236         if(data->set.tls_ech & CURLECH_HARD)
1237           return CURLE_SSL_CONNECT_ERROR;
1238       }
1239       else {
1240         struct Curl_https_rrinfo *rinfo = NULL;
1241 
1242         rinfo = dns->hinfo;
1243         if(rinfo && rinfo->echconfiglist) {
1244           unsigned char *ecl = rinfo->echconfiglist;
1245           size_t elen = rinfo->echconfiglist_len;
1246 
1247           infof(data, "ECH: ECHConfig from DoH HTTPS RR");
1248           if(wolfSSL_SetEchConfigs(backend->handle, ecl, (word32) elen) !=
1249                 WOLFSSL_SUCCESS) {
1250             infof(data, "ECH: wolfSSL_SetEchConfigs failed");
1251             if(data->set.tls_ech & CURLECH_HARD)
1252               return CURLE_SSL_CONNECT_ERROR;
1253           }
1254           else {
1255             trying_ech_now = 1;
1256             infof(data, "ECH: imported ECHConfigList of length %ld", elen);
1257           }
1258         }
1259         else {
1260           infof(data, "ECH: requested but no ECHConfig available");
1261           if(data->set.tls_ech & CURLECH_HARD)
1262             return CURLE_SSL_CONNECT_ERROR;
1263         }
1264         Curl_resolv_unlink(data, &dns);
1265       }
1266     }
1267 
1268     if(trying_ech_now
1269        && SSL_set_min_proto_version(backend->handle, TLS1_3_VERSION) != 1) {
1270       infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
1271       return CURLE_SSL_CONNECT_ERROR;
1272     }
1273 
1274   }
1275 #endif  /* USE_ECH */
1276 
1277 #ifdef USE_BIO_CHAIN
1278   {
1279     WOLFSSL_BIO *bio;
1280 
1281     bio = wolfSSL_BIO_new(wolfssl_bio_cf_method);
1282     if(!bio)
1283       return CURLE_OUT_OF_MEMORY;
1284 
1285     wolfSSL_BIO_set_data(bio, cf);
1286     wolfSSL_set_bio(backend->handle, bio, bio);
1287   }
1288 #else /* USE_BIO_CHAIN */
1289   /* pass the raw socket into the SSL layer */
1290   if(!wolfSSL_set_fd(backend->handle,
1291                      (int)Curl_conn_cf_get_socket(cf, data))) {
1292     failf(data, "SSL: SSL_set_fd failed");
1293     return CURLE_SSL_CONNECT_ERROR;
1294   }
1295 #endif /* !USE_BIO_CHAIN */
1296 
1297   connssl->connecting_state = ssl_connect_2;
1298   return CURLE_OK;
1299 }
1300 
1301 
wolfssl_strerror(unsigned long error,char * buf,unsigned long size)1302 static char *wolfssl_strerror(unsigned long error, char *buf,
1303                               unsigned long size)
1304 {
1305   DEBUGASSERT(size > 40);
1306   *buf = '\0';
1307 
1308   wolfSSL_ERR_error_string_n(error, buf, size);
1309 
1310   if(!*buf) {
1311     const char *msg = error ? "Unknown error" : "No error";
1312     /* the string fits because the assert above assures this */
1313     strcpy(buf, msg);
1314   }
1315 
1316   return buf;
1317 }
1318 
1319 
1320 static CURLcode
wolfssl_connect_step2(struct Curl_cfilter * cf,struct Curl_easy * data)1321 wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
1322 {
1323   int ret = -1;
1324   struct ssl_connect_data *connssl = cf->ctx;
1325   struct wolfssl_ctx *backend =
1326     (struct wolfssl_ctx *)connssl->backend;
1327   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1328 #ifndef CURL_DISABLE_PROXY
1329   const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
1330     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1331     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1332 #else
1333   const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1334 #endif
1335 
1336   DEBUGASSERT(backend);
1337 
1338   wolfSSL_ERR_clear_error();
1339 
1340   /* Enable RFC2818 checks */
1341   if(conn_config->verifyhost) {
1342     char *snihost = connssl->peer.sni ?
1343       connssl->peer.sni : connssl->peer.hostname;
1344     if(wolfSSL_check_domain_name(backend->handle, snihost) == WOLFSSL_FAILURE)
1345       return CURLE_SSL_CONNECT_ERROR;
1346   }
1347 
1348   if(!backend->x509_store_setup) {
1349     /* After having send off the ClientHello, we prepare the x509
1350      * store to verify the coming certificate from the server */
1351     CURLcode result;
1352     result = Curl_wssl_setup_x509_store(cf, data, backend);
1353     if(result)
1354       return result;
1355   }
1356 
1357   connssl->io_need = CURL_SSL_IO_NEED_NONE;
1358   ret = wolfSSL_connect(backend->handle);
1359 
1360 #ifdef OPENSSL_EXTRA
1361   if(Curl_tls_keylog_enabled()) {
1362     /* If key logging is enabled, wait for the handshake to complete and then
1363      * proceed with logging secrets (for TLS 1.2 or older).
1364      *
1365      * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
1366      * for the server response. At that point the master secret is not yet
1367      * available, so we must not try to read it.
1368      * To log the secret on completion with a handshake failure, detect
1369      * completion via the observation that there is nothing to read or write.
1370      * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
1371      * changes, the worst case is that no key is logged on error.
1372      */
1373     if(ret == WOLFSSL_SUCCESS ||
1374        (!wolfSSL_want_read(backend->handle) &&
1375         !wolfSSL_want_write(backend->handle))) {
1376       wolfssl_log_tls12_secret(backend->handle);
1377       /* Client Random and master secrets are no longer needed, erase these.
1378        * Ignored while the handshake is still in progress. */
1379       wolfSSL_FreeArrays(backend->handle);
1380     }
1381   }
1382 #endif  /* OPENSSL_EXTRA */
1383 
1384   if(ret != 1) {
1385     int detail = wolfSSL_get_error(backend->handle, ret);
1386 
1387     if(WOLFSSL_ERROR_WANT_READ == detail) {
1388       connssl->io_need = CURL_SSL_IO_NEED_RECV;
1389       return CURLE_OK;
1390     }
1391     else if(WOLFSSL_ERROR_WANT_WRITE == detail) {
1392       connssl->io_need = CURL_SSL_IO_NEED_SEND;
1393       return CURLE_OK;
1394     }
1395     /* There is no easy way to override only the CN matching.
1396      * This will enable the override of both mismatching SubjectAltNames
1397      * as also mismatching CN fields */
1398     else if(DOMAIN_NAME_MISMATCH == detail) {
1399 #if 1
1400       failf(data, " subject alt name(s) or common name do not match \"%s\"",
1401             connssl->peer.dispname);
1402       return CURLE_PEER_FAILED_VERIFICATION;
1403 #else
1404       /* When the wolfssl_check_domain_name() is used and you desire to
1405        * continue on a DOMAIN_NAME_MISMATCH, i.e. 'ssl_config.verifyhost
1406        * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
1407        * error. The only way to do this is currently to switch the
1408        * Wolfssl_check_domain_name() in and out based on the
1409        * 'ssl_config.verifyhost' value. */
1410       if(conn_config->verifyhost) {
1411         failf(data,
1412               " subject alt name(s) or common name do not match \"%s\"\n",
1413               connssl->dispname);
1414         return CURLE_PEER_FAILED_VERIFICATION;
1415       }
1416       else {
1417         infof(data,
1418               " subject alt name(s) and/or common name do not match \"%s\"",
1419               connssl->dispname);
1420         return CURLE_OK;
1421       }
1422 #endif
1423     }
1424     else if(ASN_NO_SIGNER_E == detail) {
1425       if(conn_config->verifypeer) {
1426         failf(data, " CA signer not available for verification");
1427         return CURLE_SSL_CACERT_BADFILE;
1428       }
1429       else {
1430         /* Just continue with a warning if no strict certificate
1431            verification is required. */
1432         infof(data, "CA signer not available for verification, "
1433                     "continuing anyway");
1434       }
1435     }
1436     else if(ASN_AFTER_DATE_E == detail) {
1437       failf(data, "server verification failed: certificate has expired.");
1438       return CURLE_PEER_FAILED_VERIFICATION;
1439     }
1440     else if(ASN_BEFORE_DATE_E == detail) {
1441       failf(data, "server verification failed: certificate not valid yet.");
1442       return CURLE_PEER_FAILED_VERIFICATION;
1443     }
1444 #ifdef USE_ECH
1445     else if(-1 == detail) {
1446       /* try access a retry_config ECHConfigList for tracing */
1447       byte echConfigs[1000];
1448       word32 echConfigsLen = 1000;
1449       int rv = 0;
1450 
1451       /* this currently does not produce the retry_configs */
1452       rv = wolfSSL_GetEchConfigs(backend->handle, echConfigs,
1453                                  &echConfigsLen);
1454       if(rv != WOLFSSL_SUCCESS) {
1455         infof(data, "Failed to get ECHConfigs");
1456       }
1457       else {
1458         char *b64str = NULL;
1459         size_t blen = 0;
1460 
1461         rv = Curl_base64_encode((const char *)echConfigs, echConfigsLen,
1462                                 &b64str, &blen);
1463         if(!rv && b64str)
1464           infof(data, "ECH: (not yet) retry_configs %s", b64str);
1465         free(b64str);
1466       }
1467     }
1468 #endif
1469     else if(backend->io_result == CURLE_AGAIN) {
1470       return CURLE_OK;
1471     }
1472     else {
1473       char error_buffer[256];
1474       failf(data, "SSL_connect failed with error %d: %s", detail,
1475             wolfssl_strerror((unsigned long)detail, error_buffer,
1476                              sizeof(error_buffer)));
1477       return CURLE_SSL_CONNECT_ERROR;
1478     }
1479   }
1480 
1481   if(pinnedpubkey) {
1482 #ifdef KEEP_PEER_CERT
1483     WOLFSSL_X509 *x509;
1484     const char *x509_der;
1485     int x509_der_len;
1486     struct Curl_X509certificate x509_parsed;
1487     struct Curl_asn1Element *pubkey;
1488     CURLcode result;
1489 
1490     x509 = wolfSSL_get_peer_certificate(backend->handle);
1491     if(!x509) {
1492       failf(data, "SSL: failed retrieving server certificate");
1493       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1494     }
1495 
1496     x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
1497     if(!x509_der) {
1498       failf(data, "SSL: failed retrieving ASN.1 server certificate");
1499       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1500     }
1501 
1502     memset(&x509_parsed, 0, sizeof(x509_parsed));
1503     if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
1504       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1505 
1506     pubkey = &x509_parsed.subjectPublicKeyInfo;
1507     if(!pubkey->header || pubkey->end <= pubkey->header) {
1508       failf(data, "SSL: failed retrieving public key from server certificate");
1509       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1510     }
1511 
1512     result = Curl_pin_peer_pubkey(data,
1513                                   pinnedpubkey,
1514                                   (const unsigned char *)pubkey->header,
1515                                   (size_t)(pubkey->end - pubkey->header));
1516     wolfSSL_FreeX509(x509);
1517     if(result) {
1518       failf(data, "SSL: public key does not match pinned public key");
1519       return result;
1520     }
1521 #else
1522     failf(data, "Library lacks pinning support built-in");
1523     return CURLE_NOT_BUILT_IN;
1524 #endif
1525   }
1526 
1527 #ifdef HAVE_ALPN
1528   if(connssl->alpn) {
1529     int rc;
1530     char *protocol = NULL;
1531     unsigned short protocol_len = 0;
1532 
1533     rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
1534 
1535     if(rc == WOLFSSL_SUCCESS) {
1536       Curl_alpn_set_negotiated(cf, data, connssl,
1537                                (const unsigned char *)protocol, protocol_len);
1538     }
1539     else if(rc == WOLFSSL_ALPN_NOT_FOUND)
1540       Curl_alpn_set_negotiated(cf, data, connssl, NULL, 0);
1541     else {
1542       failf(data, "ALPN, failure getting protocol, error %d", rc);
1543       return CURLE_SSL_CONNECT_ERROR;
1544     }
1545   }
1546 #endif /* HAVE_ALPN */
1547 
1548   connssl->connecting_state = ssl_connect_3;
1549 #if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
1550   infof(data, "SSL connection using %s / %s",
1551         wolfSSL_get_version(backend->handle),
1552         wolfSSL_get_cipher_name(backend->handle));
1553 #else
1554   infof(data, "SSL connected");
1555 #endif
1556 
1557   return CURLE_OK;
1558 }
1559 
wolfssl_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * mem,size_t len,CURLcode * curlcode)1560 static ssize_t wolfssl_send(struct Curl_cfilter *cf,
1561                             struct Curl_easy *data,
1562                             const void *mem,
1563                             size_t len,
1564                             CURLcode *curlcode)
1565 {
1566   struct ssl_connect_data *connssl = cf->ctx;
1567   struct wolfssl_ctx *backend =
1568     (struct wolfssl_ctx *)connssl->backend;
1569   int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
1570   int rc;
1571 
1572   DEBUGASSERT(backend);
1573 
1574   wolfSSL_ERR_clear_error();
1575 
1576   rc = wolfSSL_write(backend->handle, mem, memlen);
1577   if(rc <= 0) {
1578     int err = wolfSSL_get_error(backend->handle, rc);
1579 
1580     switch(err) {
1581     case WOLFSSL_ERROR_WANT_READ:
1582     case WOLFSSL_ERROR_WANT_WRITE:
1583       /* there is data pending, re-invoke SSL_write() */
1584       CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len);
1585       *curlcode = CURLE_AGAIN;
1586       return -1;
1587     default:
1588       if(backend->io_result == CURLE_AGAIN) {
1589         CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len);
1590         *curlcode = CURLE_AGAIN;
1591         return -1;
1592       }
1593       CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d, %d", len, rc, err);
1594       {
1595         char error_buffer[256];
1596         failf(data, "SSL write: %s, errno %d",
1597               wolfssl_strerror((unsigned long)err, error_buffer,
1598                                sizeof(error_buffer)),
1599               SOCKERRNO);
1600       }
1601       *curlcode = CURLE_SEND_ERROR;
1602       return -1;
1603     }
1604   }
1605   CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d", len, rc);
1606   return rc;
1607 }
1608 
wolfssl_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool send_shutdown,bool * done)1609 static CURLcode wolfssl_shutdown(struct Curl_cfilter *cf,
1610                                  struct Curl_easy *data,
1611                                  bool send_shutdown, bool *done)
1612 {
1613   struct ssl_connect_data *connssl = cf->ctx;
1614   struct wolfssl_ctx *wctx = (struct wolfssl_ctx *)connssl->backend;
1615   CURLcode result = CURLE_OK;
1616   char buf[1024];
1617   char error_buffer[256];
1618   int nread = -1, err;
1619   size_t i;
1620   int detail;
1621 
1622   DEBUGASSERT(wctx);
1623   if(!wctx->handle || cf->shutdown) {
1624     *done = TRUE;
1625     goto out;
1626   }
1627 
1628   wctx->shutting_down = TRUE;
1629   connssl->io_need = CURL_SSL_IO_NEED_NONE;
1630   *done = FALSE;
1631   if(!(wolfSSL_get_shutdown(wctx->handle) & WOLFSSL_SENT_SHUTDOWN)) {
1632     /* We have not started the shutdown from our side yet. Check
1633      * if the server already sent us one. */
1634     wolfSSL_ERR_clear_error();
1635     nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf));
1636     err = wolfSSL_get_error(wctx->handle, nread);
1637     CURL_TRC_CF(data, cf, "wolfSSL_read, nread=%d, err=%d", nread, err);
1638     if(!nread && err == WOLFSSL_ERROR_ZERO_RETURN) {
1639       bool input_pending;
1640       /* Yes, it did. */
1641       if(!send_shutdown) {
1642         CURL_TRC_CF(data, cf, "SSL shutdown received, not sending");
1643         *done = TRUE;
1644         goto out;
1645       }
1646       else if(!cf->next->cft->is_alive(cf->next, data, &input_pending)) {
1647         /* Server closed the connection after its closy notify. It
1648          * seems not interested to see our close notify, so do not
1649          * send it. We are done. */
1650         CURL_TRC_CF(data, cf, "peer closed connection");
1651         connssl->peer_closed = TRUE;
1652         *done = TRUE;
1653         goto out;
1654       }
1655     }
1656   }
1657 
1658   /* SSL should now have started the shutdown from our side. Since it
1659    * was not complete, we are lacking the close notify from the server. */
1660   if(send_shutdown) {
1661     wolfSSL_ERR_clear_error();
1662     if(wolfSSL_shutdown(wctx->handle) == 1) {
1663       CURL_TRC_CF(data, cf, "SSL shutdown finished");
1664       *done = TRUE;
1665       goto out;
1666     }
1667     if(WOLFSSL_ERROR_WANT_WRITE == wolfSSL_get_error(wctx->handle, nread)) {
1668       CURL_TRC_CF(data, cf, "SSL shutdown still wants to send");
1669       connssl->io_need = CURL_SSL_IO_NEED_SEND;
1670       goto out;
1671     }
1672     /* Having sent the close notify, we use wolfSSL_read() to get the
1673      * missing close notify from the server. */
1674   }
1675 
1676   for(i = 0; i < 10; ++i) {
1677     wolfSSL_ERR_clear_error();
1678     nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf));
1679     if(nread <= 0)
1680       break;
1681   }
1682   err = wolfSSL_get_error(wctx->handle, nread);
1683   switch(err) {
1684   case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */
1685     CURL_TRC_CF(data, cf, "SSL shutdown received");
1686     *done = TRUE;
1687     break;
1688   case WOLFSSL_ERROR_NONE: /* just did not get anything */
1689   case WOLFSSL_ERROR_WANT_READ:
1690     /* SSL has send its notify and now wants to read the reply
1691      * from the server. We are not really interested in that. */
1692     CURL_TRC_CF(data, cf, "SSL shutdown sent, want receive");
1693     connssl->io_need = CURL_SSL_IO_NEED_RECV;
1694     break;
1695   case WOLFSSL_ERROR_WANT_WRITE:
1696     CURL_TRC_CF(data, cf, "SSL shutdown send blocked");
1697     connssl->io_need = CURL_SSL_IO_NEED_SEND;
1698     break;
1699   default:
1700     detail = wolfSSL_get_error(wctx->handle, err);
1701     CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s'(%d)",
1702                 wolfssl_strerror((unsigned long)err, error_buffer,
1703                                  sizeof(error_buffer)),
1704                 detail);
1705     result = CURLE_RECV_ERROR;
1706     break;
1707   }
1708 
1709 out:
1710   cf->shutdown = (result || *done);
1711   return result;
1712 }
1713 
wolfssl_close(struct Curl_cfilter * cf,struct Curl_easy * data)1714 static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1715 {
1716   struct ssl_connect_data *connssl = cf->ctx;
1717   struct wolfssl_ctx *backend =
1718     (struct wolfssl_ctx *)connssl->backend;
1719 
1720   (void) data;
1721 
1722   DEBUGASSERT(backend);
1723 
1724   if(backend->handle) {
1725     wolfSSL_free(backend->handle);
1726     backend->handle = NULL;
1727   }
1728   if(backend->ctx) {
1729     wolfSSL_CTX_free(backend->ctx);
1730     backend->ctx = NULL;
1731   }
1732 }
1733 
wolfssl_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t blen,CURLcode * curlcode)1734 static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
1735                             struct Curl_easy *data,
1736                             char *buf, size_t blen,
1737                             CURLcode *curlcode)
1738 {
1739   struct ssl_connect_data *connssl = cf->ctx;
1740   struct wolfssl_ctx *backend =
1741     (struct wolfssl_ctx *)connssl->backend;
1742   int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen;
1743   int nread;
1744 
1745   DEBUGASSERT(backend);
1746 
1747   wolfSSL_ERR_clear_error();
1748   *curlcode = CURLE_OK;
1749 
1750   nread = wolfSSL_read(backend->handle, buf, buffsize);
1751 
1752   if(nread <= 0) {
1753     int err = wolfSSL_get_error(backend->handle, nread);
1754 
1755     switch(err) {
1756     case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */
1757       CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1758       *curlcode = CURLE_OK;
1759       return 0;
1760     case WOLFSSL_ERROR_NONE:
1761     case WOLFSSL_ERROR_WANT_READ:
1762     case WOLFSSL_ERROR_WANT_WRITE:
1763       if(!backend->io_result && connssl->peer_closed) {
1764         CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1765         *curlcode = CURLE_OK;
1766         return 0;
1767       }
1768       /* there is data pending, re-invoke wolfSSL_read() */
1769       CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
1770       *curlcode = CURLE_AGAIN;
1771       return -1;
1772     default:
1773       if(backend->io_result == CURLE_AGAIN) {
1774         CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
1775         *curlcode = CURLE_AGAIN;
1776         return -1;
1777       }
1778       else if(!backend->io_result && connssl->peer_closed) {
1779         CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1780         *curlcode = CURLE_OK;
1781         return 0;
1782       }
1783       else {
1784         char error_buffer[256];
1785         failf(data, "SSL read: %s, errno %d",
1786               wolfssl_strerror((unsigned long)err, error_buffer,
1787                                sizeof(error_buffer)),
1788               SOCKERRNO);
1789       }
1790       *curlcode = CURLE_RECV_ERROR;
1791       return -1;
1792     }
1793   }
1794   CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread);
1795   return nread;
1796 }
1797 
1798 
wolfssl_version(char * buffer,size_t size)1799 static size_t wolfssl_version(char *buffer, size_t size)
1800 {
1801 #if LIBWOLFSSL_VERSION_HEX >= 0x03006000
1802   return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
1803 #elif defined(WOLFSSL_VERSION)
1804   return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
1805 #endif
1806 }
1807 
1808 
wolfssl_init(void)1809 static int wolfssl_init(void)
1810 {
1811   int ret;
1812 
1813 #ifdef OPENSSL_EXTRA
1814   Curl_tls_keylog_open();
1815 #endif
1816   ret = (wolfSSL_Init() == WOLFSSL_SUCCESS);
1817   wolfssl_bio_cf_init_methods();
1818   return ret;
1819 }
1820 
1821 
wolfssl_cleanup(void)1822 static void wolfssl_cleanup(void)
1823 {
1824   wolfssl_bio_cf_free_methods();
1825   wolfSSL_Cleanup();
1826 #ifdef OPENSSL_EXTRA
1827   Curl_tls_keylog_close();
1828 #endif
1829 }
1830 
1831 
wolfssl_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1832 static bool wolfssl_data_pending(struct Curl_cfilter *cf,
1833                                  const struct Curl_easy *data)
1834 {
1835   struct ssl_connect_data *ctx = cf->ctx;
1836   struct wolfssl_ctx *backend;
1837 
1838   (void)data;
1839   DEBUGASSERT(ctx && ctx->backend);
1840 
1841   backend = (struct wolfssl_ctx *)ctx->backend;
1842   if(backend->handle)   /* SSL is in use */
1843     return wolfSSL_pending(backend->handle);
1844   else
1845     return FALSE;
1846 }
1847 
1848 static CURLcode
wolfssl_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1849 wolfssl_connect_common(struct Curl_cfilter *cf,
1850                        struct Curl_easy *data,
1851                        bool nonblocking,
1852                        bool *done)
1853 {
1854   CURLcode result;
1855   struct ssl_connect_data *connssl = cf->ctx;
1856   curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
1857 
1858   /* check if the connection has already been established */
1859   if(ssl_connection_complete == connssl->state) {
1860     *done = TRUE;
1861     return CURLE_OK;
1862   }
1863 
1864   if(ssl_connect_1 == connssl->connecting_state) {
1865     /* Find out how much more time we are allowed */
1866     const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1867 
1868     if(timeout_ms < 0) {
1869       /* no need to continue if time already is up */
1870       failf(data, "SSL connection timeout");
1871       return CURLE_OPERATION_TIMEDOUT;
1872     }
1873 
1874     result = wolfssl_connect_step1(cf, data);
1875     if(result)
1876       return result;
1877   }
1878 
1879   while(ssl_connect_2 == connssl->connecting_state) {
1880 
1881     /* check allowed time left */
1882     const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1883 
1884     if(timeout_ms < 0) {
1885       /* no need to continue if time already is up */
1886       failf(data, "SSL connection timeout");
1887       return CURLE_OPERATION_TIMEDOUT;
1888     }
1889 
1890     /* if ssl is expecting something, check if it is available. */
1891     if(connssl->io_need) {
1892       curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
1893         sockfd : CURL_SOCKET_BAD;
1894       curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
1895         sockfd : CURL_SOCKET_BAD;
1896       int what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
1897                                    nonblocking ? 0 : timeout_ms);
1898       if(what < 0) {
1899         /* fatal error */
1900         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1901         return CURLE_SSL_CONNECT_ERROR;
1902       }
1903       else if(0 == what) {
1904         if(nonblocking) {
1905           *done = FALSE;
1906           return CURLE_OK;
1907         }
1908         else {
1909           /* timeout */
1910           failf(data, "SSL connection timeout");
1911           return CURLE_OPERATION_TIMEDOUT;
1912         }
1913       }
1914       /* socket is readable or writable */
1915     }
1916 
1917     /* Run transaction, and return to the caller if it failed or if
1918      * this connection is part of a multi handle and this loop would
1919      * execute again. This permits the owner of a multi handle to
1920      * abort a connection attempt before step2 has completed while
1921      * ensuring that a client using select() or epoll() will always
1922      * have a valid fdset to wait on.
1923      */
1924     result = wolfssl_connect_step2(cf, data);
1925     if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
1926       return result;
1927   } /* repeat step2 until all transactions are done. */
1928 
1929   if(ssl_connect_3 == connssl->connecting_state) {
1930     /* In other backends, this is where we verify the certificate, but
1931      * wolfSSL already does that as part of the handshake. */
1932     connssl->connecting_state = ssl_connect_done;
1933   }
1934 
1935   if(ssl_connect_done == connssl->connecting_state) {
1936     connssl->state = ssl_connection_complete;
1937     *done = TRUE;
1938   }
1939   else
1940     *done = FALSE;
1941 
1942   /* Reset our connect state machine */
1943   connssl->connecting_state = ssl_connect_1;
1944 
1945   return CURLE_OK;
1946 }
1947 
1948 
wolfssl_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1949 static CURLcode wolfssl_connect_nonblocking(struct Curl_cfilter *cf,
1950                                             struct Curl_easy *data,
1951                                             bool *done)
1952 {
1953   return wolfssl_connect_common(cf, data, TRUE, done);
1954 }
1955 
1956 
wolfssl_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1957 static CURLcode wolfssl_connect(struct Curl_cfilter *cf,
1958                                 struct Curl_easy *data)
1959 {
1960   CURLcode result;
1961   bool done = FALSE;
1962 
1963   result = wolfssl_connect_common(cf, data, FALSE, &done);
1964   if(result)
1965     return result;
1966 
1967   DEBUGASSERT(done);
1968 
1969   return CURLE_OK;
1970 }
1971 
wolfssl_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1972 static CURLcode wolfssl_random(struct Curl_easy *data,
1973                                unsigned char *entropy, size_t length)
1974 {
1975   WC_RNG rng;
1976   (void)data;
1977   if(wc_InitRng(&rng))
1978     return CURLE_FAILED_INIT;
1979   if(length > UINT_MAX)
1980     return CURLE_FAILED_INIT;
1981   if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
1982     return CURLE_FAILED_INIT;
1983   if(wc_FreeRng(&rng))
1984     return CURLE_FAILED_INIT;
1985   return CURLE_OK;
1986 }
1987 
wolfssl_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t unused)1988 static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
1989                                   size_t tmplen,
1990                                   unsigned char *sha256sum /* output */,
1991                                   size_t unused)
1992 {
1993   wc_Sha256 SHA256pw;
1994   (void)unused;
1995   if(wc_InitSha256(&SHA256pw))
1996     return CURLE_FAILED_INIT;
1997   wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
1998   wc_Sha256Final(&SHA256pw, sha256sum);
1999   return CURLE_OK;
2000 }
2001 
wolfssl_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)2002 static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
2003                                    CURLINFO info UNUSED_PARAM)
2004 {
2005   struct wolfssl_ctx *backend =
2006     (struct wolfssl_ctx *)connssl->backend;
2007   (void)info;
2008   DEBUGASSERT(backend);
2009   return backend->handle;
2010 }
2011 
2012 const struct Curl_ssl Curl_ssl_wolfssl = {
2013   { CURLSSLBACKEND_WOLFSSL, "wolfssl" }, /* info */
2014 
2015 #ifdef KEEP_PEER_CERT
2016   SSLSUPP_PINNEDPUBKEY |
2017 #endif
2018 #ifdef USE_BIO_CHAIN
2019   SSLSUPP_HTTPS_PROXY |
2020 #endif
2021   SSLSUPP_CA_PATH |
2022   SSLSUPP_CAINFO_BLOB |
2023 #ifdef USE_ECH
2024   SSLSUPP_ECH |
2025 #endif
2026   SSLSUPP_SSL_CTX |
2027 #ifdef WOLFSSL_TLS13
2028   SSLSUPP_TLS13_CIPHERSUITES |
2029 #endif
2030   SSLSUPP_CA_CACHE |
2031   SSLSUPP_CIPHER_LIST,
2032 
2033   sizeof(struct wolfssl_ctx),
2034 
2035   wolfssl_init,                    /* init */
2036   wolfssl_cleanup,                 /* cleanup */
2037   wolfssl_version,                 /* version */
2038   Curl_none_check_cxn,             /* check_cxn */
2039   wolfssl_shutdown,                /* shutdown */
2040   wolfssl_data_pending,            /* data_pending */
2041   wolfssl_random,                  /* random */
2042   Curl_none_cert_status_request,   /* cert_status_request */
2043   wolfssl_connect,                 /* connect */
2044   wolfssl_connect_nonblocking,     /* connect_nonblocking */
2045   Curl_ssl_adjust_pollset,         /* adjust_pollset */
2046   wolfssl_get_internals,           /* get_internals */
2047   wolfssl_close,                   /* close_one */
2048   Curl_none_close_all,             /* close_all */
2049   Curl_none_set_engine,            /* set_engine */
2050   Curl_none_set_engine_default,    /* set_engine_default */
2051   Curl_none_engines_list,          /* engines_list */
2052   Curl_none_false_start,           /* false_start */
2053   wolfssl_sha256sum,               /* sha256sum */
2054   NULL,                            /* associate_connection */
2055   NULL,                            /* disassociate_connection */
2056   wolfssl_recv,                    /* recv decrypted data */
2057   wolfssl_send,                    /* send data to encrypt */
2058   NULL,                            /* get_channel_binding */
2059 };
2060 
2061 #endif
2062