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