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