xref: /curl/lib/vtls/mbedtls.c (revision bcf8a848)
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 #include <mbedtls/version.h>
40 #if MBEDTLS_VERSION_NUMBER >= 0x02040000
41 #include <mbedtls/net_sockets.h>
42 #else
43 #include <mbedtls/net.h>
44 #endif
45 #include <mbedtls/ssl.h>
46 #include <mbedtls/x509.h>
47 
48 #include <mbedtls/error.h>
49 #include <mbedtls/entropy.h>
50 #include <mbedtls/ctr_drbg.h>
51 #include <mbedtls/sha256.h>
52 
53 #if MBEDTLS_VERSION_MAJOR >= 2
54 #  ifdef MBEDTLS_DEBUG
55 #    include <mbedtls/debug.h>
56 #  endif
57 #endif /* MBEDTLS_VERSION_MAJOR >= 2 */
58 
59 #include "cipher_suite.h"
60 #include "strcase.h"
61 #include "urldata.h"
62 #include "sendf.h"
63 #include "inet_pton.h"
64 #include "mbedtls.h"
65 #include "vtls.h"
66 #include "vtls_int.h"
67 #include "x509asn1.h"
68 #include "parsedate.h"
69 #include "connect.h" /* for the connect timeout */
70 #include "select.h"
71 #include "multiif.h"
72 #include "mbedtls_threadlock.h"
73 #include "strdup.h"
74 
75 /* The last 3 #include files should be in this order */
76 #include "curl_printf.h"
77 #include "curl_memory.h"
78 #include "memdebug.h"
79 
80 /* ALPN for http2 */
81 #ifdef USE_HTTP2
82 #  undef HAS_ALPN
83 #  ifdef MBEDTLS_SSL_ALPN
84 #    define HAS_ALPN
85 #  endif
86 #endif
87 
88 struct mbed_ssl_backend_data {
89   mbedtls_ctr_drbg_context ctr_drbg;
90   mbedtls_entropy_context entropy;
91   mbedtls_ssl_context ssl;
92   mbedtls_x509_crt cacert;
93   mbedtls_x509_crt clicert;
94 #ifdef MBEDTLS_X509_CRL_PARSE_C
95   mbedtls_x509_crl crl;
96 #endif
97   mbedtls_pk_context pk;
98   mbedtls_ssl_config config;
99 #ifdef HAS_ALPN
100   const char *protocols[3];
101 #endif
102   int *ciphersuites;
103   BIT(initialized); /* mbedtls_ssl_context is initialized */
104   BIT(sent_shutdown);
105 };
106 
107 /* apply threading? */
108 #if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
109     defined(_WIN32)
110 #define THREADING_SUPPORT
111 #endif
112 
113 #ifndef MBEDTLS_ERROR_C
114 #define mbedtls_strerror(a,b,c) b[0] = 0
115 #endif
116 
117 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && MBEDTLS_VERSION_NUMBER >= 0x03060000
118 #define TLS13_SUPPORT
119 #endif
120 
121 #if defined(TLS13_SUPPORT) && defined(MBEDTLS_SSL_SESSION_TICKETS)
122 #define HAS_SESSION_TICKETS
123 #endif
124 
125 #ifdef THREADING_SUPPORT
126 static mbedtls_entropy_context ts_entropy;
127 
128 static int entropy_init_initialized = 0;
129 
entropy_init_mutex(mbedtls_entropy_context * ctx)130 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
131 {
132   /* lock 0 = entropy_init_mutex() */
133   Curl_mbedtlsthreadlock_lock_function(0);
134   if(entropy_init_initialized == 0) {
135     mbedtls_entropy_init(ctx);
136     entropy_init_initialized = 1;
137   }
138   Curl_mbedtlsthreadlock_unlock_function(0);
139 }
140 
entropy_cleanup_mutex(mbedtls_entropy_context * ctx)141 static void entropy_cleanup_mutex(mbedtls_entropy_context *ctx)
142 {
143   /* lock 0 = use same lock as init */
144   Curl_mbedtlsthreadlock_lock_function(0);
145   if(entropy_init_initialized == 1) {
146     mbedtls_entropy_free(ctx);
147     entropy_init_initialized = 0;
148   }
149   Curl_mbedtlsthreadlock_unlock_function(0);
150 }
151 
entropy_func_mutex(void * data,unsigned char * output,size_t len)152 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
153 {
154   int ret;
155   /* lock 1 = entropy_func_mutex() */
156   Curl_mbedtlsthreadlock_lock_function(1);
157   ret = mbedtls_entropy_func(data, output, len);
158   Curl_mbedtlsthreadlock_unlock_function(1);
159 
160   return ret;
161 }
162 
163 #endif /* THREADING_SUPPORT */
164 
165 #ifdef MBEDTLS_DEBUG
mbed_debug(void * context,int level,const char * f_name,int line_nb,const char * line)166 static void mbed_debug(void *context, int level, const char *f_name,
167                        int line_nb, const char *line)
168 {
169   struct Curl_easy *data = (struct Curl_easy *)context;
170   (void) level;
171   (void) line_nb;
172   (void) f_name;
173 
174   if(data) {
175     size_t len = strlen(line);
176     if(len && (line[len - 1] == '\n'))
177       /* discount any trailing newline */
178       len--;
179     infof(data, "%.*s", (int)len, line);
180   }
181 }
182 #endif
183 
mbedtls_bio_cf_write(void * bio,const unsigned char * buf,size_t blen)184 static int mbedtls_bio_cf_write(void *bio,
185                                 const unsigned char *buf, size_t blen)
186 {
187   struct Curl_cfilter *cf = bio;
188   struct Curl_easy *data = CF_DATA_CURRENT(cf);
189   ssize_t nwritten;
190   CURLcode result;
191 
192   DEBUGASSERT(data);
193   if(!data)
194     return 0;
195 
196   nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, FALSE,
197                                &result);
198   CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %zd, err=%d",
199               blen, nwritten, result);
200   if(nwritten < 0 && CURLE_AGAIN == result) {
201     nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
202   }
203   return (int)nwritten;
204 }
205 
mbedtls_bio_cf_read(void * bio,unsigned char * buf,size_t blen)206 static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen)
207 {
208   struct Curl_cfilter *cf = bio;
209   struct Curl_easy *data = CF_DATA_CURRENT(cf);
210   ssize_t nread;
211   CURLcode result;
212 
213   DEBUGASSERT(data);
214   if(!data)
215     return 0;
216   /* OpenSSL catches this case, so should we. */
217   if(!buf)
218     return 0;
219 
220   nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
221   CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %zd, err=%d",
222               blen, nread, result);
223   if(nread < 0 && CURLE_AGAIN == result) {
224     nread = MBEDTLS_ERR_SSL_WANT_READ;
225   }
226   return (int)nread;
227 }
228 
229 /*
230  *  profile
231  */
232 static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
233 {
234   /* Hashes from SHA-1 and above */
235   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
236   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) |
237   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) |
238   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
239   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
240   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
241   0xFFFFFFF, /* Any PK alg    */
242   0xFFFFFFF, /* Any curve     */
243   1024,      /* RSA min key len */
244 };
245 
246 /* See https://web.archive.org/web/20200921194007/tls.mbed.org/discussions/
247    generic/howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
248 */
249 #define RSA_PUB_DER_MAX_BYTES   (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
250 #define ECP_PUB_DER_MAX_BYTES   (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
251 
252 #define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
253                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
254 
255 static CURLcode
mbed_set_ssl_version_min_max(struct Curl_easy * data,struct mbed_ssl_backend_data * backend,struct ssl_primary_config * conn_config)256 mbed_set_ssl_version_min_max(struct Curl_easy *data,
257                              struct mbed_ssl_backend_data *backend,
258                              struct ssl_primary_config *conn_config)
259 {
260   /* TLS 1.0 and TLS 1.1 were dropped with mbedTLS 3.0.0 (2021). So, since
261    * then, and before the introduction of TLS 1.3 in 3.6.0 (2024), this
262    * function basically always sets TLS 1.2 as min/max, unless given
263    * unsupported option values. */
264 
265 #if MBEDTLS_VERSION_NUMBER < 0x03020000
266   int ver_min = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
267   int ver_max = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
268 #else
269   /* mbedTLS 3.2.0 (2022) introduced new methods for setting TLS version */
270   mbedtls_ssl_protocol_version ver_min = MBEDTLS_SSL_VERSION_TLS1_2;
271   mbedtls_ssl_protocol_version ver_max = MBEDTLS_SSL_VERSION_TLS1_2;
272 #endif
273 
274   switch(conn_config->version) {
275   case CURL_SSLVERSION_DEFAULT:
276 #if MBEDTLS_VERSION_NUMBER < 0x03000000
277   case CURL_SSLVERSION_TLSv1:
278   case CURL_SSLVERSION_TLSv1_0:
279     ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
280     break;
281   case CURL_SSLVERSION_TLSv1_1:
282     ver_min = MBEDTLS_SSL_MINOR_VERSION_2;
283     break;
284 #else
285   case CURL_SSLVERSION_TLSv1:
286   case CURL_SSLVERSION_TLSv1_0:
287   case CURL_SSLVERSION_TLSv1_1:
288 #endif
289   case CURL_SSLVERSION_TLSv1_2:
290     /* ver_min = MBEDTLS_SSL_VERSION_TLS1_2; */
291     break;
292   case CURL_SSLVERSION_TLSv1_3:
293 #ifdef TLS13_SUPPORT
294     ver_min = MBEDTLS_SSL_VERSION_TLS1_3;
295     break;
296 #endif
297   default:
298     failf(data, "mbedTLS: unsupported minimum TLS version value: %x",
299           conn_config->version);
300     return CURLE_SSL_CONNECT_ERROR;
301   }
302 
303   switch(conn_config->version_max) {
304   case CURL_SSLVERSION_MAX_DEFAULT:
305   case CURL_SSLVERSION_MAX_NONE:
306   case CURL_SSLVERSION_MAX_TLSv1_3:
307 #ifdef TLS13_SUPPORT
308     ver_max = MBEDTLS_SSL_VERSION_TLS1_3;
309     break;
310 #endif
311   case CURL_SSLVERSION_MAX_TLSv1_2:
312     /* ver_max = MBEDTLS_SSL_VERSION_TLS1_2; */
313     break;
314 #if MBEDTLS_VERSION_NUMBER < 0x03000000
315   case CURL_SSLVERSION_MAX_TLSv1_1:
316     ver_max = MBEDTLS_SSL_MINOR_VERSION_2;
317     break;
318   case CURL_SSLVERSION_MAX_TLSv1_0:
319     ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
320     break;
321 #else
322   case CURL_SSLVERSION_MAX_TLSv1_1:
323   case CURL_SSLVERSION_MAX_TLSv1_0:
324 #endif
325   default:
326     failf(data, "mbedTLS: unsupported maximum TLS version value");
327     return CURLE_SSL_CONNECT_ERROR;
328   }
329 
330 #if MBEDTLS_VERSION_NUMBER < 0x03020000
331   mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
332                                ver_min);
333   mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
334                                ver_max);
335 #else
336   mbedtls_ssl_conf_min_tls_version(&backend->config, ver_min);
337   mbedtls_ssl_conf_max_tls_version(&backend->config, ver_max);
338 #endif
339 
340   return CURLE_OK;
341 }
342 
343 /* TLS_ECJPAKE_WITH_AES_128_CCM_8 (0xC0FF) is marked experimental
344    in mbedTLS. The number is not reserved by IANA nor is the
345    cipher suite present in other SSL implementations. Provide
346    provisional support for specifying the cipher suite here. */
347 #ifdef MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
348 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
349 static int
mbed_cipher_suite_get_str(uint16_t id,char * buf,size_t buf_size,bool prefer_rfc)350 mbed_cipher_suite_get_str(uint16_t id, char *buf, size_t buf_size,
351                           bool prefer_rfc)
352 {
353   if(id == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
354     msnprintf(buf, buf_size, "%s", "TLS_ECJPAKE_WITH_AES_128_CCM_8");
355   else
356     return Curl_cipher_suite_get_str(id, buf, buf_size, prefer_rfc);
357   return 0;
358 }
359 #endif
360 
361 static uint16_t
mbed_cipher_suite_walk_str(const char ** str,const char ** end)362 mbed_cipher_suite_walk_str(const char **str, const char **end)
363 {
364   uint16_t id = Curl_cipher_suite_walk_str(str, end);
365   size_t len = *end - *str;
366 
367   if(!id) {
368     if(strncasecompare("TLS_ECJPAKE_WITH_AES_128_CCM_8", *str, len))
369       id = MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8;
370   }
371   return id;
372 }
373 #else
374 #define mbed_cipher_suite_get_str Curl_cipher_suite_get_str
375 #define mbed_cipher_suite_walk_str Curl_cipher_suite_walk_str
376 #endif
377 
378 static CURLcode
mbed_set_selected_ciphers(struct Curl_easy * data,struct mbed_ssl_backend_data * backend,const char * ciphers12,const char * ciphers13)379 mbed_set_selected_ciphers(struct Curl_easy *data,
380                           struct mbed_ssl_backend_data *backend,
381                           const char *ciphers12,
382                           const char *ciphers13)
383 {
384   const char *ciphers = ciphers12;
385   const int *supported;
386   int *selected;
387   size_t supported_len, count = 0, default13_count = 0, i, j;
388   const char *ptr, *end;
389 
390   supported = mbedtls_ssl_list_ciphersuites();
391   for(i = 0; supported[i] != 0; i++);
392   supported_len = i;
393 
394   selected = malloc(sizeof(int) * (supported_len + 1));
395   if(!selected)
396     return CURLE_OUT_OF_MEMORY;
397 
398 #ifndef TLS13_SUPPORT
399   (void) ciphers13, (void) j;
400 #else
401   if(!ciphers13) {
402     /* Add default TLSv1.3 ciphers to selection */
403     for(j = 0; j < supported_len; j++) {
404       uint16_t id = (uint16_t) supported[j];
405       if(strncmp(mbedtls_ssl_get_ciphersuite_name(id), "TLS1-3", 6) != 0)
406         continue;
407 
408       selected[count++] = id;
409     }
410 
411     default13_count = count;
412   }
413   else
414     ciphers = ciphers13;
415 
416 add_ciphers:
417 #endif
418   for(ptr = ciphers; ptr[0] != '\0' && count < supported_len; ptr = end) {
419     uint16_t id = mbed_cipher_suite_walk_str(&ptr, &end);
420 
421     /* Check if cipher is supported */
422     if(id) {
423       for(i = 0; i < supported_len && supported[i] != id; i++);
424       if(i == supported_len)
425         id = 0;
426     }
427     if(!id) {
428       if(ptr[0] != '\0')
429         infof(data, "mbedTLS: unknown cipher in list: \"%.*s\"",
430               (int) (end - ptr), ptr);
431       continue;
432     }
433 
434     /* No duplicates allowed (so selected cannot overflow) */
435     for(i = 0; i < count && selected[i] != id; i++);
436     if(i < count) {
437       if(i >= default13_count)
438         infof(data, "mbedTLS: duplicate cipher in list: \"%.*s\"",
439               (int) (end - ptr), ptr);
440       continue;
441     }
442 
443     selected[count++] = id;
444   }
445 
446 #ifdef TLS13_SUPPORT
447   if(ciphers == ciphers13 && ciphers12) {
448     ciphers = ciphers12;
449     goto add_ciphers;
450   }
451 
452   if(!ciphers12) {
453     /* Add default TLSv1.2 ciphers to selection */
454     for(j = 0; j < supported_len; j++) {
455       uint16_t id = (uint16_t) supported[j];
456       if(strncmp(mbedtls_ssl_get_ciphersuite_name(id), "TLS1-3", 6) == 0)
457         continue;
458 
459       /* No duplicates allowed (so selected cannot overflow) */
460       for(i = 0; i < count && selected[i] != id; i++);
461       if(i < count)
462         continue;
463 
464       selected[count++] = id;
465     }
466   }
467 #endif
468 
469   selected[count] = 0;
470 
471   if(count == 0) {
472     free(selected);
473     failf(data, "mbedTLS: no supported cipher in list");
474     return CURLE_SSL_CIPHER;
475   }
476 
477   /* mbedtls_ssl_conf_ciphersuites(): The ciphersuites array is not copied.
478      It must remain valid for the lifetime of the SSL configuration */
479   backend->ciphersuites = selected;
480   mbedtls_ssl_conf_ciphersuites(&backend->config, backend->ciphersuites);
481   return CURLE_OK;
482 }
483 
484 static void
mbed_dump_cert_info(struct Curl_easy * data,const mbedtls_x509_crt * crt)485 mbed_dump_cert_info(struct Curl_easy *data, const mbedtls_x509_crt *crt)
486 {
487 #if defined(CURL_DISABLE_VERBOSE_STRINGS) || \
488     (MBEDTLS_VERSION_NUMBER >= 0x03000000 && defined(MBEDTLS_X509_REMOVE_INFO))
489   (void) data, (void) crt;
490 #else
491   const size_t bufsize = 16384;
492   char *p, *buffer = malloc(bufsize);
493 
494   if(buffer && mbedtls_x509_crt_info(buffer, bufsize, " ", crt) > 0) {
495     infof(data, "Server certificate:");
496     for(p = buffer; *p; p += *p != '\0') {
497       size_t s = strcspn(p, "\n");
498       infof(data, "%.*s", (int) s, p);
499       p += s;
500     }
501   }
502   else
503     infof(data, "Unable to dump certificate information");
504 
505   free(buffer);
506 #endif
507 }
508 
509 static void
mbed_extract_certinfo(struct Curl_easy * data,const mbedtls_x509_crt * crt)510 mbed_extract_certinfo(struct Curl_easy *data, const mbedtls_x509_crt *crt)
511 {
512   CURLcode result;
513   const mbedtls_x509_crt *cur;
514   int i;
515 
516   for(i = 0, cur = crt; cur; ++i, cur = cur->next);
517   result = Curl_ssl_init_certinfo(data, i);
518 
519   for(i = 0, cur = crt; result == CURLE_OK && cur; ++i, cur = cur->next) {
520     const char *beg = (const char *) cur->raw.p;
521     const char *end = beg + cur->raw.len;
522     result = Curl_extract_certinfo(data, i, beg, end);
523   }
524 }
525 
mbed_verify_cb(void * ptr,mbedtls_x509_crt * crt,int depth,uint32_t * flags)526 static int mbed_verify_cb(void *ptr, mbedtls_x509_crt *crt,
527                           int depth, uint32_t *flags)
528 {
529   struct Curl_cfilter *cf = (struct Curl_cfilter *) ptr;
530   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
531   struct Curl_easy *data = CF_DATA_CURRENT(cf);
532 
533   if(depth == 0) {
534     if(data->set.verbose)
535       mbed_dump_cert_info(data, crt);
536     if(data->set.ssl.certinfo)
537       mbed_extract_certinfo(data, crt);
538   }
539 
540   if(!conn_config->verifypeer)
541     *flags = 0;
542   else if(!conn_config->verifyhost)
543     *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
544 
545   if(*flags) {
546 #if MBEDTLS_VERSION_NUMBER < 0x03000000 || !defined(MBEDTLS_X509_REMOVE_INFO)
547     char buf[128];
548     mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags);
549     failf(data, "mbedTLS: %s", buf);
550 #else
551     failf(data, "mbedTLS: certificate verification error 0x%08x", *flags);
552 #endif
553   }
554 
555   return 0;
556 }
557 
558 static CURLcode
mbed_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)559 mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
560 {
561   struct ssl_connect_data *connssl = cf->ctx;
562   struct mbed_ssl_backend_data *backend =
563     (struct mbed_ssl_backend_data *)connssl->backend;
564   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
565   const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
566   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
567   const char * const ssl_cafile =
568     /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
569     (ca_info_blob ? NULL : conn_config->CAfile);
570   const bool verifypeer = conn_config->verifypeer;
571   const char * const ssl_capath = conn_config->CApath;
572   char * const ssl_cert = ssl_config->primary.clientcert;
573   const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
574   const char * const ssl_crlfile = ssl_config->primary.CRLfile;
575   const char *hostname = connssl->peer.hostname;
576   int ret = -1;
577   char errorbuf[128];
578 
579   DEBUGASSERT(backend);
580   DEBUGASSERT(!backend->initialized);
581 
582   if((conn_config->version == CURL_SSLVERSION_SSLv2) ||
583      (conn_config->version == CURL_SSLVERSION_SSLv3)) {
584     failf(data, "Not supported SSL version");
585     return CURLE_NOT_BUILT_IN;
586   }
587 
588 #ifdef THREADING_SUPPORT
589   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
590 
591   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
592                               &ts_entropy, NULL, 0);
593   if(ret) {
594     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
595     failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
596           -ret, errorbuf);
597     return CURLE_FAILED_INIT;
598   }
599 #else
600   mbedtls_entropy_init(&backend->entropy);
601   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
602 
603   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func,
604                               &backend->entropy, NULL, 0);
605   if(ret) {
606     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
607     failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
608           -ret, errorbuf);
609     return CURLE_FAILED_INIT;
610   }
611 #endif /* THREADING_SUPPORT */
612 
613   /* Load the trusted CA */
614   mbedtls_x509_crt_init(&backend->cacert);
615 
616   if(ca_info_blob && verifypeer) {
617     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
618        terminated even when provided the exact length, forcing us to waste
619        extra memory here. */
620     unsigned char *newblob = Curl_memdup0(ca_info_blob->data,
621                                           ca_info_blob->len);
622     if(!newblob)
623       return CURLE_OUT_OF_MEMORY;
624     ret = mbedtls_x509_crt_parse(&backend->cacert, newblob,
625                                  ca_info_blob->len + 1);
626     free(newblob);
627     if(ret < 0) {
628       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
629       failf(data, "Error importing ca cert blob - mbedTLS: (-0x%04X) %s",
630             -ret, errorbuf);
631       return CURLE_SSL_CERTPROBLEM;
632     }
633   }
634 
635   if(ssl_cafile && verifypeer) {
636 #ifdef MBEDTLS_FS_IO
637     ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile);
638 
639     if(ret < 0) {
640       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
641       failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
642             ssl_cafile, -ret, errorbuf);
643       return CURLE_SSL_CACERT_BADFILE;
644     }
645 #else
646     failf(data, "mbedtls: functions that use the filesystem not built in");
647     return CURLE_NOT_BUILT_IN;
648 #endif
649   }
650 
651   if(ssl_capath) {
652 #ifdef MBEDTLS_FS_IO
653     ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath);
654 
655     if(ret < 0) {
656       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
657       failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
658             ssl_capath, -ret, errorbuf);
659 
660       if(verifypeer)
661         return CURLE_SSL_CACERT_BADFILE;
662     }
663 #else
664     failf(data, "mbedtls: functions that use the filesystem not built in");
665     return CURLE_NOT_BUILT_IN;
666 #endif
667   }
668 
669   /* Load the client certificate */
670   mbedtls_x509_crt_init(&backend->clicert);
671 
672   if(ssl_cert) {
673 #ifdef MBEDTLS_FS_IO
674     ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert);
675 
676     if(ret) {
677       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
678       failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
679             ssl_cert, -ret, errorbuf);
680 
681       return CURLE_SSL_CERTPROBLEM;
682     }
683 #else
684     failf(data, "mbedtls: functions that use the filesystem not built in");
685     return CURLE_NOT_BUILT_IN;
686 #endif
687   }
688 
689   if(ssl_cert_blob) {
690     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
691        terminated even when provided the exact length, forcing us to waste
692        extra memory here. */
693     unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data,
694                                           ssl_cert_blob->len);
695     if(!newblob)
696       return CURLE_OUT_OF_MEMORY;
697     ret = mbedtls_x509_crt_parse(&backend->clicert, newblob,
698                                  ssl_cert_blob->len + 1);
699     free(newblob);
700 
701     if(ret) {
702       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
703       failf(data, "Error reading client cert data %s - mbedTLS: (-0x%04X) %s",
704             ssl_config->key, -ret, errorbuf);
705       return CURLE_SSL_CERTPROBLEM;
706     }
707   }
708 
709   /* Load the client private key */
710   mbedtls_pk_init(&backend->pk);
711 
712   if(ssl_config->key || ssl_config->key_blob) {
713     if(ssl_config->key) {
714 #ifdef MBEDTLS_FS_IO
715 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
716       ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
717                                      ssl_config->key_passwd,
718                                      mbedtls_ctr_drbg_random,
719                                      &backend->ctr_drbg);
720 #else
721       ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
722                                      ssl_config->key_passwd);
723 #endif
724 
725       if(ret) {
726         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
727         failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
728               ssl_config->key, -ret, errorbuf);
729         return CURLE_SSL_CERTPROBLEM;
730       }
731 #else
732       failf(data, "mbedtls: functions that use the filesystem not built in");
733       return CURLE_NOT_BUILT_IN;
734 #endif
735     }
736     else {
737       const struct curl_blob *ssl_key_blob = ssl_config->key_blob;
738       const unsigned char *key_data =
739         (const unsigned char *)ssl_key_blob->data;
740       const char *passwd = ssl_config->key_passwd;
741 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
742       ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
743                                  (const unsigned char *)passwd,
744                                  passwd ? strlen(passwd) : 0,
745                                  mbedtls_ctr_drbg_random,
746                                  &backend->ctr_drbg);
747 #else
748       ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
749                                  (const unsigned char *)passwd,
750                                  passwd ? strlen(passwd) : 0);
751 #endif
752 
753       if(ret) {
754         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
755         failf(data, "Error parsing private key - mbedTLS: (-0x%04X) %s",
756               -ret, errorbuf);
757         return CURLE_SSL_CERTPROBLEM;
758       }
759     }
760 
761     if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
762                      mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
763       ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
764   }
765 
766   /* Load the CRL */
767 #ifdef MBEDTLS_X509_CRL_PARSE_C
768   mbedtls_x509_crl_init(&backend->crl);
769 
770   if(ssl_crlfile) {
771 #ifdef MBEDTLS_FS_IO
772     ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile);
773 
774     if(ret) {
775       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
776       failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
777             ssl_crlfile, -ret, errorbuf);
778 
779       return CURLE_SSL_CRL_BADFILE;
780     }
781 #else
782     failf(data, "mbedtls: functions that use the filesystem not built in");
783     return CURLE_NOT_BUILT_IN;
784 #endif
785   }
786 #else
787   if(ssl_crlfile) {
788     failf(data, "mbedtls: crl support not built in");
789     return CURLE_NOT_BUILT_IN;
790   }
791 #endif
792 
793   infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->peer.port);
794 
795   mbedtls_ssl_config_init(&backend->config);
796   ret = mbedtls_ssl_config_defaults(&backend->config,
797                                     MBEDTLS_SSL_IS_CLIENT,
798                                     MBEDTLS_SSL_TRANSPORT_STREAM,
799                                     MBEDTLS_SSL_PRESET_DEFAULT);
800   if(ret) {
801     failf(data, "mbedTLS: ssl_config failed");
802     return CURLE_SSL_CONNECT_ERROR;
803   }
804 
805 #ifdef MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED
806   /* New in mbedTLS 3.6.1, need to enable, default is now disabled */
807   mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(&backend->config,
808     MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED);
809 #endif
810 
811   /* Always let mbedTLS verify certificates, if verifypeer or verifyhost are
812    * disabled we clear the corresponding error flags in the verify callback
813    * function. That is also where we log verification errors. */
814   mbedtls_ssl_conf_verify(&backend->config, mbed_verify_cb, cf);
815   mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_REQUIRED);
816 
817   mbedtls_ssl_init(&backend->ssl);
818   backend->initialized = TRUE;
819 
820   /* new profile with RSA min key len = 1024 ... */
821   mbedtls_ssl_conf_cert_profile(&backend->config,
822                                 &mbedtls_x509_crt_profile_fr);
823 
824   ret = mbed_set_ssl_version_min_max(data, backend, conn_config);
825   if(ret != CURLE_OK)
826     return ret;
827 
828   mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
829                        &backend->ctr_drbg);
830 
831   ret = mbedtls_ssl_setup(&backend->ssl, &backend->config);
832   if(ret) {
833     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
834     failf(data, "ssl_setup failed - mbedTLS: (-0x%04X) %s",
835           -ret, errorbuf);
836     return CURLE_SSL_CONNECT_ERROR;
837   }
838 
839   mbedtls_ssl_set_bio(&backend->ssl, cf,
840                       mbedtls_bio_cf_write,
841                       mbedtls_bio_cf_read,
842                       NULL /*  rev_timeout() */);
843 
844 #ifndef TLS13_SUPPORT
845   if(conn_config->cipher_list) {
846     CURLcode result = mbed_set_selected_ciphers(data, backend,
847                                                 conn_config->cipher_list,
848                                                 NULL);
849 #else
850   if(conn_config->cipher_list || conn_config->cipher_list13) {
851     CURLcode result = mbed_set_selected_ciphers(data, backend,
852                                                 conn_config->cipher_list,
853                                                 conn_config->cipher_list13);
854 #endif
855     if(result != CURLE_OK) {
856       failf(data, "mbedTLS: failed to set cipher suites");
857       return result;
858     }
859   }
860   else {
861     mbedtls_ssl_conf_ciphersuites(&backend->config,
862                                   mbedtls_ssl_list_ciphersuites());
863   }
864 
865 
866 #if defined(MBEDTLS_SSL_RENEGOTIATION)
867   mbedtls_ssl_conf_renegotiation(&backend->config,
868                                  MBEDTLS_SSL_RENEGOTIATION_ENABLED);
869 #endif
870 
871 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
872   mbedtls_ssl_conf_session_tickets(&backend->config,
873                                    MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
874 #endif
875 
876   /* Check if there is a cached ID we can/should use here! */
877   if(ssl_config->primary.cache_session) {
878     void *sdata = NULL;
879     size_t slen = 0;
880 
881     Curl_ssl_sessionid_lock(data);
882     if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
883                               &sdata, &slen, NULL) && slen) {
884       mbedtls_ssl_session session;
885 
886       mbedtls_ssl_session_init(&session);
887       ret = mbedtls_ssl_session_load(&session, sdata, slen);
888       if(ret) {
889         failf(data, "error loading cached session: -0x%x", -ret);
890       }
891       else {
892         ret = mbedtls_ssl_set_session(&backend->ssl, &session);
893         if(ret)
894           failf(data, "error setting session: -0x%x", -ret);
895         else
896           infof(data, "SSL reusing session ID");
897       }
898       mbedtls_ssl_session_free(&session);
899     }
900     Curl_ssl_sessionid_unlock(data);
901   }
902 
903   mbedtls_ssl_conf_ca_chain(&backend->config,
904                             &backend->cacert,
905 #ifdef MBEDTLS_X509_CRL_PARSE_C
906                             &backend->crl);
907 #else
908                             NULL);
909 #endif
910 
911   if(ssl_config->key || ssl_config->key_blob) {
912     mbedtls_ssl_conf_own_cert(&backend->config,
913                               &backend->clicert, &backend->pk);
914   }
915 
916   if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni ?
917                               connssl->peer.sni : connssl->peer.hostname)) {
918     /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and
919        the name to set in the SNI extension. So even if curl connects to a
920        host specified as an IP address, this function must be used. */
921     failf(data, "Failed to set SNI");
922     return CURLE_SSL_CONNECT_ERROR;
923   }
924 
925 #ifdef HAS_ALPN
926   if(connssl->alpn) {
927     struct alpn_proto_buf proto;
928     size_t i;
929 
930     for(i = 0; i < connssl->alpn->count; ++i) {
931       backend->protocols[i] = connssl->alpn->entries[i];
932     }
933     /* this function does not clone the protocols array, which is why we need
934        to keep it around */
935     if(mbedtls_ssl_conf_alpn_protocols(&backend->config,
936                                        &backend->protocols[0])) {
937       failf(data, "Failed setting ALPN protocols");
938       return CURLE_SSL_CONNECT_ERROR;
939     }
940     Curl_alpn_to_proto_str(&proto, connssl->alpn);
941     infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
942   }
943 #endif
944 
945 #ifdef MBEDTLS_DEBUG
946   /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
947   mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data);
948   /* - 0 No debug
949    * - 1 Error
950    * - 2 State change
951    * - 3 Informational
952    * - 4 Verbose
953    */
954   mbedtls_debug_set_threshold(4);
955 #endif
956 
957   /* give application a chance to interfere with mbedTLS set up. */
958   if(data->set.ssl.fsslctx) {
959     CURLcode result = (*data->set.ssl.fsslctx)(data, &backend->config,
960                                                data->set.ssl.fsslctxp);
961     if(result != CURLE_OK) {
962       failf(data, "error signaled by ssl ctx callback");
963       return result;
964     }
965   }
966 
967   connssl->connecting_state = ssl_connect_2;
968 
969   return CURLE_OK;
970 }
971 
972 static CURLcode
973 mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
974 {
975   int ret;
976   struct ssl_connect_data *connssl = cf->ctx;
977   struct mbed_ssl_backend_data *backend =
978     (struct mbed_ssl_backend_data *)connssl->backend;
979 #ifndef CURL_DISABLE_PROXY
980   const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
981     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
982     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
983 #else
984   const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
985 #endif
986 
987   DEBUGASSERT(backend);
988 
989   ret = mbedtls_ssl_handshake(&backend->ssl);
990 
991   if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
992     connssl->io_need = CURL_SSL_IO_NEED_RECV;
993     return CURLE_OK;
994   }
995   else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
996     connssl->io_need = CURL_SSL_IO_NEED_SEND;
997     return CURLE_OK;
998   }
999   else if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
1000     failf(data, "peer certificate could not be verified");
1001     return CURLE_PEER_FAILED_VERIFICATION;
1002   }
1003   else if(ret) {
1004     char errorbuf[128];
1005 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
1006     CURL_TRC_CF(data, cf, "TLS version %04X",
1007                 mbedtls_ssl_get_version_number(&backend->ssl));
1008 #endif
1009     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
1010     failf(data, "ssl_handshake returned: (-0x%04X) %s",
1011           -ret, errorbuf);
1012     return CURLE_SSL_CONNECT_ERROR;
1013   }
1014 
1015 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
1016   {
1017     char cipher_str[64];
1018     uint16_t cipher_id;
1019     cipher_id = (uint16_t)
1020                 mbedtls_ssl_get_ciphersuite_id_from_ssl(&backend->ssl);
1021     mbed_cipher_suite_get_str(cipher_id, cipher_str, sizeof(cipher_str), TRUE);
1022     infof(data, "mbedTLS: %s Handshake complete, cipher is %s",
1023           mbedtls_ssl_get_version(&backend->ssl), cipher_str);
1024   }
1025 #else
1026   infof(data, "mbedTLS: %s Handshake complete",
1027         mbedtls_ssl_get_version(&backend->ssl));
1028 #endif
1029 
1030   if(pinnedpubkey) {
1031     int size;
1032     CURLcode result;
1033     const mbedtls_x509_crt *peercert;
1034     mbedtls_x509_crt *p = NULL;
1035     unsigned char *pubkey = NULL;
1036 
1037     peercert = mbedtls_ssl_get_peer_cert(&backend->ssl);
1038 #if MBEDTLS_VERSION_NUMBER == 0x03000000
1039     if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) ||
1040        !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) {
1041 #else
1042     if(!peercert || !peercert->raw.p || !peercert->raw.len) {
1043 #endif
1044       failf(data, "Failed due to missing peer certificate");
1045       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1046     }
1047 
1048     p = calloc(1, sizeof(*p));
1049 
1050     if(!p)
1051       return CURLE_OUT_OF_MEMORY;
1052 
1053     pubkey = malloc(PUB_DER_MAX_BYTES);
1054 
1055     if(!pubkey) {
1056       result = CURLE_OUT_OF_MEMORY;
1057       goto pinnedpubkey_error;
1058     }
1059 
1060     mbedtls_x509_crt_init(p);
1061 
1062     /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
1063        needs a non-const key, for now.
1064        https://github.com/Mbed-TLS/mbedtls/issues/396 */
1065 #if MBEDTLS_VERSION_NUMBER == 0x03000000
1066     if(mbedtls_x509_crt_parse_der(p,
1067                         peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
1068                         peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) {
1069 #else
1070     if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
1071 #endif
1072       failf(data, "Failed copying peer certificate");
1073       result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1074       goto pinnedpubkey_error;
1075     }
1076 
1077 #if MBEDTLS_VERSION_NUMBER == 0x03000000
1078     size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey,
1079                                        PUB_DER_MAX_BYTES);
1080 #else
1081     size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
1082 #endif
1083 
1084     if(size <= 0) {
1085       failf(data, "Failed copying public key from peer certificate");
1086       result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1087       goto pinnedpubkey_error;
1088     }
1089 
1090     /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
1091     result = Curl_pin_peer_pubkey(data,
1092                                   pinnedpubkey,
1093                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
1094 pinnedpubkey_error:
1095     mbedtls_x509_crt_free(p);
1096     free(p);
1097     free(pubkey);
1098     if(result) {
1099       return result;
1100     }
1101   }
1102 
1103 #ifdef HAS_ALPN
1104   if(connssl->alpn) {
1105     const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
1106 
1107     Curl_alpn_set_negotiated(cf, data, connssl, (const unsigned char *)proto,
1108                              proto ? strlen(proto) : 0);
1109   }
1110 #endif
1111 
1112   connssl->connecting_state = ssl_connect_3;
1113   infof(data, "SSL connected");
1114 
1115   return CURLE_OK;
1116 }
1117 
1118 static void mbedtls_session_free(void *session, size_t slen)
1119 {
1120   (void)slen;
1121   free(session);
1122 }
1123 
1124 static CURLcode
1125 mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data)
1126 {
1127   struct ssl_connect_data *connssl = cf->ctx;
1128   struct mbed_ssl_backend_data *backend =
1129     (struct mbed_ssl_backend_data *)connssl->backend;
1130   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1131   CURLcode result = CURLE_OK;
1132 
1133   DEBUGASSERT(backend);
1134   if(ssl_config->primary.cache_session) {
1135     int ret;
1136     mbedtls_ssl_session session;
1137     unsigned char *sdata = NULL;
1138     size_t slen = 0;
1139 
1140     mbedtls_ssl_session_init(&session);
1141     ret = mbedtls_ssl_get_session(&backend->ssl, &session);
1142     if(ret) {
1143       if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED)
1144         mbedtls_ssl_session_free(&session);
1145       failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
1146       return CURLE_SSL_CONNECT_ERROR;
1147     }
1148 
1149     mbedtls_ssl_session_save(&session, NULL, 0, &slen);
1150     if(!slen) {
1151       failf(data, "failed to serialize session: length is 0");
1152     }
1153     else {
1154       sdata = malloc(slen);
1155       if(sdata) {
1156         ret = mbedtls_ssl_session_save(&session, sdata, slen, &slen);
1157         if(ret) {
1158           failf(data, "failed to serialize session: -0x%x", -ret);
1159         }
1160         else {
1161           Curl_ssl_sessionid_lock(data);
1162           result = Curl_ssl_set_sessionid(cf, data, &connssl->peer, NULL,
1163                                           sdata, slen, mbedtls_session_free);
1164           Curl_ssl_sessionid_unlock(data);
1165           if(!result)
1166             sdata = NULL;
1167         }
1168       }
1169     }
1170     mbedtls_ssl_session_free(&session);
1171     free(sdata);
1172   }
1173   return result;
1174 }
1175 
1176 static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
1177                          const void *mem, size_t len,
1178                          CURLcode *curlcode)
1179 {
1180   struct ssl_connect_data *connssl = cf->ctx;
1181   struct mbed_ssl_backend_data *backend =
1182     (struct mbed_ssl_backend_data *)connssl->backend;
1183   int ret = -1;
1184 
1185   (void)data;
1186   DEBUGASSERT(backend);
1187   ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
1188 
1189   if(ret < 0) {
1190     CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X",
1191                 len, -ret);
1192     *curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_WRITE)
1193 #ifdef TLS13_SUPPORT
1194       || (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
1195 #endif
1196       ) ? CURLE_AGAIN : CURLE_SEND_ERROR;
1197     ret = -1;
1198   }
1199 
1200   return ret;
1201 }
1202 
1203 static void mbedtls_close_all(struct Curl_easy *data)
1204 {
1205   (void)data;
1206 }
1207 
1208 static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf,
1209                                  struct Curl_easy *data,
1210                                  bool send_shutdown, bool *done)
1211 {
1212   struct ssl_connect_data *connssl = cf->ctx;
1213   struct mbed_ssl_backend_data *backend =
1214     (struct mbed_ssl_backend_data *)connssl->backend;
1215   unsigned char buf[1024];
1216   CURLcode result = CURLE_OK;
1217   int ret;
1218   size_t i;
1219 
1220   DEBUGASSERT(backend);
1221 
1222   if(!backend->initialized || cf->shutdown) {
1223     *done = TRUE;
1224     return CURLE_OK;
1225   }
1226 
1227   connssl->io_need = CURL_SSL_IO_NEED_NONE;
1228   *done = FALSE;
1229 
1230   if(!backend->sent_shutdown) {
1231     /* do this only once */
1232     backend->sent_shutdown = TRUE;
1233     if(send_shutdown) {
1234       ret = mbedtls_ssl_close_notify(&backend->ssl);
1235       switch(ret) {
1236       case 0: /* we sent it, receive from the server */
1237         break;
1238       case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: /* server also closed */
1239         *done = TRUE;
1240         goto out;
1241       case MBEDTLS_ERR_SSL_WANT_READ:
1242         connssl->io_need = CURL_SSL_IO_NEED_RECV;
1243         goto out;
1244       case MBEDTLS_ERR_SSL_WANT_WRITE:
1245         connssl->io_need = CURL_SSL_IO_NEED_SEND;
1246         goto out;
1247       default:
1248         CURL_TRC_CF(data, cf, "mbedtls_shutdown error -0x%04X", -ret);
1249         result = CURLE_RECV_ERROR;
1250         goto out;
1251       }
1252     }
1253   }
1254 
1255   /* SSL should now have started the shutdown from our side. Since it
1256    * was not complete, we are lacking the close notify from the server. */
1257   for(i = 0; i < 10; ++i) {
1258     ret = mbedtls_ssl_read(&backend->ssl, buf, sizeof(buf));
1259     /* This seems to be a bug in mbedTLS TLSv1.3 where it reports
1260      * WANT_READ, but has not encountered an EAGAIN. */
1261     if(ret == MBEDTLS_ERR_SSL_WANT_READ)
1262       ret = mbedtls_ssl_read(&backend->ssl, buf, sizeof(buf));
1263 #ifdef TLS13_SUPPORT
1264     if(ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
1265       continue;
1266 #endif
1267     if(ret <= 0)
1268       break;
1269   }
1270 
1271   if(ret > 0) {
1272     /* still data coming in? */
1273     CURL_TRC_CF(data, cf, "mbedtls_shutdown, still getting data");
1274   }
1275   else if(ret == 0 || (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)) {
1276     /* We got the close notify alert and are done. */
1277     CURL_TRC_CF(data, cf, "mbedtls_shutdown done");
1278     *done = TRUE;
1279   }
1280   else if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
1281     CURL_TRC_CF(data, cf, "mbedtls_shutdown, need RECV");
1282     connssl->io_need = CURL_SSL_IO_NEED_RECV;
1283   }
1284   else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
1285     CURL_TRC_CF(data, cf, "mbedtls_shutdown, need SEND");
1286     connssl->io_need = CURL_SSL_IO_NEED_SEND;
1287   }
1288   else {
1289     CURL_TRC_CF(data, cf, "mbedtls_shutdown error -0x%04X", -ret);
1290     result = CURLE_RECV_ERROR;
1291   }
1292 
1293 out:
1294   cf->shutdown = (result || *done);
1295   return result;
1296 }
1297 
1298 static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1299 {
1300   struct ssl_connect_data *connssl = cf->ctx;
1301   struct mbed_ssl_backend_data *backend =
1302     (struct mbed_ssl_backend_data *)connssl->backend;
1303 
1304   (void)data;
1305   DEBUGASSERT(backend);
1306   if(backend->initialized) {
1307     mbedtls_pk_free(&backend->pk);
1308     mbedtls_x509_crt_free(&backend->clicert);
1309     mbedtls_x509_crt_free(&backend->cacert);
1310 #ifdef MBEDTLS_X509_CRL_PARSE_C
1311     mbedtls_x509_crl_free(&backend->crl);
1312 #endif
1313     Curl_safefree(backend->ciphersuites);
1314     mbedtls_ssl_config_free(&backend->config);
1315     mbedtls_ssl_free(&backend->ssl);
1316     mbedtls_ctr_drbg_free(&backend->ctr_drbg);
1317 #ifndef THREADING_SUPPORT
1318     mbedtls_entropy_free(&backend->entropy);
1319 #endif /* THREADING_SUPPORT */
1320     backend->initialized = FALSE;
1321   }
1322 }
1323 
1324 static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
1325                          char *buf, size_t buffersize,
1326                          CURLcode *curlcode)
1327 {
1328   struct ssl_connect_data *connssl = cf->ctx;
1329   struct mbed_ssl_backend_data *backend =
1330     (struct mbed_ssl_backend_data *)connssl->backend;
1331   int ret = -1;
1332 
1333   (void)data;
1334   DEBUGASSERT(backend);
1335 
1336   ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
1337                          buffersize);
1338   if(ret <= 0) {
1339     CURL_TRC_CF(data, cf, "mbedtls_ssl_read(len=%zu) -> -0x%04X",
1340                 buffersize, -ret);
1341     switch(ret) {
1342 #ifdef HAS_SESSION_TICKETS
1343     case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET:
1344       mbed_new_session(cf, data);
1345       FALLTHROUGH();
1346 #endif
1347     case MBEDTLS_ERR_SSL_WANT_READ:
1348       *curlcode = CURLE_AGAIN;
1349       ret = -1;
1350       break;
1351     case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1352       *curlcode = CURLE_OK;
1353       ret = 0;
1354       break;
1355     default: {
1356       char errorbuf[128];
1357       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
1358       failf(data, "ssl_read returned: (-0x%04X) %s", -ret, errorbuf);
1359       *curlcode = CURLE_RECV_ERROR;
1360       ret = -1;
1361       break;
1362     }
1363     }
1364   }
1365   return (ssize_t)ret;
1366 }
1367 
1368 static size_t mbedtls_version(char *buffer, size_t size)
1369 {
1370 #ifdef MBEDTLS_VERSION_C
1371   /* if mbedtls_version_get_number() is available it is better */
1372   unsigned int version = mbedtls_version_get_number();
1373   return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version >> 24,
1374                    (version >> 16) & 0xff, (version >> 8) & 0xff);
1375 #else
1376   return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING);
1377 #endif
1378 }
1379 
1380 /* 'data' might be NULL */
1381 static CURLcode mbedtls_random(struct Curl_easy *data,
1382                                unsigned char *entropy, size_t length)
1383 {
1384 #if defined(MBEDTLS_CTR_DRBG_C)
1385   int ret;
1386   mbedtls_entropy_context ctr_entropy;
1387   mbedtls_ctr_drbg_context ctr_drbg;
1388   mbedtls_entropy_init(&ctr_entropy);
1389   mbedtls_ctr_drbg_init(&ctr_drbg);
1390   (void)data;
1391 
1392   ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
1393                               &ctr_entropy, NULL, 0);
1394 
1395   if(!ret)
1396     ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
1397 
1398   mbedtls_ctr_drbg_free(&ctr_drbg);
1399   mbedtls_entropy_free(&ctr_entropy);
1400 
1401   return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
1402 #elif defined(MBEDTLS_HAVEGE_C)
1403   mbedtls_havege_state hs;
1404   mbedtls_havege_init(&hs);
1405   mbedtls_havege_random(&hs, entropy, length);
1406   mbedtls_havege_free(&hs);
1407   return CURLE_OK;
1408 #else
1409   return CURLE_NOT_BUILT_IN;
1410 #endif
1411 }
1412 
1413 static CURLcode
1414 mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
1415                     bool nonblocking,
1416                     bool *done)
1417 {
1418   CURLcode retcode;
1419   struct ssl_connect_data *connssl = cf->ctx;
1420   curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
1421   timediff_t timeout_ms;
1422   int what;
1423 
1424   /* check if the connection has already been established */
1425   if(ssl_connection_complete == connssl->state) {
1426     *done = TRUE;
1427     return CURLE_OK;
1428   }
1429 
1430   if(ssl_connect_1 == connssl->connecting_state) {
1431     /* Find out how much more time we are allowed */
1432     timeout_ms = Curl_timeleft(data, NULL, TRUE);
1433 
1434     if(timeout_ms < 0) {
1435       /* no need to continue if time already is up */
1436       failf(data, "SSL connection timeout");
1437       return CURLE_OPERATION_TIMEDOUT;
1438     }
1439     retcode = mbed_connect_step1(cf, data);
1440     if(retcode)
1441       return retcode;
1442   }
1443 
1444   while(ssl_connect_2 == connssl->connecting_state) {
1445 
1446     /* check allowed time left */
1447     timeout_ms = Curl_timeleft(data, NULL, TRUE);
1448 
1449     if(timeout_ms < 0) {
1450       /* no need to continue if time already is up */
1451       failf(data, "SSL connection timeout");
1452       return CURLE_OPERATION_TIMEDOUT;
1453     }
1454 
1455     /* if ssl is expecting something, check if it is available. */
1456     if(connssl->io_need) {
1457       curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
1458         sockfd : CURL_SOCKET_BAD;
1459       curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
1460         sockfd : CURL_SOCKET_BAD;
1461 
1462       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
1463                                nonblocking ? 0 : timeout_ms);
1464       if(what < 0) {
1465         /* fatal error */
1466         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1467         return CURLE_SSL_CONNECT_ERROR;
1468       }
1469       else if(0 == what) {
1470         if(nonblocking) {
1471           *done = FALSE;
1472           return CURLE_OK;
1473         }
1474         else {
1475           /* timeout */
1476           failf(data, "SSL connection timeout");
1477           return CURLE_OPERATION_TIMEDOUT;
1478         }
1479       }
1480       /* socket is readable or writable */
1481     }
1482 
1483     /* Run transaction, and return to the caller if it failed or if
1484      * this connection is part of a multi handle and this loop would
1485      * execute again. This permits the owner of a multi handle to
1486      * abort a connection attempt before step2 has completed while
1487      * ensuring that a client using select() or epoll() will always
1488      * have a valid fdset to wait on.
1489      */
1490     connssl->io_need = CURL_SSL_IO_NEED_NONE;
1491     retcode = mbed_connect_step2(cf, data);
1492     if(retcode ||
1493        (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
1494       return retcode;
1495 
1496   } /* repeat step2 until all transactions are done. */
1497 
1498   if(ssl_connect_3 == connssl->connecting_state) {
1499     /* For tls1.3 we get notified about new sessions */
1500 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
1501     struct ssl_connect_data *ctx = cf->ctx;
1502     struct mbed_ssl_backend_data *backend =
1503       (struct mbed_ssl_backend_data *)ctx->backend;
1504 
1505     if(mbedtls_ssl_get_version_number(&backend->ssl) <=
1506        MBEDTLS_SSL_VERSION_TLS1_2) {
1507 #else
1508     {  /* no TLSv1.3 supported here */
1509 #endif
1510       retcode = mbed_new_session(cf, data);
1511       if(retcode)
1512         return retcode;
1513     }
1514     connssl->connecting_state = ssl_connect_done;
1515   }
1516 
1517   if(ssl_connect_done == connssl->connecting_state) {
1518     connssl->state = ssl_connection_complete;
1519     *done = TRUE;
1520   }
1521   else
1522     *done = FALSE;
1523 
1524   /* Reset our connect state machine */
1525   connssl->connecting_state = ssl_connect_1;
1526 
1527   return CURLE_OK;
1528 }
1529 
1530 static CURLcode mbedtls_connect_nonblocking(struct Curl_cfilter *cf,
1531                                             struct Curl_easy *data,
1532                                             bool *done)
1533 {
1534   return mbed_connect_common(cf, data, TRUE, done);
1535 }
1536 
1537 
1538 static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
1539                                 struct Curl_easy *data)
1540 {
1541   CURLcode retcode;
1542   bool done = FALSE;
1543 
1544   retcode = mbed_connect_common(cf, data, FALSE, &done);
1545   if(retcode)
1546     return retcode;
1547 
1548   DEBUGASSERT(done);
1549 
1550   return CURLE_OK;
1551 }
1552 
1553 /*
1554  * return 0 error initializing SSL
1555  * return 1 SSL initialized successfully
1556  */
1557 static int mbedtls_init(void)
1558 {
1559   if(!Curl_mbedtlsthreadlock_thread_setup())
1560     return 0;
1561 #ifdef THREADING_SUPPORT
1562   entropy_init_mutex(&ts_entropy);
1563 #endif
1564 #ifdef TLS13_SUPPORT
1565   {
1566     int ret;
1567 #ifdef THREADING_SUPPORT
1568     Curl_mbedtlsthreadlock_lock_function(0);
1569 #endif
1570     ret = psa_crypto_init();
1571 #ifdef THREADING_SUPPORT
1572     Curl_mbedtlsthreadlock_unlock_function(0);
1573 #endif
1574     if(ret != PSA_SUCCESS)
1575       return 0;
1576   }
1577 #endif /* TLS13_SUPPORT */
1578   return 1;
1579 }
1580 
1581 static void mbedtls_cleanup(void)
1582 {
1583 #ifdef THREADING_SUPPORT
1584   entropy_cleanup_mutex(&ts_entropy);
1585 #endif
1586   (void)Curl_mbedtlsthreadlock_thread_cleanup();
1587 }
1588 
1589 static bool mbedtls_data_pending(struct Curl_cfilter *cf,
1590                                  const struct Curl_easy *data)
1591 {
1592   struct ssl_connect_data *ctx = cf->ctx;
1593   struct mbed_ssl_backend_data *backend;
1594 
1595   (void)data;
1596   DEBUGASSERT(ctx && ctx->backend);
1597   backend = (struct mbed_ssl_backend_data *)ctx->backend;
1598   return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
1599 }
1600 
1601 static CURLcode mbedtls_sha256sum(const unsigned char *input,
1602                                   size_t inputlen,
1603                                   unsigned char *sha256sum,
1604                                   size_t sha256len UNUSED_PARAM)
1605 {
1606   /* TODO: explain this for different mbedtls 2.x vs 3 version */
1607   (void)sha256len;
1608 #if MBEDTLS_VERSION_NUMBER < 0x02070000
1609   mbedtls_sha256(input, inputlen, sha256sum, 0);
1610 #else
1611   /* returns 0 on success, otherwise failure */
1612 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
1613   if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0)
1614 #else
1615   if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
1616 #endif
1617     return CURLE_BAD_FUNCTION_ARGUMENT;
1618 #endif
1619   return CURLE_OK;
1620 }
1621 
1622 static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
1623                                    CURLINFO info UNUSED_PARAM)
1624 {
1625   struct mbed_ssl_backend_data *backend =
1626     (struct mbed_ssl_backend_data *)connssl->backend;
1627   (void)info;
1628   DEBUGASSERT(backend);
1629   return &backend->ssl;
1630 }
1631 
1632 const struct Curl_ssl Curl_ssl_mbedtls = {
1633   { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
1634 
1635   SSLSUPP_CA_PATH |
1636   SSLSUPP_CAINFO_BLOB |
1637   SSLSUPP_CERTINFO |
1638   SSLSUPP_PINNEDPUBKEY |
1639   SSLSUPP_SSL_CTX |
1640 #ifdef TLS13_SUPPORT
1641   SSLSUPP_TLS13_CIPHERSUITES |
1642 #endif
1643   SSLSUPP_HTTPS_PROXY |
1644   SSLSUPP_CIPHER_LIST,
1645 
1646   sizeof(struct mbed_ssl_backend_data),
1647 
1648   mbedtls_init,                     /* init */
1649   mbedtls_cleanup,                  /* cleanup */
1650   mbedtls_version,                  /* version */
1651   Curl_none_check_cxn,              /* check_cxn */
1652   mbedtls_shutdown,                 /* shutdown */
1653   mbedtls_data_pending,             /* data_pending */
1654   mbedtls_random,                   /* random */
1655   Curl_none_cert_status_request,    /* cert_status_request */
1656   mbedtls_connect,                  /* connect */
1657   mbedtls_connect_nonblocking,      /* connect_nonblocking */
1658   Curl_ssl_adjust_pollset,          /* adjust_pollset */
1659   mbedtls_get_internals,            /* get_internals */
1660   mbedtls_close,                    /* close_one */
1661   mbedtls_close_all,                /* close_all */
1662   Curl_none_set_engine,             /* set_engine */
1663   Curl_none_set_engine_default,     /* set_engine_default */
1664   Curl_none_engines_list,           /* engines_list */
1665   Curl_none_false_start,            /* false_start */
1666   mbedtls_sha256sum,                /* sha256sum */
1667   NULL,                             /* associate_connection */
1668   NULL,                             /* disassociate_connection */
1669   mbed_recv,                        /* recv decrypted data */
1670   mbed_send,                        /* send data to encrypt */
1671   NULL,                             /* get_channel_binding */
1672 };
1673 
1674 #endif /* USE_MBEDTLS */
1675