From 3780717db0bb65ae2a5cd005defbe36cd8857a5b Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Sat, 13 Mar 2021 17:54:43 -0800 Subject: [PATCH] rustls: allocate a buffer for TLS data. Previously, rustls was using an on-stack array for TLS data. However, crustls has an (unusual) requirement that buffers it deals with are initialized before writing to them. By using calloc, we can ensure the buffer is initialized once and then reuse it across calls. Closes #6742 --- lib/vtls/rustls.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index f64899acc5..3b7bc3afb7 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -37,11 +37,16 @@ #include "multiif.h" +/* Per https://www.bearssl.org/api1.html, max TLS record size plus max + per-record overhead. */ +#define TLSBUF_SIZE (16384 + 325) + struct ssl_backend_data { const struct rustls_client_config *config; struct rustls_client_session *session; bool data_pending; + uint8_t *tlsbuf; }; /* For a given rustls_result error code, return the best-matching CURLcode. */ @@ -98,9 +103,6 @@ cr_recv(struct Curl_easy *data, int sockindex, struct ssl_backend_data *const backend = connssl->backend; struct rustls_client_session *const session = backend->session; curl_socket_t sockfd = conn->sock[sockindex]; - /* Per https://www.bearssl.org/api1.html, max TLS record size plus max - per-record overhead. */ - uint8_t tlsbuf[16384 + 325]; size_t n = 0; ssize_t tls_bytes_read = 0; size_t tls_bytes_processed = 0; @@ -108,7 +110,7 @@ cr_recv(struct Curl_easy *data, int sockindex, rustls_result rresult = 0; char errorbuf[255]; - tls_bytes_read = sread(sockfd, tlsbuf, sizeof(tlsbuf)); + tls_bytes_read = sread(sockfd, backend->tlsbuf, TLSBUF_SIZE); if(tls_bytes_read == 0) { failf(data, "EOF in sread"); *err = CURLE_READ_ERROR; @@ -131,7 +133,7 @@ cr_recv(struct Curl_easy *data, int sockindex, DEBUGASSERT(tls_bytes_read > 0); while(tls_bytes_processed < (size_t)tls_bytes_read) { rresult = rustls_client_session_read_tls(session, - (uint8_t *)tlsbuf + tls_bytes_processed, + backend->tlsbuf + tls_bytes_processed, tls_bytes_read - tls_bytes_processed, &n); if(rresult != RUSTLS_RESULT_OK) { @@ -214,8 +216,6 @@ cr_send(struct Curl_easy *data, int sockindex, size_t plainwritten = 0; size_t tlslen = 0; size_t tlswritten = 0; - /* Max size of a TLS message, plus some space for TLS framing overhead. */ - uint8_t tlsbuf[16384 + 325]; rustls_result rresult; if(plainlen > 0) { @@ -235,7 +235,7 @@ cr_send(struct Curl_easy *data, int sockindex, while(rustls_client_session_wants_write(session)) { rresult = rustls_client_session_write_tls( - session, tlsbuf, sizeof(tlsbuf), &tlslen); + session, backend->tlsbuf, TLSBUF_SIZE, &tlslen); if(rresult != RUSTLS_RESULT_OK) { failf(data, "error in rustls_client_session_write_tls"); *err = CURLE_WRITE_ERROR; @@ -250,7 +250,7 @@ cr_send(struct Curl_easy *data, int sockindex, tlswritten = 0; while(tlswritten < tlslen) { - n = swrite(sockfd, tlsbuf + tlswritten, tlslen - tlswritten); + n = swrite(sockfd, backend->tlsbuf + tlswritten, tlslen - tlswritten); if(n < 0) { if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) { /* Since recv is called from poll, there should be room to @@ -315,6 +315,11 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn, size_t errorlen; int result; + backend->tlsbuf = calloc(TLSBUF_SIZE, 1); + if(backend->tlsbuf == NULL) { + return CURLE_OUT_OF_MEMORY; + } + config_builder = rustls_client_config_builder_new(); if(!verifypeer) { rustls_client_config_builder_dangerous_set_certificate_verifier( @@ -518,6 +523,7 @@ cr_close(struct Curl_easy *data, struct connectdata *conn, rustls_client_config_free(backend->config); backend->config = NULL; } + free(backend->tlsbuf); } const struct Curl_ssl Curl_ssl_rustls = {