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