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