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
This commit is contained in:
Jacob Hoffman-Andrews 2021-03-13 17:54:43 -08:00 committed by Daniel Stenberg
parent 7dbb0a87e6
commit 3780717db0
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -37,11 +37,16 @@
#include "multiif.h" #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 struct ssl_backend_data
{ {
const struct rustls_client_config *config; const struct rustls_client_config *config;
struct rustls_client_session *session; struct rustls_client_session *session;
bool data_pending; bool data_pending;
uint8_t *tlsbuf;
}; };
/* For a given rustls_result error code, return the best-matching CURLcode. */ /* 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 ssl_backend_data *const backend = connssl->backend;
struct rustls_client_session *const session = backend->session; struct rustls_client_session *const session = backend->session;
curl_socket_t sockfd = conn->sock[sockindex]; 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; size_t n = 0;
ssize_t tls_bytes_read = 0; ssize_t tls_bytes_read = 0;
size_t tls_bytes_processed = 0; size_t tls_bytes_processed = 0;
@ -108,7 +110,7 @@ cr_recv(struct Curl_easy *data, int sockindex,
rustls_result rresult = 0; rustls_result rresult = 0;
char errorbuf[255]; 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) { if(tls_bytes_read == 0) {
failf(data, "EOF in sread"); failf(data, "EOF in sread");
*err = CURLE_READ_ERROR; *err = CURLE_READ_ERROR;
@ -131,7 +133,7 @@ cr_recv(struct Curl_easy *data, int sockindex,
DEBUGASSERT(tls_bytes_read > 0); DEBUGASSERT(tls_bytes_read > 0);
while(tls_bytes_processed < (size_t)tls_bytes_read) { while(tls_bytes_processed < (size_t)tls_bytes_read) {
rresult = rustls_client_session_read_tls(session, rresult = rustls_client_session_read_tls(session,
(uint8_t *)tlsbuf + tls_bytes_processed, backend->tlsbuf + tls_bytes_processed,
tls_bytes_read - tls_bytes_processed, tls_bytes_read - tls_bytes_processed,
&n); &n);
if(rresult != RUSTLS_RESULT_OK) { if(rresult != RUSTLS_RESULT_OK) {
@ -214,8 +216,6 @@ cr_send(struct Curl_easy *data, int sockindex,
size_t plainwritten = 0; size_t plainwritten = 0;
size_t tlslen = 0; size_t tlslen = 0;
size_t tlswritten = 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; rustls_result rresult;
if(plainlen > 0) { if(plainlen > 0) {
@ -235,7 +235,7 @@ cr_send(struct Curl_easy *data, int sockindex,
while(rustls_client_session_wants_write(session)) { while(rustls_client_session_wants_write(session)) {
rresult = rustls_client_session_write_tls( rresult = rustls_client_session_write_tls(
session, tlsbuf, sizeof(tlsbuf), &tlslen); session, backend->tlsbuf, TLSBUF_SIZE, &tlslen);
if(rresult != RUSTLS_RESULT_OK) { if(rresult != RUSTLS_RESULT_OK) {
failf(data, "error in rustls_client_session_write_tls"); failf(data, "error in rustls_client_session_write_tls");
*err = CURLE_WRITE_ERROR; *err = CURLE_WRITE_ERROR;
@ -250,7 +250,7 @@ cr_send(struct Curl_easy *data, int sockindex,
tlswritten = 0; tlswritten = 0;
while(tlswritten < tlslen) { while(tlswritten < tlslen) {
n = swrite(sockfd, tlsbuf + tlswritten, tlslen - tlswritten); n = swrite(sockfd, backend->tlsbuf + tlswritten, tlslen - tlswritten);
if(n < 0) { if(n < 0) {
if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) { if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
/* Since recv is called from poll, there should be room to /* 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; size_t errorlen;
int result; int result;
backend->tlsbuf = calloc(TLSBUF_SIZE, 1);
if(backend->tlsbuf == NULL) {
return CURLE_OUT_OF_MEMORY;
}
config_builder = rustls_client_config_builder_new(); config_builder = rustls_client_config_builder_new();
if(!verifypeer) { if(!verifypeer) {
rustls_client_config_builder_dangerous_set_certificate_verifier( 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); rustls_client_config_free(backend->config);
backend->config = NULL; backend->config = NULL;
} }
free(backend->tlsbuf);
} }
const struct Curl_ssl Curl_ssl_rustls = { const struct Curl_ssl Curl_ssl_rustls = {