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