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