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