xref: /curl/lib/vtls/mbedtls.c (revision e1ed6b8e)
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
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 #if defined(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 TLS13_SUPPORT
589   ret = psa_crypto_init();
590   if(ret != PSA_SUCCESS) {
591     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
592     failf(data, "mbedTLS psa_crypto_init returned (-0x%04X) %s",
593           -ret, errorbuf);
594     return CURLE_SSL_CONNECT_ERROR;
595   }
596 #endif /* TLS13_SUPPORT */
597 
598 #ifdef THREADING_SUPPORT
599   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
600 
601   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
602                               &ts_entropy, NULL, 0);
603   if(ret) {
604     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
605     failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
606           -ret, errorbuf);
607     return CURLE_FAILED_INIT;
608   }
609 #else
610   mbedtls_entropy_init(&backend->entropy);
611   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
612 
613   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func,
614                               &backend->entropy, NULL, 0);
615   if(ret) {
616     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
617     failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
618           -ret, errorbuf);
619     return CURLE_FAILED_INIT;
620   }
621 #endif /* THREADING_SUPPORT */
622 
623   /* Load the trusted CA */
624   mbedtls_x509_crt_init(&backend->cacert);
625 
626   if(ca_info_blob && verifypeer) {
627     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
628        terminated even when provided the exact length, forcing us to waste
629        extra memory here. */
630     unsigned char *newblob = Curl_memdup0(ca_info_blob->data,
631                                           ca_info_blob->len);
632     if(!newblob)
633       return CURLE_OUT_OF_MEMORY;
634     ret = mbedtls_x509_crt_parse(&backend->cacert, newblob,
635                                  ca_info_blob->len + 1);
636     free(newblob);
637     if(ret < 0) {
638       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
639       failf(data, "Error importing ca cert blob - mbedTLS: (-0x%04X) %s",
640             -ret, errorbuf);
641       return CURLE_SSL_CERTPROBLEM;
642     }
643   }
644 
645   if(ssl_cafile && verifypeer) {
646 #ifdef MBEDTLS_FS_IO
647     ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile);
648 
649     if(ret < 0) {
650       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
651       failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
652             ssl_cafile, -ret, errorbuf);
653       return CURLE_SSL_CACERT_BADFILE;
654     }
655 #else
656     failf(data, "mbedtls: functions that use the filesystem not built in");
657     return CURLE_NOT_BUILT_IN;
658 #endif
659   }
660 
661   if(ssl_capath) {
662 #ifdef MBEDTLS_FS_IO
663     ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath);
664 
665     if(ret < 0) {
666       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
667       failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
668             ssl_capath, -ret, errorbuf);
669 
670       if(verifypeer)
671         return CURLE_SSL_CACERT_BADFILE;
672     }
673 #else
674     failf(data, "mbedtls: functions that use the filesystem not built in");
675     return CURLE_NOT_BUILT_IN;
676 #endif
677   }
678 
679   /* Load the client certificate */
680   mbedtls_x509_crt_init(&backend->clicert);
681 
682   if(ssl_cert) {
683 #ifdef MBEDTLS_FS_IO
684     ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert);
685 
686     if(ret) {
687       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
688       failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
689             ssl_cert, -ret, errorbuf);
690 
691       return CURLE_SSL_CERTPROBLEM;
692     }
693 #else
694     failf(data, "mbedtls: functions that use the filesystem not built in");
695     return CURLE_NOT_BUILT_IN;
696 #endif
697   }
698 
699   if(ssl_cert_blob) {
700     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
701        terminated even when provided the exact length, forcing us to waste
702        extra memory here. */
703     unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data,
704                                           ssl_cert_blob->len);
705     if(!newblob)
706       return CURLE_OUT_OF_MEMORY;
707     ret = mbedtls_x509_crt_parse(&backend->clicert, newblob,
708                                  ssl_cert_blob->len + 1);
709     free(newblob);
710 
711     if(ret) {
712       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
713       failf(data, "Error reading client cert data %s - mbedTLS: (-0x%04X) %s",
714             ssl_config->key, -ret, errorbuf);
715       return CURLE_SSL_CERTPROBLEM;
716     }
717   }
718 
719   /* Load the client private key */
720   mbedtls_pk_init(&backend->pk);
721 
722   if(ssl_config->key || ssl_config->key_blob) {
723     if(ssl_config->key) {
724 #ifdef MBEDTLS_FS_IO
725 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
726       ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
727                                      ssl_config->key_passwd,
728                                      mbedtls_ctr_drbg_random,
729                                      &backend->ctr_drbg);
730 #else
731       ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
732                                      ssl_config->key_passwd);
733 #endif
734 
735       if(ret) {
736         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
737         failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
738               ssl_config->key, -ret, errorbuf);
739         return CURLE_SSL_CERTPROBLEM;
740       }
741 #else
742       failf(data, "mbedtls: functions that use the filesystem not built in");
743       return CURLE_NOT_BUILT_IN;
744 #endif
745     }
746     else {
747       const struct curl_blob *ssl_key_blob = ssl_config->key_blob;
748       const unsigned char *key_data =
749         (const unsigned char *)ssl_key_blob->data;
750       const char *passwd = ssl_config->key_passwd;
751 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
752       ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
753                                  (const unsigned char *)passwd,
754                                  passwd ? strlen(passwd) : 0,
755                                  mbedtls_ctr_drbg_random,
756                                  &backend->ctr_drbg);
757 #else
758       ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
759                                  (const unsigned char *)passwd,
760                                  passwd ? strlen(passwd) : 0);
761 #endif
762 
763       if(ret) {
764         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
765         failf(data, "Error parsing private key - mbedTLS: (-0x%04X) %s",
766               -ret, errorbuf);
767         return CURLE_SSL_CERTPROBLEM;
768       }
769     }
770 
771     if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
772                      mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
773       ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
774   }
775 
776   /* Load the CRL */
777 #ifdef MBEDTLS_X509_CRL_PARSE_C
778   mbedtls_x509_crl_init(&backend->crl);
779 
780   if(ssl_crlfile) {
781 #ifdef MBEDTLS_FS_IO
782     ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile);
783 
784     if(ret) {
785       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
786       failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
787             ssl_crlfile, -ret, errorbuf);
788 
789       return CURLE_SSL_CRL_BADFILE;
790     }
791 #else
792     failf(data, "mbedtls: functions that use the filesystem not built in");
793     return CURLE_NOT_BUILT_IN;
794 #endif
795   }
796 #else
797   if(ssl_crlfile) {
798     failf(data, "mbedtls: crl support not built in");
799     return CURLE_NOT_BUILT_IN;
800   }
801 #endif
802 
803   infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->peer.port);
804 
805   mbedtls_ssl_config_init(&backend->config);
806   ret = mbedtls_ssl_config_defaults(&backend->config,
807                                     MBEDTLS_SSL_IS_CLIENT,
808                                     MBEDTLS_SSL_TRANSPORT_STREAM,
809                                     MBEDTLS_SSL_PRESET_DEFAULT);
810   if(ret) {
811     failf(data, "mbedTLS: ssl_config failed");
812     return CURLE_SSL_CONNECT_ERROR;
813   }
814 
815 #ifdef MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED
816   /* New in mbedTLS 3.6.1, need to enable, default is now disabled */
817   mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(&backend->config,
818     MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED);
819 #endif
820 
821   /* Always let mbedTLS verify certificates, if verifypeer or verifyhost are
822    * disabled we clear the corresponding error flags in the verify callback
823    * function. That is also where we log verification errors. */
824   mbedtls_ssl_conf_verify(&backend->config, mbed_verify_cb, cf);
825   mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_REQUIRED);
826 
827   mbedtls_ssl_init(&backend->ssl);
828   backend->initialized = TRUE;
829 
830   /* new profile with RSA min key len = 1024 ... */
831   mbedtls_ssl_conf_cert_profile(&backend->config,
832                                 &mbedtls_x509_crt_profile_fr);
833 
834   ret = mbed_set_ssl_version_min_max(data, backend, conn_config);
835   if(ret != CURLE_OK)
836     return ret;
837 
838   mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
839                        &backend->ctr_drbg);
840 
841   ret = mbedtls_ssl_setup(&backend->ssl, &backend->config);
842   if(ret) {
843     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
844     failf(data, "ssl_setup failed - mbedTLS: (-0x%04X) %s",
845           -ret, errorbuf);
846     return CURLE_SSL_CONNECT_ERROR;
847   }
848 
849   mbedtls_ssl_set_bio(&backend->ssl, cf,
850                       mbedtls_bio_cf_write,
851                       mbedtls_bio_cf_read,
852                       NULL /*  rev_timeout() */);
853 
854 #ifndef TLS13_SUPPORT
855   if(conn_config->cipher_list) {
856     CURLcode result = mbed_set_selected_ciphers(data, backend,
857                                                 conn_config->cipher_list,
858                                                 NULL);
859 #else
860   if(conn_config->cipher_list || conn_config->cipher_list13) {
861     CURLcode result = mbed_set_selected_ciphers(data, backend,
862                                                 conn_config->cipher_list,
863                                                 conn_config->cipher_list13);
864 #endif
865     if(result != CURLE_OK) {
866       failf(data, "mbedTLS: failed to set cipher suites");
867       return result;
868     }
869   }
870   else {
871     mbedtls_ssl_conf_ciphersuites(&backend->config,
872                                   mbedtls_ssl_list_ciphersuites());
873   }
874 
875 
876 #if defined(MBEDTLS_SSL_RENEGOTIATION)
877   mbedtls_ssl_conf_renegotiation(&backend->config,
878                                  MBEDTLS_SSL_RENEGOTIATION_ENABLED);
879 #endif
880 
881 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
882   mbedtls_ssl_conf_session_tickets(&backend->config,
883                                    MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
884 #endif
885 
886   /* Check if there is a cached ID we can/should use here! */
887   if(ssl_config->primary.cache_session) {
888     void *sdata = NULL;
889     size_t slen = 0;
890 
891     Curl_ssl_sessionid_lock(data);
892     if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
893                               &sdata, &slen, NULL) && slen) {
894       mbedtls_ssl_session session;
895 
896       mbedtls_ssl_session_init(&session);
897       ret = mbedtls_ssl_session_load(&session, sdata, slen);
898       if(ret) {
899         failf(data, "error loading cached session: -0x%x", -ret);
900       }
901       else {
902         ret = mbedtls_ssl_set_session(&backend->ssl, &session);
903         if(ret)
904           failf(data, "error setting session: -0x%x", -ret);
905         else
906           infof(data, "SSL reusing session ID");
907       }
908       mbedtls_ssl_session_free(&session);
909     }
910     Curl_ssl_sessionid_unlock(data);
911   }
912 
913   mbedtls_ssl_conf_ca_chain(&backend->config,
914                             &backend->cacert,
915 #ifdef MBEDTLS_X509_CRL_PARSE_C
916                             &backend->crl);
917 #else
918                             NULL);
919 #endif
920 
921   if(ssl_config->key || ssl_config->key_blob) {
922     mbedtls_ssl_conf_own_cert(&backend->config,
923                               &backend->clicert, &backend->pk);
924   }
925 
926   if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni ?
927                               connssl->peer.sni : connssl->peer.hostname)) {
928     /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and
929        the name to set in the SNI extension. So even if curl connects to a
930        host specified as an IP address, this function must be used. */
931     failf(data, "Failed to set SNI");
932     return CURLE_SSL_CONNECT_ERROR;
933   }
934 
935 #ifdef HAS_ALPN
936   if(connssl->alpn) {
937     struct alpn_proto_buf proto;
938     size_t i;
939 
940     for(i = 0; i < connssl->alpn->count; ++i) {
941       backend->protocols[i] = connssl->alpn->entries[i];
942     }
943     /* this function does not clone the protocols array, which is why we need
944        to keep it around */
945     if(mbedtls_ssl_conf_alpn_protocols(&backend->config,
946                                        &backend->protocols[0])) {
947       failf(data, "Failed setting ALPN protocols");
948       return CURLE_SSL_CONNECT_ERROR;
949     }
950     Curl_alpn_to_proto_str(&proto, connssl->alpn);
951     infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
952   }
953 #endif
954 
955 #ifdef MBEDTLS_DEBUG
956   /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
957   mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data);
958   /* - 0 No debug
959    * - 1 Error
960    * - 2 State change
961    * - 3 Informational
962    * - 4 Verbose
963    */
964   mbedtls_debug_set_threshold(4);
965 #endif
966 
967   /* give application a chance to interfere with mbedTLS set up. */
968   if(data->set.ssl.fsslctx) {
969     CURLcode result = (*data->set.ssl.fsslctx)(data, &backend->config,
970                                                data->set.ssl.fsslctxp);
971     if(result != CURLE_OK) {
972       failf(data, "error signaled by ssl ctx callback");
973       return result;
974     }
975   }
976 
977   connssl->connecting_state = ssl_connect_2;
978 
979   return CURLE_OK;
980 }
981 
982 static CURLcode
983 mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
984 {
985   int ret;
986   struct ssl_connect_data *connssl = cf->ctx;
987   struct mbed_ssl_backend_data *backend =
988     (struct mbed_ssl_backend_data *)connssl->backend;
989 #ifndef CURL_DISABLE_PROXY
990   const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
991     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
992     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
993 #else
994   const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
995 #endif
996 
997   DEBUGASSERT(backend);
998 
999   ret = mbedtls_ssl_handshake(&backend->ssl);
1000 
1001   if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
1002     connssl->io_need = CURL_SSL_IO_NEED_RECV;
1003     return CURLE_OK;
1004   }
1005   else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
1006     connssl->io_need = CURL_SSL_IO_NEED_SEND;
1007     return CURLE_OK;
1008   }
1009   else if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
1010     failf(data, "peer certificate could not be verified");
1011     return CURLE_PEER_FAILED_VERIFICATION;
1012   }
1013   else if(ret) {
1014     char errorbuf[128];
1015 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
1016     CURL_TRC_CF(data, cf, "TLS version %04X",
1017                 mbedtls_ssl_get_version_number(&backend->ssl));
1018 #endif
1019     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
1020     failf(data, "ssl_handshake returned: (-0x%04X) %s",
1021           -ret, errorbuf);
1022     return CURLE_SSL_CONNECT_ERROR;
1023   }
1024 
1025 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
1026   {
1027     char cipher_str[64];
1028     uint16_t cipher_id;
1029     cipher_id = (uint16_t)
1030                 mbedtls_ssl_get_ciphersuite_id_from_ssl(&backend->ssl);
1031     mbed_cipher_suite_get_str(cipher_id, cipher_str, sizeof(cipher_str), TRUE);
1032     infof(data, "mbedTLS: %s Handshake complete, cipher is %s",
1033           mbedtls_ssl_get_version(&backend->ssl), cipher_str);
1034   }
1035 #else
1036   infof(data, "mbedTLS: %s Handshake complete",
1037         mbedtls_ssl_get_version(&backend->ssl));
1038 #endif
1039 
1040   if(pinnedpubkey) {
1041     int size;
1042     CURLcode result;
1043     const mbedtls_x509_crt *peercert;
1044     mbedtls_x509_crt *p = NULL;
1045     unsigned char *pubkey = NULL;
1046 
1047     peercert = mbedtls_ssl_get_peer_cert(&backend->ssl);
1048 #if MBEDTLS_VERSION_NUMBER == 0x03000000
1049     if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) ||
1050        !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) {
1051 #else
1052     if(!peercert || !peercert->raw.p || !peercert->raw.len) {
1053 #endif
1054       failf(data, "Failed due to missing peer certificate");
1055       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1056     }
1057 
1058     p = calloc(1, sizeof(*p));
1059 
1060     if(!p)
1061       return CURLE_OUT_OF_MEMORY;
1062 
1063     pubkey = malloc(PUB_DER_MAX_BYTES);
1064 
1065     if(!pubkey) {
1066       result = CURLE_OUT_OF_MEMORY;
1067       goto pinnedpubkey_error;
1068     }
1069 
1070     mbedtls_x509_crt_init(p);
1071 
1072     /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
1073        needs a non-const key, for now.
1074        https://github.com/Mbed-TLS/mbedtls/issues/396 */
1075 #if MBEDTLS_VERSION_NUMBER == 0x03000000
1076     if(mbedtls_x509_crt_parse_der(p,
1077                         peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
1078                         peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) {
1079 #else
1080     if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
1081 #endif
1082       failf(data, "Failed copying peer certificate");
1083       result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1084       goto pinnedpubkey_error;
1085     }
1086 
1087 #if MBEDTLS_VERSION_NUMBER == 0x03000000
1088     size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey,
1089                                        PUB_DER_MAX_BYTES);
1090 #else
1091     size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
1092 #endif
1093 
1094     if(size <= 0) {
1095       failf(data, "Failed copying public key from peer certificate");
1096       result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1097       goto pinnedpubkey_error;
1098     }
1099 
1100     /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
1101     result = Curl_pin_peer_pubkey(data,
1102                                   pinnedpubkey,
1103                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
1104 pinnedpubkey_error:
1105     mbedtls_x509_crt_free(p);
1106     free(p);
1107     free(pubkey);
1108     if(result) {
1109       return result;
1110     }
1111   }
1112 
1113 #ifdef HAS_ALPN
1114   if(connssl->alpn) {
1115     const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
1116 
1117     Curl_alpn_set_negotiated(cf, data, connssl, (const unsigned char *)proto,
1118                              proto ? strlen(proto) : 0);
1119   }
1120 #endif
1121 
1122   connssl->connecting_state = ssl_connect_3;
1123   infof(data, "SSL connected");
1124 
1125   return CURLE_OK;
1126 }
1127 
1128 static void mbedtls_session_free(void *session, size_t slen)
1129 {
1130   (void)slen;
1131   free(session);
1132 }
1133 
1134 static CURLcode
1135 mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data)
1136 {
1137   struct ssl_connect_data *connssl = cf->ctx;
1138   struct mbed_ssl_backend_data *backend =
1139     (struct mbed_ssl_backend_data *)connssl->backend;
1140   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1141   CURLcode result = CURLE_OK;
1142 
1143   DEBUGASSERT(backend);
1144   if(ssl_config->primary.cache_session) {
1145     int ret;
1146     mbedtls_ssl_session session;
1147     unsigned char *sdata = NULL;
1148     size_t slen = 0;
1149 
1150     mbedtls_ssl_session_init(&session);
1151     ret = mbedtls_ssl_get_session(&backend->ssl, &session);
1152     if(ret) {
1153       if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED)
1154         mbedtls_ssl_session_free(&session);
1155       failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
1156       return CURLE_SSL_CONNECT_ERROR;
1157     }
1158 
1159     mbedtls_ssl_session_save(&session, NULL, 0, &slen);
1160     if(!slen) {
1161       failf(data, "failed to serialize session: length is 0");
1162     }
1163     else {
1164       sdata = malloc(slen);
1165       if(sdata) {
1166         ret = mbedtls_ssl_session_save(&session, sdata, slen, &slen);
1167         if(ret) {
1168           failf(data, "failed to serialize session: -0x%x", -ret);
1169         }
1170         else {
1171           Curl_ssl_sessionid_lock(data);
1172           result = Curl_ssl_set_sessionid(cf, data, &connssl->peer, NULL,
1173                                           sdata, slen, mbedtls_session_free);
1174           Curl_ssl_sessionid_unlock(data);
1175           if(!result)
1176             sdata = NULL;
1177         }
1178       }
1179     }
1180     mbedtls_ssl_session_free(&session);
1181     free(sdata);
1182   }
1183   return result;
1184 }
1185 
1186 static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
1187                          const void *mem, size_t len,
1188                          CURLcode *curlcode)
1189 {
1190   struct ssl_connect_data *connssl = cf->ctx;
1191   struct mbed_ssl_backend_data *backend =
1192     (struct mbed_ssl_backend_data *)connssl->backend;
1193   int ret = -1;
1194 
1195   (void)data;
1196   DEBUGASSERT(backend);
1197   ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
1198 
1199   if(ret < 0) {
1200     CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X",
1201                 len, -ret);
1202     *curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_WRITE)
1203 #ifdef TLS13_SUPPORT
1204       || (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
1205 #endif
1206       ) ? CURLE_AGAIN : CURLE_SEND_ERROR;
1207     ret = -1;
1208   }
1209 
1210   return ret;
1211 }
1212 
1213 static void mbedtls_close_all(struct Curl_easy *data)
1214 {
1215   (void)data;
1216 }
1217 
1218 static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf,
1219                                  struct Curl_easy *data,
1220                                  bool send_shutdown, bool *done)
1221 {
1222   struct ssl_connect_data *connssl = cf->ctx;
1223   struct mbed_ssl_backend_data *backend =
1224     (struct mbed_ssl_backend_data *)connssl->backend;
1225   unsigned char buf[1024];
1226   CURLcode result = CURLE_OK;
1227   int ret;
1228   size_t i;
1229 
1230   DEBUGASSERT(backend);
1231 
1232   if(!backend->initialized || cf->shutdown) {
1233     *done = TRUE;
1234     return CURLE_OK;
1235   }
1236 
1237   connssl->io_need = CURL_SSL_IO_NEED_NONE;
1238   *done = FALSE;
1239 
1240   if(!backend->sent_shutdown) {
1241     /* do this only once */
1242     backend->sent_shutdown = TRUE;
1243     if(send_shutdown) {
1244       ret = mbedtls_ssl_close_notify(&backend->ssl);
1245       switch(ret) {
1246       case 0: /* we sent it, receive from the server */
1247         break;
1248       case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: /* server also closed */
1249         *done = TRUE;
1250         goto out;
1251       case MBEDTLS_ERR_SSL_WANT_READ:
1252         connssl->io_need = CURL_SSL_IO_NEED_RECV;
1253         goto out;
1254       case MBEDTLS_ERR_SSL_WANT_WRITE:
1255         connssl->io_need = CURL_SSL_IO_NEED_SEND;
1256         goto out;
1257       default:
1258         CURL_TRC_CF(data, cf, "mbedtls_shutdown error -0x%04X", -ret);
1259         result = CURLE_RECV_ERROR;
1260         goto out;
1261       }
1262     }
1263   }
1264 
1265   /* SSL should now have started the shutdown from our side. Since it
1266    * was not complete, we are lacking the close notify from the server. */
1267   for(i = 0; i < 10; ++i) {
1268     ret = mbedtls_ssl_read(&backend->ssl, buf, sizeof(buf));
1269     /* This seems to be a bug in mbedTLS TLSv1.3 where it reports
1270      * WANT_READ, but has not encountered an EAGAIN. */
1271     if(ret == MBEDTLS_ERR_SSL_WANT_READ)
1272       ret = mbedtls_ssl_read(&backend->ssl, buf, sizeof(buf));
1273 #ifdef TLS13_SUPPORT
1274     if(ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
1275       continue;
1276 #endif
1277     if(ret <= 0)
1278       break;
1279   }
1280 
1281   if(ret > 0) {
1282     /* still data coming in? */
1283     CURL_TRC_CF(data, cf, "mbedtls_shutdown, still getting data");
1284   }
1285   else if(ret == 0 || (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)) {
1286     /* We got the close notify alert and are done. */
1287     CURL_TRC_CF(data, cf, "mbedtls_shutdown done");
1288     *done = TRUE;
1289   }
1290   else if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
1291     CURL_TRC_CF(data, cf, "mbedtls_shutdown, need RECV");
1292     connssl->io_need = CURL_SSL_IO_NEED_RECV;
1293   }
1294   else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
1295     CURL_TRC_CF(data, cf, "mbedtls_shutdown, need SEND");
1296     connssl->io_need = CURL_SSL_IO_NEED_SEND;
1297   }
1298   else {
1299     CURL_TRC_CF(data, cf, "mbedtls_shutdown error -0x%04X", -ret);
1300     result = CURLE_RECV_ERROR;
1301   }
1302 
1303 out:
1304   cf->shutdown = (result || *done);
1305   return result;
1306 }
1307 
1308 static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1309 {
1310   struct ssl_connect_data *connssl = cf->ctx;
1311   struct mbed_ssl_backend_data *backend =
1312     (struct mbed_ssl_backend_data *)connssl->backend;
1313 
1314   (void)data;
1315   DEBUGASSERT(backend);
1316   if(backend->initialized) {
1317     mbedtls_pk_free(&backend->pk);
1318     mbedtls_x509_crt_free(&backend->clicert);
1319     mbedtls_x509_crt_free(&backend->cacert);
1320 #ifdef MBEDTLS_X509_CRL_PARSE_C
1321     mbedtls_x509_crl_free(&backend->crl);
1322 #endif
1323     Curl_safefree(backend->ciphersuites);
1324     mbedtls_ssl_config_free(&backend->config);
1325     mbedtls_ssl_free(&backend->ssl);
1326     mbedtls_ctr_drbg_free(&backend->ctr_drbg);
1327 #ifndef THREADING_SUPPORT
1328     mbedtls_entropy_free(&backend->entropy);
1329 #endif /* THREADING_SUPPORT */
1330     backend->initialized = FALSE;
1331   }
1332 }
1333 
1334 static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
1335                          char *buf, size_t buffersize,
1336                          CURLcode *curlcode)
1337 {
1338   struct ssl_connect_data *connssl = cf->ctx;
1339   struct mbed_ssl_backend_data *backend =
1340     (struct mbed_ssl_backend_data *)connssl->backend;
1341   int ret = -1;
1342 
1343   (void)data;
1344   DEBUGASSERT(backend);
1345 
1346   ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
1347                          buffersize);
1348   if(ret <= 0) {
1349     CURL_TRC_CF(data, cf, "mbedtls_ssl_read(len=%zu) -> -0x%04X",
1350                 buffersize, -ret);
1351     switch(ret) {
1352 #ifdef HAS_SESSION_TICKETS
1353     case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET:
1354       mbed_new_session(cf, data);
1355       FALLTHROUGH();
1356 #endif
1357     case MBEDTLS_ERR_SSL_WANT_READ:
1358       *curlcode = CURLE_AGAIN;
1359       ret = -1;
1360       break;
1361     case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1362       *curlcode = CURLE_OK;
1363       ret = 0;
1364       break;
1365     default: {
1366       char errorbuf[128];
1367       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
1368       failf(data, "ssl_read returned: (-0x%04X) %s", -ret, errorbuf);
1369       *curlcode = CURLE_RECV_ERROR;
1370       ret = -1;
1371       break;
1372     }
1373     }
1374   }
1375   return (ssize_t)ret;
1376 }
1377 
1378 static size_t mbedtls_version(char *buffer, size_t size)
1379 {
1380 #ifdef MBEDTLS_VERSION_C
1381   /* if mbedtls_version_get_number() is available it is better */
1382   unsigned int version = mbedtls_version_get_number();
1383   return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version >> 24,
1384                    (version >> 16) & 0xff, (version >> 8) & 0xff);
1385 #else
1386   return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING);
1387 #endif
1388 }
1389 
1390 /* 'data' might be NULL */
1391 static CURLcode mbedtls_random(struct Curl_easy *data,
1392                                unsigned char *entropy, size_t length)
1393 {
1394 #if defined(MBEDTLS_CTR_DRBG_C)
1395   int ret;
1396   mbedtls_entropy_context ctr_entropy;
1397   mbedtls_ctr_drbg_context ctr_drbg;
1398   mbedtls_entropy_init(&ctr_entropy);
1399   mbedtls_ctr_drbg_init(&ctr_drbg);
1400   (void)data;
1401 
1402   ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
1403                               &ctr_entropy, NULL, 0);
1404 
1405   if(!ret)
1406     ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
1407 
1408   mbedtls_ctr_drbg_free(&ctr_drbg);
1409   mbedtls_entropy_free(&ctr_entropy);
1410 
1411   return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
1412 #elif defined(MBEDTLS_HAVEGE_C)
1413   mbedtls_havege_state hs;
1414   mbedtls_havege_init(&hs);
1415   mbedtls_havege_random(&hs, entropy, length);
1416   mbedtls_havege_free(&hs);
1417   return CURLE_OK;
1418 #else
1419   return CURLE_NOT_BUILT_IN;
1420 #endif
1421 }
1422 
1423 static CURLcode
1424 mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
1425                     bool nonblocking,
1426                     bool *done)
1427 {
1428   CURLcode retcode;
1429   struct ssl_connect_data *connssl = cf->ctx;
1430   curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
1431   timediff_t timeout_ms;
1432   int what;
1433 
1434   /* check if the connection has already been established */
1435   if(ssl_connection_complete == connssl->state) {
1436     *done = TRUE;
1437     return CURLE_OK;
1438   }
1439 
1440   if(ssl_connect_1 == connssl->connecting_state) {
1441     /* Find out how much more time we are allowed */
1442     timeout_ms = Curl_timeleft(data, NULL, TRUE);
1443 
1444     if(timeout_ms < 0) {
1445       /* no need to continue if time already is up */
1446       failf(data, "SSL connection timeout");
1447       return CURLE_OPERATION_TIMEDOUT;
1448     }
1449     retcode = mbed_connect_step1(cf, data);
1450     if(retcode)
1451       return retcode;
1452   }
1453 
1454   while(ssl_connect_2 == connssl->connecting_state) {
1455 
1456     /* check allowed time left */
1457     timeout_ms = Curl_timeleft(data, NULL, TRUE);
1458 
1459     if(timeout_ms < 0) {
1460       /* no need to continue if time already is up */
1461       failf(data, "SSL connection timeout");
1462       return CURLE_OPERATION_TIMEDOUT;
1463     }
1464 
1465     /* if ssl is expecting something, check if it is available. */
1466     if(connssl->io_need) {
1467       curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
1468         sockfd : CURL_SOCKET_BAD;
1469       curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
1470         sockfd : CURL_SOCKET_BAD;
1471 
1472       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
1473                                nonblocking ? 0 : timeout_ms);
1474       if(what < 0) {
1475         /* fatal error */
1476         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1477         return CURLE_SSL_CONNECT_ERROR;
1478       }
1479       else if(0 == what) {
1480         if(nonblocking) {
1481           *done = FALSE;
1482           return CURLE_OK;
1483         }
1484         else {
1485           /* timeout */
1486           failf(data, "SSL connection timeout");
1487           return CURLE_OPERATION_TIMEDOUT;
1488         }
1489       }
1490       /* socket is readable or writable */
1491     }
1492 
1493     /* Run transaction, and return to the caller if it failed or if
1494      * this connection is part of a multi handle and this loop would
1495      * execute again. This permits the owner of a multi handle to
1496      * abort a connection attempt before step2 has completed while
1497      * ensuring that a client using select() or epoll() will always
1498      * have a valid fdset to wait on.
1499      */
1500     connssl->io_need = CURL_SSL_IO_NEED_NONE;
1501     retcode = mbed_connect_step2(cf, data);
1502     if(retcode ||
1503        (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
1504       return retcode;
1505 
1506   } /* repeat step2 until all transactions are done. */
1507 
1508   if(ssl_connect_3 == connssl->connecting_state) {
1509     /* For tls1.3 we get notified about new sessions */
1510 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
1511     struct ssl_connect_data *ctx = cf->ctx;
1512     struct mbed_ssl_backend_data *backend =
1513       (struct mbed_ssl_backend_data *)ctx->backend;
1514 
1515     if(mbedtls_ssl_get_version_number(&backend->ssl) <=
1516        MBEDTLS_SSL_VERSION_TLS1_2) {
1517 #else
1518     {  /* no TLSv1.3 supported here */
1519 #endif
1520       retcode = mbed_new_session(cf, data);
1521       if(retcode)
1522         return retcode;
1523     }
1524     connssl->connecting_state = ssl_connect_done;
1525   }
1526 
1527   if(ssl_connect_done == connssl->connecting_state) {
1528     connssl->state = ssl_connection_complete;
1529     *done = TRUE;
1530   }
1531   else
1532     *done = FALSE;
1533 
1534   /* Reset our connect state machine */
1535   connssl->connecting_state = ssl_connect_1;
1536 
1537   return CURLE_OK;
1538 }
1539 
1540 static CURLcode mbedtls_connect_nonblocking(struct Curl_cfilter *cf,
1541                                             struct Curl_easy *data,
1542                                             bool *done)
1543 {
1544   return mbed_connect_common(cf, data, TRUE, done);
1545 }
1546 
1547 
1548 static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
1549                                 struct Curl_easy *data)
1550 {
1551   CURLcode retcode;
1552   bool done = FALSE;
1553 
1554   retcode = mbed_connect_common(cf, data, FALSE, &done);
1555   if(retcode)
1556     return retcode;
1557 
1558   DEBUGASSERT(done);
1559 
1560   return CURLE_OK;
1561 }
1562 
1563 /*
1564  * return 0 error initializing SSL
1565  * return 1 SSL initialized successfully
1566  */
1567 static int mbedtls_init(void)
1568 {
1569   if(!Curl_mbedtlsthreadlock_thread_setup())
1570     return 0;
1571 #ifdef THREADING_SUPPORT
1572   entropy_init_mutex(&ts_entropy);
1573 #endif
1574   return 1;
1575 }
1576 
1577 static void mbedtls_cleanup(void)
1578 {
1579 #ifdef THREADING_SUPPORT
1580   entropy_cleanup_mutex(&ts_entropy);
1581 #endif
1582   (void)Curl_mbedtlsthreadlock_thread_cleanup();
1583 }
1584 
1585 static bool mbedtls_data_pending(struct Curl_cfilter *cf,
1586                                  const struct Curl_easy *data)
1587 {
1588   struct ssl_connect_data *ctx = cf->ctx;
1589   struct mbed_ssl_backend_data *backend;
1590 
1591   (void)data;
1592   DEBUGASSERT(ctx && ctx->backend);
1593   backend = (struct mbed_ssl_backend_data *)ctx->backend;
1594   return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
1595 }
1596 
1597 static CURLcode mbedtls_sha256sum(const unsigned char *input,
1598                                   size_t inputlen,
1599                                   unsigned char *sha256sum,
1600                                   size_t sha256len UNUSED_PARAM)
1601 {
1602   /* TODO: explain this for different mbedtls 2.x vs 3 version */
1603   (void)sha256len;
1604 #if MBEDTLS_VERSION_NUMBER < 0x02070000
1605   mbedtls_sha256(input, inputlen, sha256sum, 0);
1606 #else
1607   /* returns 0 on success, otherwise failure */
1608 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
1609   if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0)
1610 #else
1611   if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
1612 #endif
1613     return CURLE_BAD_FUNCTION_ARGUMENT;
1614 #endif
1615   return CURLE_OK;
1616 }
1617 
1618 static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
1619                                    CURLINFO info UNUSED_PARAM)
1620 {
1621   struct mbed_ssl_backend_data *backend =
1622     (struct mbed_ssl_backend_data *)connssl->backend;
1623   (void)info;
1624   DEBUGASSERT(backend);
1625   return &backend->ssl;
1626 }
1627 
1628 const struct Curl_ssl Curl_ssl_mbedtls = {
1629   { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
1630 
1631   SSLSUPP_CA_PATH |
1632   SSLSUPP_CAINFO_BLOB |
1633   SSLSUPP_CERTINFO |
1634   SSLSUPP_PINNEDPUBKEY |
1635   SSLSUPP_SSL_CTX |
1636 #ifdef TLS13_SUPPORT
1637   SSLSUPP_TLS13_CIPHERSUITES |
1638 #endif
1639   SSLSUPP_HTTPS_PROXY |
1640   SSLSUPP_CIPHER_LIST,
1641 
1642   sizeof(struct mbed_ssl_backend_data),
1643 
1644   mbedtls_init,                     /* init */
1645   mbedtls_cleanup,                  /* cleanup */
1646   mbedtls_version,                  /* version */
1647   Curl_none_check_cxn,              /* check_cxn */
1648   mbedtls_shutdown,                 /* shutdown */
1649   mbedtls_data_pending,             /* data_pending */
1650   mbedtls_random,                   /* random */
1651   Curl_none_cert_status_request,    /* cert_status_request */
1652   mbedtls_connect,                  /* connect */
1653   mbedtls_connect_nonblocking,      /* connect_nonblocking */
1654   Curl_ssl_adjust_pollset,          /* adjust_pollset */
1655   mbedtls_get_internals,            /* get_internals */
1656   mbedtls_close,                    /* close_one */
1657   mbedtls_close_all,                /* close_all */
1658   Curl_none_set_engine,             /* set_engine */
1659   Curl_none_set_engine_default,     /* set_engine_default */
1660   Curl_none_engines_list,           /* engines_list */
1661   Curl_none_false_start,            /* false_start */
1662   mbedtls_sha256sum,                /* sha256sum */
1663   NULL,                             /* associate_connection */
1664   NULL,                             /* disassociate_connection */
1665   mbed_recv,                        /* recv decrypted data */
1666   mbed_send,                        /* send data to encrypt */
1667   NULL,                             /* get_channel_binding */
1668 };
1669 
1670 #endif /* USE_MBEDTLS */
1671