1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Jacob Hoffman-Andrews,
9 * <github@hoffman-andrews.com>
10 * Copyright (C) kpcyrd, <kpcyrd@archlinux.org>
11 *
12 * This software is licensed as described in the file COPYING, which
13 * you should have received as part of this distribution. The terms
14 * are also available at https://curl.se/docs/copyright.html.
15 *
16 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
17 * copies of the Software, and permit persons to whom the Software is
18 * furnished to do so, under the terms of the COPYING file.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 * SPDX-License-Identifier: curl
24 *
25 ***************************************************************************/
26 #include "curl_setup.h"
27
28 #ifdef USE_RUSTLS
29
30 #include "curl_printf.h"
31
32 #include <errno.h>
33 #include <rustls.h>
34
35 #include "inet_pton.h"
36 #include "urldata.h"
37 #include "sendf.h"
38 #include "vtls.h"
39 #include "vtls_int.h"
40 #include "rustls.h"
41 #include "select.h"
42 #include "strerror.h"
43 #include "multiif.h"
44 #include "connect.h" /* for the connect timeout */
45 #include "cipher_suite.h"
46 #include "rand.h"
47
48 struct rustls_ssl_backend_data
49 {
50 const struct rustls_client_config *config;
51 struct rustls_connection *conn;
52 size_t plain_out_buffered;
53 BIT(data_in_pending);
54 BIT(sent_shutdown);
55 };
56
57 /* For a given rustls_result error code, return the best-matching CURLcode. */
map_error(rustls_result r)58 static CURLcode map_error(rustls_result r)
59 {
60 if(rustls_result_is_cert_error(r)) {
61 return CURLE_PEER_FAILED_VERIFICATION;
62 }
63 switch(r) {
64 case RUSTLS_RESULT_OK:
65 return CURLE_OK;
66 case RUSTLS_RESULT_NULL_PARAMETER:
67 return CURLE_BAD_FUNCTION_ARGUMENT;
68 default:
69 return CURLE_RECV_ERROR;
70 }
71 }
72
73 static bool
cr_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)74 cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
75 {
76 struct ssl_connect_data *ctx = cf->ctx;
77 struct rustls_ssl_backend_data *backend;
78
79 (void)data;
80 DEBUGASSERT(ctx && ctx->backend);
81 backend = (struct rustls_ssl_backend_data *)ctx->backend;
82 return backend->data_in_pending;
83 }
84
85 struct io_ctx {
86 struct Curl_cfilter *cf;
87 struct Curl_easy *data;
88 };
89
90 static int
read_cb(void * userdata,uint8_t * buf,uintptr_t len,uintptr_t * out_n)91 read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
92 {
93 struct io_ctx *io_ctx = userdata;
94 struct ssl_connect_data *const connssl = io_ctx->cf->ctx;
95 CURLcode result;
96 int ret = 0;
97 ssize_t nread = Curl_conn_cf_recv(io_ctx->cf->next, io_ctx->data,
98 (char *)buf, len, &result);
99 if(nread < 0) {
100 nread = 0;
101 if(CURLE_AGAIN == result)
102 ret = EAGAIN;
103 else
104 ret = EINVAL;
105 }
106 else if(nread == 0)
107 connssl->peer_closed = TRUE;
108 *out_n = (uintptr_t)nread;
109 CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next recv(len=%zu) -> %zd, %d",
110 len, nread, result);
111 return ret;
112 }
113
114 static int
write_cb(void * userdata,const uint8_t * buf,uintptr_t len,uintptr_t * out_n)115 write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
116 {
117 struct io_ctx *io_ctx = userdata;
118 CURLcode result;
119 int ret = 0;
120 ssize_t nwritten = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data,
121 (const char *)buf, len, FALSE,
122 &result);
123 if(nwritten < 0) {
124 nwritten = 0;
125 if(CURLE_AGAIN == result)
126 ret = EAGAIN;
127 else
128 ret = EINVAL;
129 }
130 *out_n = (uintptr_t)nwritten;
131 CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next send(len=%zu) -> %zd, %d",
132 len, nwritten, result);
133 return ret;
134 }
135
tls_recv_more(struct Curl_cfilter * cf,struct Curl_easy * data,CURLcode * err)136 static ssize_t tls_recv_more(struct Curl_cfilter *cf,
137 struct Curl_easy *data, CURLcode *err)
138 {
139 struct ssl_connect_data *const connssl = cf->ctx;
140 struct rustls_ssl_backend_data *const backend =
141 (struct rustls_ssl_backend_data *)connssl->backend;
142 struct io_ctx io_ctx;
143 size_t tls_bytes_read = 0;
144 rustls_io_result io_error;
145 rustls_result rresult = 0;
146
147 io_ctx.cf = cf;
148 io_ctx.data = data;
149 io_error = rustls_connection_read_tls(backend->conn, read_cb, &io_ctx,
150 &tls_bytes_read);
151 if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
152 *err = CURLE_AGAIN;
153 return -1;
154 }
155 else if(io_error) {
156 char buffer[STRERROR_LEN];
157 failf(data, "reading from socket: %s",
158 Curl_strerror(io_error, buffer, sizeof(buffer)));
159 *err = CURLE_RECV_ERROR;
160 return -1;
161 }
162
163 rresult = rustls_connection_process_new_packets(backend->conn);
164 if(rresult != RUSTLS_RESULT_OK) {
165 char errorbuf[255];
166 size_t errorlen;
167 rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
168 failf(data, "rustls_connection_process_new_packets: %.*s",
169 (int)errorlen, errorbuf);
170 *err = map_error(rresult);
171 return -1;
172 }
173
174 backend->data_in_pending = TRUE;
175 *err = CURLE_OK;
176 return (ssize_t)tls_bytes_read;
177 }
178
179 /*
180 * On each run:
181 * - Read a chunk of bytes from the socket into Rustls' TLS input buffer.
182 * - Tell Rustls to process any new packets.
183 * - Read out as many plaintext bytes from Rustls as possible, until hitting
184 * error, EOF, or EAGAIN/EWOULDBLOCK, or plainbuf/plainlen is filled up.
185 *
186 * it is okay to call this function with plainbuf == NULL and plainlen == 0. In
187 * that case, it will copy bytes from the socket into Rustls' TLS input
188 * buffer, and process packets, but will not consume bytes from Rustls'
189 * plaintext output buffer.
190 */
191 static ssize_t
cr_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * plainbuf,size_t plainlen,CURLcode * err)192 cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
193 char *plainbuf, size_t plainlen, CURLcode *err)
194 {
195 struct ssl_connect_data *const connssl = cf->ctx;
196 struct rustls_ssl_backend_data *const backend =
197 (struct rustls_ssl_backend_data *)connssl->backend;
198 struct rustls_connection *rconn = NULL;
199 size_t n = 0;
200 size_t plain_bytes_copied = 0;
201 rustls_result rresult = 0;
202 ssize_t nread;
203 bool eof = FALSE;
204
205 DEBUGASSERT(backend);
206 rconn = backend->conn;
207
208 while(plain_bytes_copied < plainlen) {
209 if(!backend->data_in_pending) {
210 if(tls_recv_more(cf, data, err) < 0) {
211 if(*err != CURLE_AGAIN) {
212 nread = -1;
213 goto out;
214 }
215 break;
216 }
217 }
218
219 rresult = rustls_connection_read(rconn,
220 (uint8_t *)plainbuf + plain_bytes_copied,
221 plainlen - plain_bytes_copied,
222 &n);
223 if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
224 backend->data_in_pending = FALSE;
225 }
226 else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) {
227 failf(data, "rustls: peer closed TCP connection "
228 "without first closing TLS connection");
229 *err = CURLE_RECV_ERROR;
230 nread = -1;
231 goto out;
232 }
233 else if(rresult != RUSTLS_RESULT_OK) {
234 /* n always equals 0 in this case, do not need to check it */
235 char errorbuf[255];
236 size_t errorlen;
237 rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
238 failf(data, "rustls_connection_read: %.*s", (int)errorlen, errorbuf);
239 *err = CURLE_RECV_ERROR;
240 nread = -1;
241 goto out;
242 }
243 else if(n == 0) {
244 /* n == 0 indicates clean EOF, but we may have read some other
245 plaintext bytes before we reached this. Break out of the loop
246 so we can figure out whether to return success or EOF. */
247 eof = TRUE;
248 break;
249 }
250 else {
251 plain_bytes_copied += n;
252 }
253 }
254
255 if(plain_bytes_copied) {
256 *err = CURLE_OK;
257 nread = (ssize_t)plain_bytes_copied;
258 }
259 else if(eof) {
260 *err = CURLE_OK;
261 nread = 0;
262 }
263 else {
264 *err = CURLE_AGAIN;
265 nread = -1;
266 }
267
268 out:
269 CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d",
270 plainlen, nread, *err);
271 return nread;
272 }
273
cr_flush_out(struct Curl_cfilter * cf,struct Curl_easy * data,struct rustls_connection * rconn)274 static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data,
275 struct rustls_connection *rconn)
276 {
277 struct io_ctx io_ctx;
278 rustls_io_result io_error;
279 size_t tlswritten = 0;
280 size_t tlswritten_total = 0;
281 CURLcode result = CURLE_OK;
282
283 io_ctx.cf = cf;
284 io_ctx.data = data;
285
286 while(rustls_connection_wants_write(rconn)) {
287 io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
288 &tlswritten);
289 if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
290 CURL_TRC_CF(data, cf, "cf_send: EAGAIN after %zu bytes",
291 tlswritten_total);
292 return CURLE_AGAIN;
293 }
294 else if(io_error) {
295 char buffer[STRERROR_LEN];
296 failf(data, "writing to socket: %s",
297 Curl_strerror(io_error, buffer, sizeof(buffer)));
298 return CURLE_SEND_ERROR;
299 }
300 if(tlswritten == 0) {
301 failf(data, "EOF in swrite");
302 return CURLE_SEND_ERROR;
303 }
304 CURL_TRC_CF(data, cf, "cf_send: wrote %zu TLS bytes", tlswritten);
305 tlswritten_total += tlswritten;
306 }
307 return result;
308 }
309
310 /*
311 * On each call:
312 * - Copy `plainlen` bytes into Rustls' plaintext input buffer (if > 0).
313 * - Fully drain Rustls' plaintext output buffer into the socket until
314 * we get either an error or EAGAIN/EWOULDBLOCK.
315 *
316 * it is okay to call this function with plainbuf == NULL and plainlen == 0.
317 * In that case, it will not read anything into Rustls' plaintext input buffer.
318 * It will only drain Rustls' plaintext output buffer into the socket.
319 */
320 static ssize_t
cr_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * plainbuf,size_t plainlen,CURLcode * err)321 cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
322 const void *plainbuf, size_t plainlen, CURLcode *err)
323 {
324 struct ssl_connect_data *const connssl = cf->ctx;
325 struct rustls_ssl_backend_data *const backend =
326 (struct rustls_ssl_backend_data *)connssl->backend;
327 struct rustls_connection *rconn = NULL;
328 size_t plainwritten = 0;
329 rustls_result rresult;
330 char errorbuf[256];
331 size_t errorlen;
332 const unsigned char *buf = plainbuf;
333 size_t blen = plainlen;
334 ssize_t nwritten = 0;
335
336 DEBUGASSERT(backend);
337 rconn = backend->conn;
338 DEBUGASSERT(rconn);
339
340 CURL_TRC_CF(data, cf, "cf_send(len=%zu)", plainlen);
341
342 /* If a previous send blocked, we already added its plain bytes
343 * to rustsls and must not do that again. Flush the TLS bytes and,
344 * if successful, deduct the previous plain bytes from the current
345 * send. */
346 if(backend->plain_out_buffered) {
347 *err = cr_flush_out(cf, data, rconn);
348 CURL_TRC_CF(data, cf, "cf_send: flushing %zu previously added bytes -> %d",
349 backend->plain_out_buffered, *err);
350 if(*err)
351 return -1;
352 if(blen > backend->plain_out_buffered) {
353 blen -= backend->plain_out_buffered;
354 buf += backend->plain_out_buffered;
355 }
356 else
357 blen = 0;
358 nwritten += (ssize_t)backend->plain_out_buffered;
359 backend->plain_out_buffered = 0;
360 }
361
362 if(blen > 0) {
363 CURL_TRC_CF(data, cf, "cf_send: adding %zu plain bytes to Rustls", blen);
364 rresult = rustls_connection_write(rconn, buf, blen, &plainwritten);
365 if(rresult != RUSTLS_RESULT_OK) {
366 rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
367 failf(data, "rustls_connection_write: %.*s", (int)errorlen, errorbuf);
368 *err = CURLE_WRITE_ERROR;
369 return -1;
370 }
371 else if(plainwritten == 0) {
372 failf(data, "rustls_connection_write: EOF");
373 *err = CURLE_WRITE_ERROR;
374 return -1;
375 }
376 }
377
378 *err = cr_flush_out(cf, data, rconn);
379 if(*err) {
380 if(CURLE_AGAIN == *err) {
381 /* The TLS bytes may have been partially written, but we fail the
382 * complete send() and remember how much we already added to Rustls. */
383 CURL_TRC_CF(data, cf, "cf_send: EAGAIN, remember we added %zu plain"
384 " bytes already to Rustls", blen);
385 backend->plain_out_buffered = plainwritten;
386 if(nwritten) {
387 *err = CURLE_OK;
388 return (ssize_t)nwritten;
389 }
390 }
391 return -1;
392 }
393 else
394 nwritten += (ssize_t)plainwritten;
395
396 CURL_TRC_CF(data, cf, "cf_send(len=%zu) -> %d, %zd",
397 plainlen, *err, nwritten);
398 return nwritten;
399 }
400
401 /* A server certificate verify callback for Rustls that always returns
402 RUSTLS_RESULT_OK, or in other words disable certificate verification. */
403 static uint32_t
cr_verify_none(void * userdata UNUSED_PARAM,const rustls_verify_server_cert_params * params UNUSED_PARAM)404 cr_verify_none(void *userdata UNUSED_PARAM,
405 const rustls_verify_server_cert_params *params UNUSED_PARAM)
406 {
407 return RUSTLS_RESULT_OK;
408 }
409
410 static int
read_file_into(const char * filename,struct dynbuf * out)411 read_file_into(const char *filename,
412 struct dynbuf *out)
413 {
414 FILE *f = fopen(filename, FOPEN_READTEXT);
415 if(!f) {
416 return 0;
417 }
418
419 while(!feof(f)) {
420 uint8_t buf[256];
421 size_t rr = fread(buf, 1, sizeof(buf), f);
422 if(rr == 0 ||
423 CURLE_OK != Curl_dyn_addn(out, buf, rr)) {
424 fclose(f);
425 return 0;
426 }
427 }
428
429 return fclose(f) == 0;
430 }
431
432 static void
cr_get_selected_ciphers(struct Curl_easy * data,const char * ciphers12,const char * ciphers13,const struct rustls_supported_ciphersuite ** selected,size_t * selected_size)433 cr_get_selected_ciphers(struct Curl_easy *data,
434 const char *ciphers12,
435 const char *ciphers13,
436 const struct rustls_supported_ciphersuite **selected,
437 size_t *selected_size)
438 {
439 size_t supported_len = *selected_size;
440 size_t default_len = rustls_default_crypto_provider_ciphersuites_len();
441 const struct rustls_supported_ciphersuite *entry;
442 const char *ciphers = ciphers12;
443 size_t count = 0, default13_count = 0, i, j;
444 const char *ptr, *end;
445
446 DEBUGASSERT(default_len <= supported_len);
447
448 if(!ciphers13) {
449 /* Add default TLSv1.3 ciphers to selection */
450 for(j = 0; j < default_len; j++) {
451 entry = rustls_default_crypto_provider_ciphersuites_get(j);
452 if(rustls_supported_ciphersuite_protocol_version(entry) !=
453 RUSTLS_TLS_VERSION_TLSV1_3)
454 continue;
455
456 selected[count++] = entry;
457 }
458
459 default13_count = count;
460
461 if(!ciphers)
462 ciphers = "";
463 }
464 else
465 ciphers = ciphers13;
466
467 add_ciphers:
468 for(ptr = ciphers; ptr[0] != '\0' && count < supported_len; ptr = end) {
469 uint16_t id = Curl_cipher_suite_walk_str(&ptr, &end);
470
471 /* Check if cipher is supported */
472 if(id) {
473 for(i = 0; i < supported_len; i++) {
474 entry = rustls_default_crypto_provider_ciphersuites_get(i);
475 if(rustls_supported_ciphersuite_get_suite(entry) == id)
476 break;
477 }
478 if(i == supported_len)
479 id = 0;
480 }
481 if(!id) {
482 if(ptr[0] != '\0')
483 infof(data, "rustls: unknown cipher in list: \"%.*s\"",
484 (int) (end - ptr), ptr);
485 continue;
486 }
487
488 /* No duplicates allowed (so selected cannot overflow) */
489 for(i = 0; i < count && selected[i] != entry; i++);
490 if(i < count) {
491 if(i >= default13_count)
492 infof(data, "rustls: duplicate cipher in list: \"%.*s\"",
493 (int) (end - ptr), ptr);
494 continue;
495 }
496
497 selected[count++] = entry;
498 }
499
500 if(ciphers == ciphers13 && ciphers12) {
501 ciphers = ciphers12;
502 goto add_ciphers;
503 }
504
505 if(!ciphers12) {
506 /* Add default TLSv1.2 ciphers to selection */
507 for(j = 0; j < default_len; j++) {
508 entry = rustls_default_crypto_provider_ciphersuites_get(j);
509 if(rustls_supported_ciphersuite_protocol_version(entry) ==
510 RUSTLS_TLS_VERSION_TLSV1_3)
511 continue;
512
513 /* No duplicates allowed (so selected cannot overflow) */
514 for(i = 0; i < count && selected[i] != entry; i++);
515 if(i < count)
516 continue;
517
518 selected[count++] = entry;
519 }
520 }
521
522 *selected_size = count;
523 }
524
525 static CURLcode
cr_init_backend(struct Curl_cfilter * cf,struct Curl_easy * data,struct rustls_ssl_backend_data * const backend)526 cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
527 struct rustls_ssl_backend_data *const backend)
528 {
529 struct ssl_connect_data *connssl = cf->ctx;
530 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
531 struct rustls_crypto_provider_builder *custom_provider_builder = NULL;
532 const struct rustls_crypto_provider *custom_provider = NULL;
533 struct rustls_connection *rconn = NULL;
534 struct rustls_client_config_builder *config_builder = NULL;
535 const struct rustls_root_cert_store *roots = NULL;
536 struct rustls_root_cert_store_builder *roots_builder = NULL;
537 struct rustls_web_pki_server_cert_verifier_builder *verifier_builder = NULL;
538 struct rustls_server_cert_verifier *server_cert_verifier = NULL;
539 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
540 const char * const ssl_cafile =
541 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
542 (ca_info_blob ? NULL : conn_config->CAfile);
543 const bool verifypeer = conn_config->verifypeer;
544 char errorbuf[256];
545 size_t errorlen;
546 rustls_result result;
547
548 DEBUGASSERT(backend);
549 rconn = backend->conn;
550
551 {
552 uint16_t tls_versions[2] = {
553 RUSTLS_TLS_VERSION_TLSV1_2,
554 RUSTLS_TLS_VERSION_TLSV1_3,
555 };
556 size_t tls_versions_len = 2;
557 const struct rustls_supported_ciphersuite **cipher_suites;
558 size_t cipher_suites_len =
559 rustls_default_crypto_provider_ciphersuites_len();
560
561 switch(conn_config->version) {
562 case CURL_SSLVERSION_DEFAULT:
563 case CURL_SSLVERSION_TLSv1:
564 case CURL_SSLVERSION_TLSv1_0:
565 case CURL_SSLVERSION_TLSv1_1:
566 case CURL_SSLVERSION_TLSv1_2:
567 break;
568 case CURL_SSLVERSION_TLSv1_3:
569 tls_versions[0] = RUSTLS_TLS_VERSION_TLSV1_3;
570 tls_versions_len = 1;
571 break;
572 default:
573 failf(data, "rustls: unsupported minimum TLS version value");
574 return CURLE_BAD_FUNCTION_ARGUMENT;
575 }
576
577 switch(conn_config->version_max) {
578 case CURL_SSLVERSION_MAX_DEFAULT:
579 case CURL_SSLVERSION_MAX_NONE:
580 case CURL_SSLVERSION_MAX_TLSv1_3:
581 break;
582 case CURL_SSLVERSION_MAX_TLSv1_2:
583 if(tls_versions[0] == RUSTLS_TLS_VERSION_TLSV1_2) {
584 tls_versions_len = 1;
585 break;
586 }
587 FALLTHROUGH();
588 case CURL_SSLVERSION_MAX_TLSv1_1:
589 case CURL_SSLVERSION_MAX_TLSv1_0:
590 default:
591 failf(data, "rustls: unsupported maximum TLS version value");
592 return CURLE_BAD_FUNCTION_ARGUMENT;
593 }
594
595 cipher_suites = malloc(sizeof(cipher_suites) * (cipher_suites_len));
596 if(!cipher_suites)
597 return CURLE_OUT_OF_MEMORY;
598
599 cr_get_selected_ciphers(data,
600 conn_config->cipher_list,
601 conn_config->cipher_list13,
602 cipher_suites, &cipher_suites_len);
603 if(cipher_suites_len == 0) {
604 failf(data, "rustls: no supported cipher in list");
605 free(cipher_suites);
606 return CURLE_SSL_CIPHER;
607 }
608
609 result = rustls_crypto_provider_builder_new_from_default(
610 &custom_provider_builder);
611 if(result != RUSTLS_RESULT_OK) {
612 failf(data,
613 "rustls: failed to create crypto provider builder from default");
614 return CURLE_SSL_CIPHER;
615 }
616
617 result =
618 rustls_crypto_provider_builder_set_cipher_suites(
619 custom_provider_builder,
620 cipher_suites,
621 cipher_suites_len);
622 if(result != RUSTLS_RESULT_OK) {
623 failf(data,
624 "rustls: failed to set ciphersuites for crypto provider builder");
625 rustls_crypto_provider_builder_free(custom_provider_builder);
626 return CURLE_SSL_CIPHER;
627 }
628
629 result = rustls_crypto_provider_builder_build(
630 custom_provider_builder, &custom_provider);
631 if(result != RUSTLS_RESULT_OK) {
632 failf(data, "rustls: failed to build custom crypto provider");
633 rustls_crypto_provider_builder_free(custom_provider_builder);
634 return CURLE_SSL_CIPHER;
635 }
636
637 result = rustls_client_config_builder_new_custom(custom_provider,
638 tls_versions,
639 tls_versions_len,
640 &config_builder);
641 free(cipher_suites);
642 if(result != RUSTLS_RESULT_OK) {
643 failf(data, "rustls: failed to create client config");
644 return CURLE_SSL_CIPHER;
645 }
646 }
647
648 rustls_crypto_provider_builder_free(custom_provider_builder);
649 rustls_crypto_provider_free(custom_provider);
650
651 if(connssl->alpn) {
652 struct alpn_proto_buf proto;
653 rustls_slice_bytes alpn[ALPN_ENTRIES_MAX];
654 size_t i;
655
656 for(i = 0; i < connssl->alpn->count; ++i) {
657 alpn[i].data = (const uint8_t *)connssl->alpn->entries[i];
658 alpn[i].len = strlen(connssl->alpn->entries[i]);
659 }
660 rustls_client_config_builder_set_alpn_protocols(config_builder, alpn,
661 connssl->alpn->count);
662 Curl_alpn_to_proto_str(&proto, connssl->alpn);
663 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
664 }
665 if(!verifypeer) {
666 rustls_client_config_builder_dangerous_set_certificate_verifier(
667 config_builder, cr_verify_none);
668 }
669 else if(ca_info_blob || ssl_cafile) {
670 roots_builder = rustls_root_cert_store_builder_new();
671
672 if(ca_info_blob) {
673 /* Enable strict parsing only if verification is not disabled. */
674 result = rustls_root_cert_store_builder_add_pem(roots_builder,
675 ca_info_blob->data,
676 ca_info_blob->len,
677 verifypeer);
678 if(result != RUSTLS_RESULT_OK) {
679 failf(data, "rustls: failed to parse trusted certificates from blob");
680 rustls_root_cert_store_builder_free(roots_builder);
681 rustls_client_config_builder_free(config_builder);
682 return CURLE_SSL_CACERT_BADFILE;
683 }
684 }
685 else if(ssl_cafile) {
686 /* Enable strict parsing only if verification is not disabled. */
687 result = rustls_root_cert_store_builder_load_roots_from_file(
688 roots_builder, ssl_cafile, verifypeer);
689 if(result != RUSTLS_RESULT_OK) {
690 failf(data, "rustls: failed to load trusted certificates");
691 rustls_root_cert_store_builder_free(roots_builder);
692 rustls_client_config_builder_free(config_builder);
693 return CURLE_SSL_CACERT_BADFILE;
694 }
695 }
696
697 result = rustls_root_cert_store_builder_build(roots_builder, &roots);
698 rustls_root_cert_store_builder_free(roots_builder);
699 if(result != RUSTLS_RESULT_OK) {
700 failf(data, "rustls: failed to build trusted root certificate store");
701 rustls_client_config_builder_free(config_builder);
702 return CURLE_SSL_CACERT_BADFILE;
703 }
704
705 verifier_builder = rustls_web_pki_server_cert_verifier_builder_new(roots);
706 rustls_root_cert_store_free(roots);
707
708 if(conn_config->CRLfile) {
709 struct dynbuf crl_contents;
710 Curl_dyn_init(&crl_contents, SIZE_MAX);
711 if(!read_file_into(conn_config->CRLfile, &crl_contents)) {
712 failf(data, "rustls: failed to read revocation list file");
713 Curl_dyn_free(&crl_contents);
714 rustls_web_pki_server_cert_verifier_builder_free(verifier_builder);
715 return CURLE_SSL_CRL_BADFILE;
716 }
717
718 result = rustls_web_pki_server_cert_verifier_builder_add_crl(
719 verifier_builder,
720 Curl_dyn_uptr(&crl_contents),
721 Curl_dyn_len(&crl_contents));
722 Curl_dyn_free(&crl_contents);
723 if(result != RUSTLS_RESULT_OK) {
724 failf(data, "rustls: failed to parse revocation list");
725 rustls_web_pki_server_cert_verifier_builder_free(verifier_builder);
726 return CURLE_SSL_CRL_BADFILE;
727 }
728 }
729
730 result = rustls_web_pki_server_cert_verifier_builder_build(
731 verifier_builder, &server_cert_verifier);
732 rustls_web_pki_server_cert_verifier_builder_free(verifier_builder);
733 if(result != RUSTLS_RESULT_OK) {
734 failf(data, "rustls: failed to build certificate verifier");
735 rustls_server_cert_verifier_free(server_cert_verifier);
736 rustls_client_config_builder_free(config_builder);
737 return CURLE_SSL_CACERT_BADFILE;
738 }
739
740 rustls_client_config_builder_set_server_verifier(config_builder,
741 server_cert_verifier);
742 rustls_server_cert_verifier_free(server_cert_verifier);
743 }
744
745 result = rustls_client_config_builder_build(
746 config_builder,
747 &backend->config);
748 if(result != RUSTLS_RESULT_OK) {
749 failf(data, "rustls: failed to build client config");
750 rustls_client_config_free(backend->config);
751 return CURLE_SSL_CONNECT_ERROR;
752 }
753
754 DEBUGASSERT(rconn == NULL);
755 result = rustls_client_connection_new(backend->config,
756 connssl->peer.hostname, &rconn);
757 if(result != RUSTLS_RESULT_OK) {
758 rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen);
759 failf(data, "rustls_client_connection_new: %.*s", (int)errorlen, errorbuf);
760 return CURLE_COULDNT_CONNECT;
761 }
762 DEBUGASSERT(rconn);
763 rustls_connection_set_userdata(rconn, backend);
764 backend->conn = rconn;
765 return CURLE_OK;
766 }
767
768 static void
cr_set_negotiated_alpn(struct Curl_cfilter * cf,struct Curl_easy * data,const struct rustls_connection * rconn)769 cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
770 const struct rustls_connection *rconn)
771 {
772 struct ssl_connect_data *const connssl = cf->ctx;
773 const uint8_t *protocol = NULL;
774 size_t len = 0;
775
776 rustls_connection_get_alpn_protocol(rconn, &protocol, &len);
777 Curl_alpn_set_negotiated(cf, data, connssl, protocol, len);
778 }
779
780 /* Given an established network connection, do a TLS handshake.
781 *
782 * If `blocking` is true, this function will block until the handshake is
783 * complete. Otherwise it will return as soon as I/O would block.
784 *
785 * For the non-blocking I/O case, this function will set `*done` to true
786 * once the handshake is complete. This function never reads the value of
787 * `*done*`.
788 */
789 static CURLcode
cr_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool blocking,bool * done)790 cr_connect_common(struct Curl_cfilter *cf,
791 struct Curl_easy *data,
792 bool blocking,
793 bool *done)
794 {
795 struct ssl_connect_data *const connssl = cf->ctx;
796 curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
797 struct rustls_ssl_backend_data *const backend =
798 (struct rustls_ssl_backend_data *)connssl->backend;
799 struct rustls_connection *rconn = NULL;
800 CURLcode tmperr = CURLE_OK;
801 int result;
802 int what;
803 bool wants_read;
804 bool wants_write;
805 curl_socket_t writefd;
806 curl_socket_t readfd;
807 timediff_t timeout_ms;
808 timediff_t socket_check_timeout;
809
810 DEBUGASSERT(backend);
811
812 CURL_TRC_CF(data, cf, "cr_connect_common, state=%d", connssl->state);
813 *done = FALSE;
814 if(!backend->conn) {
815 result = cr_init_backend(cf, data,
816 (struct rustls_ssl_backend_data *)connssl->backend);
817 CURL_TRC_CF(data, cf, "cr_connect_common, init backend -> %d", result);
818 if(result != CURLE_OK) {
819 return result;
820 }
821 connssl->state = ssl_connection_negotiating;
822 }
823
824 rconn = backend->conn;
825
826 /* Read/write data until the handshake is done or the socket would block. */
827 for(;;) {
828 /*
829 * Connection has been established according to Rustls. Set send/recv
830 * handlers, and update the state machine.
831 */
832 connssl->io_need = CURL_SSL_IO_NEED_NONE;
833 if(!rustls_connection_is_handshaking(rconn)) {
834 /* Rustls claims it is no longer handshaking *before* it has
835 * send its FINISHED message off. We attempt to let it write
836 * one more time. Oh my.
837 */
838 cr_set_negotiated_alpn(cf, data, rconn);
839 cr_send(cf, data, NULL, 0, &tmperr);
840 if(tmperr == CURLE_AGAIN) {
841 connssl->io_need = CURL_SSL_IO_NEED_SEND;
842 return CURLE_OK;
843 }
844 else if(tmperr != CURLE_OK) {
845 return tmperr;
846 }
847 /* REALLY Done with the handshake. */
848 {
849 uint16_t proto = rustls_connection_get_protocol_version(rconn);
850 uint16_t cipher = rustls_connection_get_negotiated_ciphersuite(rconn);
851 char buf[64] = "";
852 const char *ver = "TLS version unknown";
853 if(proto == RUSTLS_TLS_VERSION_TLSV1_3)
854 ver = "TLSv1.3";
855 if(proto == RUSTLS_TLS_VERSION_TLSV1_2)
856 ver = "TLSv1.2";
857 Curl_cipher_suite_get_str(cipher, buf, sizeof(buf), TRUE);
858 infof(data, "rustls: handshake complete, %s, cipher: %s",
859 ver, buf);
860 }
861 connssl->state = ssl_connection_complete;
862 *done = TRUE;
863 return CURLE_OK;
864 }
865
866 connssl->connecting_state = ssl_connect_2;
867 wants_read = rustls_connection_wants_read(rconn);
868 wants_write = rustls_connection_wants_write(rconn) ||
869 backend->plain_out_buffered;
870 DEBUGASSERT(wants_read || wants_write);
871 writefd = wants_write ? sockfd : CURL_SOCKET_BAD;
872 readfd = wants_read ? sockfd : CURL_SOCKET_BAD;
873
874 /* check allowed time left */
875 timeout_ms = Curl_timeleft(data, NULL, TRUE);
876
877 if(timeout_ms < 0) {
878 /* no need to continue if time already is up */
879 failf(data, "rustls: operation timed out before socket check");
880 return CURLE_OPERATION_TIMEDOUT;
881 }
882
883 socket_check_timeout = blocking ? timeout_ms : 0;
884
885 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
886 socket_check_timeout);
887 if(what < 0) {
888 /* fatal error */
889 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
890 return CURLE_SSL_CONNECT_ERROR;
891 }
892 if(blocking && 0 == what) {
893 failf(data, "rustls: connection timeout after %" FMT_TIMEDIFF_T " ms",
894 socket_check_timeout);
895 return CURLE_OPERATION_TIMEDOUT;
896 }
897 if(0 == what) {
898 CURL_TRC_CF(data, cf, "Curl_socket_check: %s would block",
899 wants_read && wants_write ? "writing and reading" :
900 wants_write ? "writing" : "reading");
901 if(wants_write)
902 connssl->io_need |= CURL_SSL_IO_NEED_SEND;
903 if(wants_read)
904 connssl->io_need |= CURL_SSL_IO_NEED_RECV;
905 return CURLE_OK;
906 }
907 /* socket is readable or writable */
908
909 if(wants_write) {
910 CURL_TRC_CF(data, cf, "rustls_connection wants us to write_tls.");
911 cr_send(cf, data, NULL, 0, &tmperr);
912 if(tmperr == CURLE_AGAIN) {
913 CURL_TRC_CF(data, cf, "writing would block");
914 /* fall through */
915 }
916 else if(tmperr != CURLE_OK) {
917 return tmperr;
918 }
919 }
920
921 if(wants_read) {
922 CURL_TRC_CF(data, cf, "rustls_connection wants us to read_tls.");
923 if(tls_recv_more(cf, data, &tmperr) < 0) {
924 if(tmperr == CURLE_AGAIN) {
925 CURL_TRC_CF(data, cf, "reading would block");
926 /* fall through */
927 }
928 else if(tmperr == CURLE_RECV_ERROR) {
929 return CURLE_SSL_CONNECT_ERROR;
930 }
931 else {
932 return tmperr;
933 }
934 }
935 }
936 }
937
938 /* We should never fall through the loop. We should return either because
939 the handshake is done or because we cannot read/write without blocking. */
940 DEBUGASSERT(FALSE);
941 }
942
943 static CURLcode
cr_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)944 cr_connect_nonblocking(struct Curl_cfilter *cf,
945 struct Curl_easy *data, bool *done)
946 {
947 return cr_connect_common(cf, data, false, done);
948 }
949
950 static CURLcode
cr_connect_blocking(struct Curl_cfilter * cf,struct Curl_easy * data)951 cr_connect_blocking(struct Curl_cfilter *cf, struct Curl_easy *data)
952 {
953 bool done; /* unused */
954 return cr_connect_common(cf, data, true, &done);
955 }
956
957 static void *
cr_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)958 cr_get_internals(struct ssl_connect_data *connssl,
959 CURLINFO info UNUSED_PARAM)
960 {
961 struct rustls_ssl_backend_data *backend =
962 (struct rustls_ssl_backend_data *)connssl->backend;
963 DEBUGASSERT(backend);
964 return &backend->conn;
965 }
966
967 static CURLcode
cr_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool send_shutdown,bool * done)968 cr_shutdown(struct Curl_cfilter *cf,
969 struct Curl_easy *data,
970 bool send_shutdown, bool *done)
971 {
972 struct ssl_connect_data *connssl = cf->ctx;
973 struct rustls_ssl_backend_data *backend =
974 (struct rustls_ssl_backend_data *)connssl->backend;
975 CURLcode result = CURLE_OK;
976 ssize_t nwritten, nread;
977 char buf[1024];
978 size_t i;
979
980 DEBUGASSERT(backend);
981 if(!backend->conn || cf->shutdown) {
982 *done = TRUE;
983 goto out;
984 }
985
986 connssl->io_need = CURL_SSL_IO_NEED_NONE;
987 *done = FALSE;
988
989 if(!backend->sent_shutdown) {
990 /* do this only once */
991 backend->sent_shutdown = TRUE;
992 if(send_shutdown) {
993 rustls_connection_send_close_notify(backend->conn);
994 }
995 }
996
997 nwritten = cr_send(cf, data, NULL, 0, &result);
998 if(nwritten < 0) {
999 if(result == CURLE_AGAIN) {
1000 connssl->io_need = CURL_SSL_IO_NEED_SEND;
1001 result = CURLE_OK;
1002 goto out;
1003 }
1004 DEBUGASSERT(result);
1005 CURL_TRC_CF(data, cf, "shutdown send failed: %d", result);
1006 goto out;
1007 }
1008
1009 for(i = 0; i < 10; ++i) {
1010 nread = cr_recv(cf, data, buf, (int)sizeof(buf), &result);
1011 if(nread <= 0)
1012 break;
1013 }
1014
1015 if(nread > 0) {
1016 /* still data coming in? */
1017 }
1018 else if(nread == 0) {
1019 /* We got the close notify alert and are done. */
1020 *done = TRUE;
1021 }
1022 else if(result == CURLE_AGAIN) {
1023 connssl->io_need = CURL_SSL_IO_NEED_RECV;
1024 result = CURLE_OK;
1025 }
1026 else {
1027 DEBUGASSERT(result);
1028 CURL_TRC_CF(data, cf, "shutdown, error: %d", result);
1029 }
1030
1031 out:
1032 cf->shutdown = (result || *done);
1033 return result;
1034 }
1035
1036 static void
cr_close(struct Curl_cfilter * cf,struct Curl_easy * data)1037 cr_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1038 {
1039 struct ssl_connect_data *connssl = cf->ctx;
1040 struct rustls_ssl_backend_data *backend =
1041 (struct rustls_ssl_backend_data *)connssl->backend;
1042
1043 (void)data;
1044 DEBUGASSERT(backend);
1045 if(backend->conn) {
1046 rustls_connection_free(backend->conn);
1047 backend->conn = NULL;
1048 }
1049 if(backend->config) {
1050 rustls_client_config_free(backend->config);
1051 backend->config = NULL;
1052 }
1053 }
1054
cr_version(char * buffer,size_t size)1055 static size_t cr_version(char *buffer, size_t size)
1056 {
1057 struct rustls_str ver = rustls_version();
1058 return msnprintf(buffer, size, "%.*s", (int)ver.len, ver.data);
1059 }
1060
1061 static CURLcode
cr_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1062 cr_random(struct Curl_easy *data, unsigned char *entropy, size_t length)
1063 {
1064 rustls_result rresult = 0;
1065 (void)data;
1066 rresult =
1067 rustls_default_crypto_provider_random(entropy, length);
1068 return map_error(rresult);
1069 }
1070
1071 const struct Curl_ssl Curl_ssl_rustls = {
1072 { CURLSSLBACKEND_RUSTLS, "rustls" },
1073 SSLSUPP_CAINFO_BLOB | /* supports */
1074 SSLSUPP_HTTPS_PROXY |
1075 SSLSUPP_CIPHER_LIST |
1076 SSLSUPP_TLS13_CIPHERSUITES,
1077 sizeof(struct rustls_ssl_backend_data),
1078
1079 NULL, /* init */
1080 NULL, /* cleanup */
1081 cr_version, /* version */
1082 cr_shutdown, /* shutdown */
1083 cr_data_pending, /* data_pending */
1084 cr_random, /* random */
1085 NULL, /* cert_status_request */
1086 cr_connect_blocking, /* connect */
1087 cr_connect_nonblocking, /* connect_nonblocking */
1088 Curl_ssl_adjust_pollset, /* adjust_pollset */
1089 cr_get_internals, /* get_internals */
1090 cr_close, /* close_one */
1091 NULL, /* close_all */
1092 NULL, /* set_engine */
1093 NULL, /* set_engine_default */
1094 NULL, /* engines_list */
1095 NULL, /* false_start */
1096 NULL, /* sha256sum */
1097 cr_recv, /* recv decrypted data */
1098 cr_send, /* send data to encrypt */
1099 NULL, /* get_channel_binding */
1100 };
1101
1102 #endif /* USE_RUSTLS */
1103