• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
10  *
11  * This software is licensed as described in the file COPYING, which
12  * you should have received as part of this distribution. The terms
13  * are also available at https://curl.se/docs/copyright.html.
14  *
15  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16  * copies of the Software, and permit persons to whom the Software is
17  * furnished to do so, under the terms of the COPYING file.
18  *
19  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20  * KIND, either express or implied.
21  *
22  * SPDX-License-Identifier: curl
23  *
24  ***************************************************************************/
25 
26 /*
27  * Source file for all mbedTLS-specific code for the TLS/SSL layer. No code
28  * but vtls.c should ever call or use these functions.
29  *
30  */
31 
32 #include "curl_setup.h"
33 
34 #ifdef USE_MBEDTLS
35 
36 /* Define this to enable lots of debugging for mbedTLS */
37 /* #define MBEDTLS_DEBUG */
38 
39 #ifdef __GNUC__
40 #pragma GCC diagnostic push
41 /* mbedTLS (as of v3.5.1) has a duplicate function declaration
42    in its public headers. Disable the warning that detects it. */
43 #pragma GCC diagnostic ignored "-Wredundant-decls"
44 #endif
45 
46 #include <mbedtls/version.h>
47 #if MBEDTLS_VERSION_NUMBER >= 0x02040000
48 #include <mbedtls/net_sockets.h>
49 #else
50 #include <mbedtls/net.h>
51 #endif
52 #include <mbedtls/ssl.h>
53 #include <mbedtls/x509.h>
54 
55 #include <mbedtls/error.h>
56 #include <mbedtls/entropy.h>
57 #include <mbedtls/ctr_drbg.h>
58 #include <mbedtls/sha256.h>
59 
60 #if MBEDTLS_VERSION_MAJOR >= 2
61 #  ifdef MBEDTLS_DEBUG
62 #    include <mbedtls/debug.h>
63 #  endif
64 #endif
65 
66 #ifdef __GNUC__
67 #pragma GCC diagnostic pop
68 #endif
69 
70 #include "urldata.h"
71 #include "sendf.h"
72 #include "inet_pton.h"
73 #include "mbedtls.h"
74 #include "vtls.h"
75 #include "vtls_int.h"
76 #include "parsedate.h"
77 #include "connect.h" /* for the connect timeout */
78 #include "select.h"
79 #include "multiif.h"
80 #include "mbedtls_threadlock.h"
81 #include "strdup.h"
82 
83 /* The last 3 #include files should be in this order */
84 #include "curl_printf.h"
85 #include "curl_memory.h"
86 #include "memdebug.h"
87 
88 /* ALPN for http2 */
89 #ifdef USE_HTTP2
90 #  undef HAS_ALPN
91 #  ifdef MBEDTLS_SSL_ALPN
92 #    define HAS_ALPN
93 #  endif
94 #endif
95 
96 struct mbed_ssl_backend_data {
97   mbedtls_ctr_drbg_context ctr_drbg;
98   mbedtls_entropy_context entropy;
99   mbedtls_ssl_context ssl;
100   mbedtls_x509_crt cacert;
101   mbedtls_x509_crt clicert;
102 #ifdef MBEDTLS_X509_CRL_PARSE_C
103   mbedtls_x509_crl crl;
104 #endif
105   mbedtls_pk_context pk;
106   mbedtls_ssl_config config;
107 #ifdef HAS_ALPN
108   const char *protocols[3];
109 #endif
110 };
111 
112 /* apply threading? */
113 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
114 #define THREADING_SUPPORT
115 #endif
116 
117 #ifndef MBEDTLS_ERROR_C
118 #define mbedtls_strerror(a,b,c) b[0] = 0
119 #endif
120 
121 #if defined(THREADING_SUPPORT)
122 static mbedtls_entropy_context ts_entropy;
123 
124 static int entropy_init_initialized = 0;
125 
126 /* start of entropy_init_mutex() */
entropy_init_mutex(mbedtls_entropy_context * ctx)127 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
128 {
129   /* lock 0 = entropy_init_mutex() */
130   Curl_mbedtlsthreadlock_lock_function(0);
131   if(entropy_init_initialized == 0) {
132     mbedtls_entropy_init(ctx);
133     entropy_init_initialized = 1;
134   }
135   Curl_mbedtlsthreadlock_unlock_function(0);
136 }
137 /* end of entropy_init_mutex() */
138 
139 /* start of entropy_func_mutex() */
entropy_func_mutex(void * data,unsigned char * output,size_t len)140 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
141 {
142   int ret;
143   /* lock 1 = entropy_func_mutex() */
144   Curl_mbedtlsthreadlock_lock_function(1);
145   ret = mbedtls_entropy_func(data, output, len);
146   Curl_mbedtlsthreadlock_unlock_function(1);
147 
148   return ret;
149 }
150 /* end of entropy_func_mutex() */
151 
152 #endif /* THREADING_SUPPORT */
153 
154 #ifdef MBEDTLS_DEBUG
mbed_debug(void * context,int level,const char * f_name,int line_nb,const char * line)155 static void mbed_debug(void *context, int level, const char *f_name,
156                        int line_nb, const char *line)
157 {
158   struct Curl_easy *data = NULL;
159 
160   if(!context)
161     return;
162 
163   data = (struct Curl_easy *)context;
164 
165   infof(data, "%s", line);
166   (void) level;
167 }
168 #endif
169 
mbedtls_bio_cf_write(void * bio,const unsigned char * buf,size_t blen)170 static int mbedtls_bio_cf_write(void *bio,
171                                 const unsigned char *buf, size_t blen)
172 {
173   struct Curl_cfilter *cf = bio;
174   struct Curl_easy *data = CF_DATA_CURRENT(cf);
175   ssize_t nwritten;
176   CURLcode result;
177 
178   DEBUGASSERT(data);
179   if(!data)
180     return 0;
181 
182   nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result);
183   CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %zd, err=%d",
184               blen, nwritten, result);
185   if(nwritten < 0 && CURLE_AGAIN == result) {
186     nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
187   }
188   return (int)nwritten;
189 }
190 
mbedtls_bio_cf_read(void * bio,unsigned char * buf,size_t blen)191 static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen)
192 {
193   struct Curl_cfilter *cf = bio;
194   struct Curl_easy *data = CF_DATA_CURRENT(cf);
195   ssize_t nread;
196   CURLcode result;
197 
198   DEBUGASSERT(data);
199   if(!data)
200     return 0;
201   /* OpenSSL catches this case, so should we. */
202   if(!buf)
203     return 0;
204 
205   nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
206   CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %zd, err=%d",
207               blen, nread, result);
208   if(nread < 0 && CURLE_AGAIN == result) {
209     nread = MBEDTLS_ERR_SSL_WANT_READ;
210   }
211   return (int)nread;
212 }
213 
214 /*
215  *  profile
216  */
217 static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
218 {
219   /* Hashes from SHA-1 and above */
220   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
221   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) |
222   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) |
223   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
224   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
225   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
226   0xFFFFFFF, /* Any PK alg    */
227   0xFFFFFFF, /* Any curve     */
228   1024,      /* RSA min key len */
229 };
230 
231 /* See https://tls.mbed.org/discussions/generic/
232    howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
233 */
234 #define RSA_PUB_DER_MAX_BYTES   (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
235 #define ECP_PUB_DER_MAX_BYTES   (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
236 
237 #define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
238                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
239 
mbedtls_version_from_curl(int * mbedver,long version)240 static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
241 {
242 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
243   switch(version) {
244     case CURL_SSLVERSION_TLSv1_0:
245     case CURL_SSLVERSION_TLSv1_1:
246     case CURL_SSLVERSION_TLSv1_2:
247       *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
248       return CURLE_OK;
249     case CURL_SSLVERSION_TLSv1_3:
250       break;
251   }
252 #else
253   switch(version) {
254     case CURL_SSLVERSION_TLSv1_0:
255       *mbedver = MBEDTLS_SSL_MINOR_VERSION_1;
256       return CURLE_OK;
257     case CURL_SSLVERSION_TLSv1_1:
258       *mbedver = MBEDTLS_SSL_MINOR_VERSION_2;
259       return CURLE_OK;
260     case CURL_SSLVERSION_TLSv1_2:
261       *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
262       return CURLE_OK;
263     case CURL_SSLVERSION_TLSv1_3:
264       break;
265   }
266 #endif
267 
268   return CURLE_SSL_CONNECT_ERROR;
269 }
270 
271 static CURLcode
set_ssl_version_min_max(struct Curl_cfilter * cf,struct Curl_easy * data)272 set_ssl_version_min_max(struct Curl_cfilter *cf, struct Curl_easy *data)
273 {
274   struct ssl_connect_data *connssl = cf->ctx;
275   struct mbed_ssl_backend_data *backend =
276     (struct mbed_ssl_backend_data *)connssl->backend;
277   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
278 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
279   int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3;
280   int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_3;
281 #else
282   int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
283   int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
284 #endif
285   long ssl_version = conn_config->version;
286   long ssl_version_max = conn_config->version_max;
287   CURLcode result = CURLE_OK;
288 
289   DEBUGASSERT(backend);
290 
291   switch(ssl_version) {
292     case CURL_SSLVERSION_DEFAULT:
293     case CURL_SSLVERSION_TLSv1:
294       ssl_version = CURL_SSLVERSION_TLSv1_0;
295       break;
296   }
297 
298   switch(ssl_version_max) {
299     case CURL_SSLVERSION_MAX_NONE:
300     case CURL_SSLVERSION_MAX_DEFAULT:
301       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
302       break;
303   }
304 
305   result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version);
306   if(result) {
307     failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
308     return result;
309   }
310   result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16);
311   if(result) {
312     failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
313     return result;
314   }
315 
316   mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
317                                mbedtls_ver_min);
318   mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
319                                mbedtls_ver_max);
320 
321   return result;
322 }
323 
324 static CURLcode
mbed_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)325 mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
326 {
327   struct ssl_connect_data *connssl = cf->ctx;
328   struct mbed_ssl_backend_data *backend =
329     (struct mbed_ssl_backend_data *)connssl->backend;
330   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
331   const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
332   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
333   const char * const ssl_cafile =
334     /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
335     (ca_info_blob ? NULL : conn_config->CAfile);
336   const bool verifypeer = conn_config->verifypeer;
337   const char * const ssl_capath = conn_config->CApath;
338   char * const ssl_cert = ssl_config->primary.clientcert;
339   const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
340   const char * const ssl_crlfile = ssl_config->primary.CRLfile;
341   const char *hostname = connssl->peer.hostname;
342   int ret = -1;
343   char errorbuf[128];
344 
345   DEBUGASSERT(backend);
346 
347   if((conn_config->version == CURL_SSLVERSION_SSLv2) ||
348      (conn_config->version == CURL_SSLVERSION_SSLv3)) {
349     failf(data, "Not supported SSL version");
350     return CURLE_NOT_BUILT_IN;
351   }
352 
353 #ifdef THREADING_SUPPORT
354   entropy_init_mutex(&ts_entropy);
355   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
356 
357   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
358                               &ts_entropy, NULL, 0);
359   if(ret) {
360     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
361     failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
362           -ret, errorbuf);
363     return CURLE_FAILED_INIT;
364   }
365 #else
366   mbedtls_entropy_init(&backend->entropy);
367   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
368 
369   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func,
370                               &backend->entropy, NULL, 0);
371   if(ret) {
372     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
373     failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
374           -ret, errorbuf);
375     return CURLE_FAILED_INIT;
376   }
377 #endif /* THREADING_SUPPORT */
378 
379   /* Load the trusted CA */
380   mbedtls_x509_crt_init(&backend->cacert);
381 
382   if(ca_info_blob && verifypeer) {
383     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
384        terminated even when provided the exact length, forcing us to waste
385        extra memory here. */
386     unsigned char *newblob = Curl_memdup0(ca_info_blob->data,
387                                           ca_info_blob->len);
388     if(!newblob)
389       return CURLE_OUT_OF_MEMORY;
390     ret = mbedtls_x509_crt_parse(&backend->cacert, newblob,
391                                  ca_info_blob->len + 1);
392     free(newblob);
393     if(ret<0) {
394       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
395       failf(data, "Error importing ca cert blob - mbedTLS: (-0x%04X) %s",
396             -ret, errorbuf);
397       return CURLE_SSL_CERTPROBLEM;
398     }
399   }
400 
401   if(ssl_cafile && verifypeer) {
402 #ifdef MBEDTLS_FS_IO
403     ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile);
404 
405     if(ret<0) {
406       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
407       failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
408             ssl_cafile, -ret, errorbuf);
409       return CURLE_SSL_CACERT_BADFILE;
410     }
411 #else
412     failf(data, "mbedtls: functions that use the filesystem not built in");
413     return CURLE_NOT_BUILT_IN;
414 #endif
415   }
416 
417   if(ssl_capath) {
418 #ifdef MBEDTLS_FS_IO
419     ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath);
420 
421     if(ret<0) {
422       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
423       failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
424             ssl_capath, -ret, errorbuf);
425 
426       if(verifypeer)
427         return CURLE_SSL_CACERT_BADFILE;
428     }
429 #else
430     failf(data, "mbedtls: functions that use the filesystem not built in");
431     return CURLE_NOT_BUILT_IN;
432 #endif
433   }
434 
435   /* Load the client certificate */
436   mbedtls_x509_crt_init(&backend->clicert);
437 
438   if(ssl_cert) {
439 #ifdef MBEDTLS_FS_IO
440     ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert);
441 
442     if(ret) {
443       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
444       failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
445             ssl_cert, -ret, errorbuf);
446 
447       return CURLE_SSL_CERTPROBLEM;
448     }
449 #else
450     failf(data, "mbedtls: functions that use the filesystem not built in");
451     return CURLE_NOT_BUILT_IN;
452 #endif
453   }
454 
455   if(ssl_cert_blob) {
456     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
457        terminated even when provided the exact length, forcing us to waste
458        extra memory here. */
459     unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data,
460                                           ssl_cert_blob->len);
461     if(!newblob)
462       return CURLE_OUT_OF_MEMORY;
463     ret = mbedtls_x509_crt_parse(&backend->clicert, newblob,
464                                  ssl_cert_blob->len + 1);
465     free(newblob);
466 
467     if(ret) {
468       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
469       failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
470             ssl_config->key, -ret, errorbuf);
471       return CURLE_SSL_CERTPROBLEM;
472     }
473   }
474 
475   /* Load the client private key */
476   mbedtls_pk_init(&backend->pk);
477 
478   if(ssl_config->key || ssl_config->key_blob) {
479     if(ssl_config->key) {
480 #ifdef MBEDTLS_FS_IO
481 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
482       ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
483                                      ssl_config->key_passwd,
484                                      mbedtls_ctr_drbg_random,
485                                      &backend->ctr_drbg);
486 #else
487       ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
488                                      ssl_config->key_passwd);
489 #endif
490 
491       if(ret) {
492         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
493         failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
494               ssl_config->key, -ret, errorbuf);
495         return CURLE_SSL_CERTPROBLEM;
496       }
497 #else
498       failf(data, "mbedtls: functions that use the filesystem not built in");
499       return CURLE_NOT_BUILT_IN;
500 #endif
501     }
502     else {
503       const struct curl_blob *ssl_key_blob = ssl_config->key_blob;
504       const unsigned char *key_data =
505         (const unsigned char *)ssl_key_blob->data;
506       const char *passwd = ssl_config->key_passwd;
507 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
508       ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
509                                  (const unsigned char *)passwd,
510                                  passwd ? strlen(passwd) : 0,
511                                  mbedtls_ctr_drbg_random,
512                                  &backend->ctr_drbg);
513 #else
514       ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
515                                  (const unsigned char *)passwd,
516                                  passwd ? strlen(passwd) : 0);
517 #endif
518 
519       if(ret) {
520         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
521         failf(data, "Error parsing private key - mbedTLS: (-0x%04X) %s",
522               -ret, errorbuf);
523         return CURLE_SSL_CERTPROBLEM;
524       }
525     }
526 
527     if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
528                      mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
529       ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
530   }
531 
532   /* Load the CRL */
533 #ifdef MBEDTLS_X509_CRL_PARSE_C
534   mbedtls_x509_crl_init(&backend->crl);
535 
536   if(ssl_crlfile) {
537 #ifdef MBEDTLS_FS_IO
538     ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile);
539 
540     if(ret) {
541       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
542       failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
543             ssl_crlfile, -ret, errorbuf);
544 
545       return CURLE_SSL_CRL_BADFILE;
546     }
547 #else
548     failf(data, "mbedtls: functions that use the filesystem not built in");
549     return CURLE_NOT_BUILT_IN;
550 #endif
551   }
552 #else
553   if(ssl_crlfile) {
554     failf(data, "mbedtls: crl support not built in");
555     return CURLE_NOT_BUILT_IN;
556   }
557 #endif
558 
559   infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->port);
560 
561   mbedtls_ssl_config_init(&backend->config);
562   ret = mbedtls_ssl_config_defaults(&backend->config,
563                                     MBEDTLS_SSL_IS_CLIENT,
564                                     MBEDTLS_SSL_TRANSPORT_STREAM,
565                                     MBEDTLS_SSL_PRESET_DEFAULT);
566   if(ret) {
567     failf(data, "mbedTLS: ssl_config failed");
568     return CURLE_SSL_CONNECT_ERROR;
569   }
570 
571   mbedtls_ssl_init(&backend->ssl);
572   if(mbedtls_ssl_setup(&backend->ssl, &backend->config)) {
573     failf(data, "mbedTLS: ssl_init failed");
574     return CURLE_SSL_CONNECT_ERROR;
575   }
576 
577   /* new profile with RSA min key len = 1024 ... */
578   mbedtls_ssl_conf_cert_profile(&backend->config,
579                                 &mbedtls_x509_crt_profile_fr);
580 
581   switch(conn_config->version) {
582   case CURL_SSLVERSION_DEFAULT:
583   case CURL_SSLVERSION_TLSv1:
584 #if MBEDTLS_VERSION_NUMBER < 0x03000000
585     mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
586                                  MBEDTLS_SSL_MINOR_VERSION_1);
587     infof(data, "mbedTLS: Set min SSL version to TLS 1.0");
588     break;
589 #endif
590   case CURL_SSLVERSION_TLSv1_0:
591   case CURL_SSLVERSION_TLSv1_1:
592   case CURL_SSLVERSION_TLSv1_2:
593   case CURL_SSLVERSION_TLSv1_3:
594     {
595       CURLcode result = set_ssl_version_min_max(cf, data);
596       if(result != CURLE_OK)
597         return result;
598       break;
599     }
600   default:
601     failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
602     return CURLE_SSL_CONNECT_ERROR;
603   }
604 
605   mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
606 
607   mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
608                        &backend->ctr_drbg);
609   mbedtls_ssl_set_bio(&backend->ssl, cf,
610                       mbedtls_bio_cf_write,
611                       mbedtls_bio_cf_read,
612                       NULL /*  rev_timeout() */);
613 
614   mbedtls_ssl_conf_ciphersuites(&backend->config,
615                                 mbedtls_ssl_list_ciphersuites());
616 
617 #if defined(MBEDTLS_SSL_RENEGOTIATION)
618   mbedtls_ssl_conf_renegotiation(&backend->config,
619                                  MBEDTLS_SSL_RENEGOTIATION_ENABLED);
620 #endif
621 
622 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
623   mbedtls_ssl_conf_session_tickets(&backend->config,
624                                    MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
625 #endif
626 
627   /* Check if there's a cached ID we can/should use here! */
628   if(ssl_config->primary.sessionid) {
629     void *old_session = NULL;
630 
631     Curl_ssl_sessionid_lock(data);
632     if(!Curl_ssl_getsessionid(cf, data, &old_session, NULL)) {
633       ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
634       if(ret) {
635         Curl_ssl_sessionid_unlock(data);
636         failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
637         return CURLE_SSL_CONNECT_ERROR;
638       }
639       infof(data, "mbedTLS reusing session");
640     }
641     Curl_ssl_sessionid_unlock(data);
642   }
643 
644   mbedtls_ssl_conf_ca_chain(&backend->config,
645                             &backend->cacert,
646 #ifdef MBEDTLS_X509_CRL_PARSE_C
647                             &backend->crl);
648 #else
649                             NULL);
650 #endif
651 
652   if(ssl_config->key || ssl_config->key_blob) {
653     mbedtls_ssl_conf_own_cert(&backend->config,
654                               &backend->clicert, &backend->pk);
655   }
656 
657   if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni?
658                               connssl->peer.sni : connssl->peer.hostname)) {
659     /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and
660        the name to set in the SNI extension. So even if curl connects to a
661        host specified as an IP address, this function must be used. */
662     failf(data, "Failed to set SNI");
663     return CURLE_SSL_CONNECT_ERROR;
664   }
665 
666 #ifdef HAS_ALPN
667   if(connssl->alpn) {
668     struct alpn_proto_buf proto;
669     size_t i;
670 
671     for(i = 0; i < connssl->alpn->count; ++i) {
672       backend->protocols[i] = connssl->alpn->entries[i];
673     }
674     /* this function doesn't clone the protocols array, which is why we need
675        to keep it around */
676     if(mbedtls_ssl_conf_alpn_protocols(&backend->config,
677                                        &backend->protocols[0])) {
678       failf(data, "Failed setting ALPN protocols");
679       return CURLE_SSL_CONNECT_ERROR;
680     }
681     Curl_alpn_to_proto_str(&proto, connssl->alpn);
682     infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
683   }
684 #endif
685 
686 #ifdef MBEDTLS_DEBUG
687   /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
688   mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data);
689   /* - 0 No debug
690    * - 1 Error
691    * - 2 State change
692    * - 3 Informational
693    * - 4 Verbose
694    */
695   mbedtls_debug_set_threshold(4);
696 #endif
697 
698   /* give application a chance to interfere with mbedTLS set up. */
699   if(data->set.ssl.fsslctx) {
700     ret = (*data->set.ssl.fsslctx)(data, &backend->config,
701                                    data->set.ssl.fsslctxp);
702     if(ret) {
703       failf(data, "error signaled by ssl ctx callback");
704       return ret;
705     }
706   }
707 
708   connssl->connecting_state = ssl_connect_2;
709 
710   return CURLE_OK;
711 }
712 
713 static CURLcode
mbed_connect_step2(struct Curl_cfilter * cf,struct Curl_easy * data)714 mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
715 {
716   int ret;
717   struct ssl_connect_data *connssl = cf->ctx;
718   struct mbed_ssl_backend_data *backend =
719     (struct mbed_ssl_backend_data *)connssl->backend;
720   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
721   const mbedtls_x509_crt *peercert;
722   const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
723     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
724     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
725 
726   DEBUGASSERT(backend);
727 
728   ret = mbedtls_ssl_handshake(&backend->ssl);
729 
730   if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
731     connssl->connecting_state = ssl_connect_2_reading;
732     return CURLE_OK;
733   }
734   else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
735     connssl->connecting_state = ssl_connect_2_writing;
736     return CURLE_OK;
737   }
738   else if(ret) {
739     char errorbuf[128];
740     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
741     failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s",
742           -ret, errorbuf);
743     return CURLE_SSL_CONNECT_ERROR;
744   }
745 
746   infof(data, "mbedTLS: Handshake complete, cipher is %s",
747         mbedtls_ssl_get_ciphersuite(&backend->ssl));
748 
749   ret = mbedtls_ssl_get_verify_result(&backend->ssl);
750 
751   if(!conn_config->verifyhost)
752     /* Ignore hostname errors if verifyhost is disabled */
753     ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
754 
755   if(ret && conn_config->verifypeer) {
756     if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
757       failf(data, "Cert verify failed: BADCERT_EXPIRED");
758 
759     else if(ret & MBEDTLS_X509_BADCERT_REVOKED)
760       failf(data, "Cert verify failed: BADCERT_REVOKED");
761 
762     else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
763       failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
764 
765     else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
766       failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
767 
768     else if(ret & MBEDTLS_X509_BADCERT_FUTURE)
769       failf(data, "Cert verify failed: BADCERT_FUTURE");
770 
771     return CURLE_PEER_FAILED_VERIFICATION;
772   }
773 
774   peercert = mbedtls_ssl_get_peer_cert(&backend->ssl);
775 
776   if(peercert && data->set.verbose) {
777     const size_t bufsize = 16384;
778     char *buffer = malloc(bufsize);
779 
780     if(!buffer)
781       return CURLE_OUT_OF_MEMORY;
782 
783     if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0)
784       infof(data, "Dumping cert info: %s", buffer);
785     else
786       infof(data, "Unable to dump certificate information");
787 
788     free(buffer);
789   }
790 
791   if(pinnedpubkey) {
792     int size;
793     CURLcode result;
794     mbedtls_x509_crt *p = NULL;
795     unsigned char *pubkey = NULL;
796 
797 #if MBEDTLS_VERSION_NUMBER == 0x03000000
798     if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) ||
799        !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) {
800 #else
801     if(!peercert || !peercert->raw.p || !peercert->raw.len) {
802 #endif
803       failf(data, "Failed due to missing peer certificate");
804       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
805     }
806 
807     p = calloc(1, sizeof(*p));
808 
809     if(!p)
810       return CURLE_OUT_OF_MEMORY;
811 
812     pubkey = malloc(PUB_DER_MAX_BYTES);
813 
814     if(!pubkey) {
815       result = CURLE_OUT_OF_MEMORY;
816       goto pinnedpubkey_error;
817     }
818 
819     mbedtls_x509_crt_init(p);
820 
821     /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
822        needs a non-const key, for now.
823        https://github.com/ARMmbed/mbedtls/issues/396 */
824 #if MBEDTLS_VERSION_NUMBER == 0x03000000
825     if(mbedtls_x509_crt_parse_der(p,
826                         peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
827                         peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) {
828 #else
829     if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
830 #endif
831       failf(data, "Failed copying peer certificate");
832       result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
833       goto pinnedpubkey_error;
834     }
835 
836 #if MBEDTLS_VERSION_NUMBER == 0x03000000
837     size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey,
838                                        PUB_DER_MAX_BYTES);
839 #else
840     size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
841 #endif
842 
843     if(size <= 0) {
844       failf(data, "Failed copying public key from peer certificate");
845       result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
846       goto pinnedpubkey_error;
847     }
848 
849     /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
850     result = Curl_pin_peer_pubkey(data,
851                                   pinnedpubkey,
852                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
853 pinnedpubkey_error:
854     mbedtls_x509_crt_free(p);
855     free(p);
856     free(pubkey);
857     if(result) {
858       return result;
859     }
860   }
861 
862 #ifdef HAS_ALPN
863   if(connssl->alpn) {
864     const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
865 
866     Curl_alpn_set_negotiated(cf, data, (const unsigned char *)proto,
867                              proto? strlen(proto) : 0);
868   }
869 #endif
870 
871   connssl->connecting_state = ssl_connect_3;
872   infof(data, "SSL connected");
873 
874   return CURLE_OK;
875 }
876 
877 static CURLcode
878 mbed_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
879 {
880   CURLcode retcode = CURLE_OK;
881   struct ssl_connect_data *connssl = cf->ctx;
882   struct mbed_ssl_backend_data *backend =
883     (struct mbed_ssl_backend_data *)connssl->backend;
884   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
885 
886   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
887   DEBUGASSERT(backend);
888 
889   if(ssl_config->primary.sessionid) {
890     int ret;
891     mbedtls_ssl_session *our_ssl_sessionid;
892     void *old_ssl_sessionid = NULL;
893     bool added = FALSE;
894 
895     our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session));
896     if(!our_ssl_sessionid)
897       return CURLE_OUT_OF_MEMORY;
898 
899     mbedtls_ssl_session_init(our_ssl_sessionid);
900 
901     ret = mbedtls_ssl_get_session(&backend->ssl, our_ssl_sessionid);
902     if(ret) {
903       if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED)
904         mbedtls_ssl_session_free(our_ssl_sessionid);
905       free(our_ssl_sessionid);
906       failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
907       return CURLE_SSL_CONNECT_ERROR;
908     }
909 
910     /* If there's already a matching session in the cache, delete it */
911     Curl_ssl_sessionid_lock(data);
912     if(!Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL))
913       Curl_ssl_delsessionid(data, old_ssl_sessionid);
914 
915     retcode = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid,
916                                     0, &added);
917     Curl_ssl_sessionid_unlock(data);
918     if(!added) {
919       mbedtls_ssl_session_free(our_ssl_sessionid);
920       free(our_ssl_sessionid);
921     }
922     if(retcode) {
923       failf(data, "failed to store ssl session");
924       return retcode;
925     }
926   }
927 
928   connssl->connecting_state = ssl_connect_done;
929 
930   return CURLE_OK;
931 }
932 
933 static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
934                          const void *mem, size_t len,
935                          CURLcode *curlcode)
936 {
937   struct ssl_connect_data *connssl = cf->ctx;
938   struct mbed_ssl_backend_data *backend =
939     (struct mbed_ssl_backend_data *)connssl->backend;
940   int ret = -1;
941 
942   (void)data;
943   DEBUGASSERT(backend);
944   ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
945 
946   if(ret < 0) {
947     *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
948       CURLE_AGAIN : CURLE_SEND_ERROR;
949     ret = -1;
950   }
951 
952   return ret;
953 }
954 
955 static void mbedtls_close_all(struct Curl_easy *data)
956 {
957   (void)data;
958 }
959 
960 static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
961 {
962   struct ssl_connect_data *connssl = cf->ctx;
963   struct mbed_ssl_backend_data *backend =
964     (struct mbed_ssl_backend_data *)connssl->backend;
965   char buf[32];
966 
967   (void)data;
968   DEBUGASSERT(backend);
969 
970   /* Maybe the server has already sent a close notify alert.
971      Read it to avoid an RST on the TCP connection. */
972   (void)mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, sizeof(buf));
973 
974   mbedtls_pk_free(&backend->pk);
975   mbedtls_x509_crt_free(&backend->clicert);
976   mbedtls_x509_crt_free(&backend->cacert);
977 #ifdef MBEDTLS_X509_CRL_PARSE_C
978   mbedtls_x509_crl_free(&backend->crl);
979 #endif
980   mbedtls_ssl_config_free(&backend->config);
981   mbedtls_ssl_free(&backend->ssl);
982   mbedtls_ctr_drbg_free(&backend->ctr_drbg);
983 #ifndef THREADING_SUPPORT
984   mbedtls_entropy_free(&backend->entropy);
985 #endif /* THREADING_SUPPORT */
986 }
987 
988 static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
989                          char *buf, size_t buffersize,
990                          CURLcode *curlcode)
991 {
992   struct ssl_connect_data *connssl = cf->ctx;
993   struct mbed_ssl_backend_data *backend =
994     (struct mbed_ssl_backend_data *)connssl->backend;
995   int ret = -1;
996   ssize_t len = -1;
997 
998   (void)data;
999   DEBUGASSERT(backend);
1000 
1001   ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
1002                          buffersize);
1003 
1004   if(ret <= 0) {
1005     if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
1006       return 0;
1007 
1008     *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ?
1009       CURLE_AGAIN : CURLE_RECV_ERROR;
1010     return -1;
1011   }
1012 
1013   len = ret;
1014 
1015   return len;
1016 }
1017 
1018 static void mbedtls_session_free(void *ptr)
1019 {
1020   mbedtls_ssl_session_free(ptr);
1021   free(ptr);
1022 }
1023 
1024 static size_t mbedtls_version(char *buffer, size_t size)
1025 {
1026 #ifdef MBEDTLS_VERSION_C
1027   /* if mbedtls_version_get_number() is available it is better */
1028   unsigned int version = mbedtls_version_get_number();
1029   return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
1030                    (version>>16)&0xff, (version>>8)&0xff);
1031 #else
1032   return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING);
1033 #endif
1034 }
1035 
1036 static CURLcode mbedtls_random(struct Curl_easy *data,
1037                                unsigned char *entropy, size_t length)
1038 {
1039 #if defined(MBEDTLS_CTR_DRBG_C)
1040   int ret = -1;
1041   char errorbuf[128];
1042   mbedtls_entropy_context ctr_entropy;
1043   mbedtls_ctr_drbg_context ctr_drbg;
1044   mbedtls_entropy_init(&ctr_entropy);
1045   mbedtls_ctr_drbg_init(&ctr_drbg);
1046 
1047   ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
1048                               &ctr_entropy, NULL, 0);
1049 
1050   if(ret) {
1051     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
1052     failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
1053           -ret, errorbuf);
1054   }
1055   else {
1056     ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
1057 
1058     if(ret) {
1059       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
1060       failf(data, "mbedtls_ctr_drbg_random returned (-0x%04X) %s",
1061             -ret, errorbuf);
1062     }
1063   }
1064 
1065   mbedtls_ctr_drbg_free(&ctr_drbg);
1066   mbedtls_entropy_free(&ctr_entropy);
1067 
1068   return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
1069 #elif defined(MBEDTLS_HAVEGE_C)
1070   mbedtls_havege_state hs;
1071   mbedtls_havege_init(&hs);
1072   mbedtls_havege_random(&hs, entropy, length);
1073   mbedtls_havege_free(&hs);
1074   return CURLE_OK;
1075 #else
1076   return CURLE_NOT_BUILT_IN;
1077 #endif
1078 }
1079 
1080 static CURLcode
1081 mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
1082                     bool nonblocking,
1083                     bool *done)
1084 {
1085   CURLcode retcode;
1086   struct ssl_connect_data *connssl = cf->ctx;
1087   curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
1088   timediff_t timeout_ms;
1089   int what;
1090 
1091   /* check if the connection has already been established */
1092   if(ssl_connection_complete == connssl->state) {
1093     *done = TRUE;
1094     return CURLE_OK;
1095   }
1096 
1097   if(ssl_connect_1 == connssl->connecting_state) {
1098     /* Find out how much more time we're allowed */
1099     timeout_ms = Curl_timeleft(data, NULL, TRUE);
1100 
1101     if(timeout_ms < 0) {
1102       /* no need to continue if time already is up */
1103       failf(data, "SSL connection timeout");
1104       return CURLE_OPERATION_TIMEDOUT;
1105     }
1106     retcode = mbed_connect_step1(cf, data);
1107     if(retcode)
1108       return retcode;
1109   }
1110 
1111   while(ssl_connect_2 == connssl->connecting_state ||
1112         ssl_connect_2_reading == connssl->connecting_state ||
1113         ssl_connect_2_writing == connssl->connecting_state) {
1114 
1115     /* check allowed time left */
1116     timeout_ms = Curl_timeleft(data, NULL, TRUE);
1117 
1118     if(timeout_ms < 0) {
1119       /* no need to continue if time already is up */
1120       failf(data, "SSL connection timeout");
1121       return CURLE_OPERATION_TIMEDOUT;
1122     }
1123 
1124     /* if ssl is expecting something, check if it's available. */
1125     if(connssl->connecting_state == ssl_connect_2_reading
1126        || connssl->connecting_state == ssl_connect_2_writing) {
1127 
1128       curl_socket_t writefd = ssl_connect_2_writing ==
1129         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
1130       curl_socket_t readfd = ssl_connect_2_reading ==
1131         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
1132 
1133       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
1134                                nonblocking ? 0 : timeout_ms);
1135       if(what < 0) {
1136         /* fatal error */
1137         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1138         return CURLE_SSL_CONNECT_ERROR;
1139       }
1140       else if(0 == what) {
1141         if(nonblocking) {
1142           *done = FALSE;
1143           return CURLE_OK;
1144         }
1145         else {
1146           /* timeout */
1147           failf(data, "SSL connection timeout");
1148           return CURLE_OPERATION_TIMEDOUT;
1149         }
1150       }
1151       /* socket is readable or writable */
1152     }
1153 
1154     /* Run transaction, and return to the caller if it failed or if
1155      * this connection is part of a multi handle and this loop would
1156      * execute again. This permits the owner of a multi handle to
1157      * abort a connection attempt before step2 has completed while
1158      * ensuring that a client using select() or epoll() will always
1159      * have a valid fdset to wait on.
1160      */
1161     retcode = mbed_connect_step2(cf, data);
1162     if(retcode || (nonblocking &&
1163                    (ssl_connect_2 == connssl->connecting_state ||
1164                     ssl_connect_2_reading == connssl->connecting_state ||
1165                     ssl_connect_2_writing == connssl->connecting_state)))
1166       return retcode;
1167 
1168   } /* repeat step2 until all transactions are done. */
1169 
1170   if(ssl_connect_3 == connssl->connecting_state) {
1171     retcode = mbed_connect_step3(cf, data);
1172     if(retcode)
1173       return retcode;
1174   }
1175 
1176   if(ssl_connect_done == connssl->connecting_state) {
1177     connssl->state = ssl_connection_complete;
1178     *done = TRUE;
1179   }
1180   else
1181     *done = FALSE;
1182 
1183   /* Reset our connect state machine */
1184   connssl->connecting_state = ssl_connect_1;
1185 
1186   return CURLE_OK;
1187 }
1188 
1189 static CURLcode mbedtls_connect_nonblocking(struct Curl_cfilter *cf,
1190                                             struct Curl_easy *data,
1191                                             bool *done)
1192 {
1193   return mbed_connect_common(cf, data, TRUE, done);
1194 }
1195 
1196 
1197 static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
1198                                 struct Curl_easy *data)
1199 {
1200   CURLcode retcode;
1201   bool done = FALSE;
1202 
1203   retcode = mbed_connect_common(cf, data, FALSE, &done);
1204   if(retcode)
1205     return retcode;
1206 
1207   DEBUGASSERT(done);
1208 
1209   return CURLE_OK;
1210 }
1211 
1212 /*
1213  * return 0 error initializing SSL
1214  * return 1 SSL initialized successfully
1215  */
1216 static int mbedtls_init(void)
1217 {
1218   return Curl_mbedtlsthreadlock_thread_setup();
1219 }
1220 
1221 static void mbedtls_cleanup(void)
1222 {
1223 #ifdef THREADING_SUPPORT
1224   mbedtls_entropy_free(&ts_entropy);
1225 #endif /* THREADING_SUPPORT */
1226   (void)Curl_mbedtlsthreadlock_thread_cleanup();
1227 }
1228 
1229 static bool mbedtls_data_pending(struct Curl_cfilter *cf,
1230                                  const struct Curl_easy *data)
1231 {
1232   struct ssl_connect_data *ctx = cf->ctx;
1233   struct mbed_ssl_backend_data *backend;
1234 
1235   (void)data;
1236   DEBUGASSERT(ctx && ctx->backend);
1237   backend = (struct mbed_ssl_backend_data *)ctx->backend;
1238   return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
1239 }
1240 
1241 static CURLcode mbedtls_sha256sum(const unsigned char *input,
1242                                   size_t inputlen,
1243                                   unsigned char *sha256sum,
1244                                   size_t sha256len UNUSED_PARAM)
1245 {
1246   /* TODO: explain this for different mbedtls 2.x vs 3 version */
1247   (void)sha256len;
1248 #if MBEDTLS_VERSION_NUMBER < 0x02070000
1249   mbedtls_sha256(input, inputlen, sha256sum, 0);
1250 #else
1251   /* returns 0 on success, otherwise failure */
1252 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
1253   if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0)
1254 #else
1255   if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
1256 #endif
1257     return CURLE_BAD_FUNCTION_ARGUMENT;
1258 #endif
1259   return CURLE_OK;
1260 }
1261 
1262 static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
1263                                    CURLINFO info UNUSED_PARAM)
1264 {
1265   struct mbed_ssl_backend_data *backend =
1266     (struct mbed_ssl_backend_data *)connssl->backend;
1267   (void)info;
1268   DEBUGASSERT(backend);
1269   return &backend->ssl;
1270 }
1271 
1272 const struct Curl_ssl Curl_ssl_mbedtls = {
1273   { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
1274 
1275   SSLSUPP_CA_PATH |
1276   SSLSUPP_CAINFO_BLOB |
1277   SSLSUPP_PINNEDPUBKEY |
1278   SSLSUPP_SSL_CTX |
1279   SSLSUPP_HTTPS_PROXY,
1280 
1281   sizeof(struct mbed_ssl_backend_data),
1282 
1283   mbedtls_init,                     /* init */
1284   mbedtls_cleanup,                  /* cleanup */
1285   mbedtls_version,                  /* version */
1286   Curl_none_check_cxn,              /* check_cxn */
1287   Curl_none_shutdown,               /* shutdown */
1288   mbedtls_data_pending,             /* data_pending */
1289   mbedtls_random,                   /* random */
1290   Curl_none_cert_status_request,    /* cert_status_request */
1291   mbedtls_connect,                  /* connect */
1292   mbedtls_connect_nonblocking,      /* connect_nonblocking */
1293   Curl_ssl_adjust_pollset,          /* adjust_pollset */
1294   mbedtls_get_internals,            /* get_internals */
1295   mbedtls_close,                    /* close_one */
1296   mbedtls_close_all,                /* close_all */
1297   mbedtls_session_free,             /* session_free */
1298   Curl_none_set_engine,             /* set_engine */
1299   Curl_none_set_engine_default,     /* set_engine_default */
1300   Curl_none_engines_list,           /* engines_list */
1301   Curl_none_false_start,            /* false_start */
1302   mbedtls_sha256sum,                /* sha256sum */
1303   NULL,                             /* associate_connection */
1304   NULL,                             /* disassociate_connection */
1305   NULL,                             /* free_multi_ssl_backend_data */
1306   mbed_recv,                        /* recv decrypted data */
1307   mbed_send,                        /* send data to encrypt */
1308 };
1309 
1310 #endif /* USE_MBEDTLS */
1311