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