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