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