Defer write buffer and WPACKET allocation/initialisation to protocol code

We move some protocol specific code for write buffer and WPACKET allocation
and initialisation out of tls_common.c and into the protocol specific files.

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19343)
This commit is contained in:
Matt Caswell 2022-09-26 16:35:30 +01:00
parent f93c0f5464
commit 91fe8ff02a
7 changed files with 285 additions and 116 deletions

View File

@ -15,6 +15,8 @@
#include "recmethod_local.h"
#include "internal/ktls.h"
static struct record_functions_st ossl_ktls_funcs;
#if defined(__FreeBSD__)
# include "crypto/cryptodev.h"
@ -389,19 +391,6 @@ static int ktls_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
return 1;
}
static struct record_functions_st ossl_ktls_funcs = {
ktls_set_crypto_state,
ktls_cipher,
NULL,
tls_default_set_protocol_version,
ktls_read_n,
tls_get_more_records,
ktls_validate_record_header,
ktls_post_process_record,
tls_get_max_records_default,
tls_write_records_default
};
static int
ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
int role, int direction, int level, uint16_t epoch,
@ -445,6 +434,67 @@ ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
return ret;
}
static int ktls_allocate_write_buffers(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl, size_t *prefix)
{
if (!ossl_assert(numtempl == 1))
return 0;
/*
* We just use the end application buffer in the case of KTLS, so nothing
* to do. We pretend we set up one buffer.
*/
rl->numwpipes = 1;
return 1;
}
static int ktls_initialise_write_packets(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl,
OSSL_RECORD_TEMPLATE *prefixtempl,
WPACKET *pkt,
SSL3_BUFFER *bufs,
size_t *wpinited)
{
SSL3_BUFFER *wb;
/*
* We just use the application buffer directly, and don't use any WPACKET
* structures
*/
wb = &bufs[0];
wb->type = templates[0].type;
/*
* ktls doesn't modify the buffer, but to avoid a warning we need
* to discard the const qualifier.
* This doesn't leak memory because the buffers have been
* released when switching to ktls.
*/
SSL3_BUFFER_set_buf(wb, (unsigned char *)templates[0].buf);
SSL3_BUFFER_set_offset(wb, 0);
SSL3_BUFFER_set_app_buffer(wb, 1);
return 1;
}
static struct record_functions_st ossl_ktls_funcs = {
ktls_set_crypto_state,
ktls_cipher,
NULL,
tls_default_set_protocol_version,
ktls_read_n,
tls_get_more_records,
ktls_validate_record_header,
ktls_post_process_record,
tls_get_max_records_default,
tls_write_records_default,
ktls_allocate_write_buffers,
ktls_initialise_write_packets
};
const OSSL_RECORD_METHOD ossl_ktls_record_method = {
ktls_new_record_layer,
tls_free,

View File

@ -74,6 +74,27 @@ struct record_functions_st
/* Return 1 for success or 0 for error */
int (*write_records)(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates,
size_t numtempl);
/* Allocate the rl->wbuf buffers. Return 1 for success or 0 for error */
int (*allocate_write_buffers)(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl, size_t *prefix);
/*
* Initialise the packets in the |pkt| array using the buffers in |rl->wbuf|.
* Some protocol versions may use the space in |prefixtempl| to add
* an artificial template in front of the |templates| array and hence may
* initialise 1 more WPACKET than there are templates. |*wpinited|
* returns the number of WPACKETs in |pkt| that were successfully
* initialised. This must be 0 on entry and will be filled in even on error.
*/
int (*initialise_write_packets)(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl,
OSSL_RECORD_TEMPLATE *prefixtempl,
WPACKET *pkt,
SSL3_BUFFER *bufs,
size_t *wpinited);
};
struct ossl_record_layer_st
@ -343,6 +364,26 @@ int tls_write_records_multiblock(OSSL_RECORD_LAYER *rl,
size_t tls_get_max_records_default(OSSL_RECORD_LAYER *rl, int type, size_t len,
size_t maxfrag, size_t *preffrag);
int tls_allocate_write_buffers_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl, size_t *prefix);
int tls_initialise_write_packets_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl,
OSSL_RECORD_TEMPLATE *prefixtempl,
WPACKET *pkt,
SSL3_BUFFER *bufs,
size_t *wpinited);
int tls1_allocate_write_buffers(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl, size_t *prefix);
int tls1_initialise_write_packets(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl,
OSSL_RECORD_TEMPLATE *prefixtempl,
WPACKET *pkt,
SSL3_BUFFER *bufs,
size_t *wpinited);
size_t tls_get_max_records_multiblock(OSSL_RECORD_LAYER *rl, int type,
size_t len, size_t maxfrag,
size_t *preffrag);

View File

@ -310,5 +310,8 @@ struct record_functions_st ssl_3_0_funcs = {
tls_default_validate_record_header,
tls_default_post_process_record,
tls_get_max_records_default,
tls_write_records_default
tls_write_records_default,
/* These 2 functions are defined in tls1_meth.c */
tls1_allocate_write_buffers,
tls1_initialise_write_packets
};

View File

@ -249,5 +249,7 @@ struct record_functions_st tls_1_3_funcs = {
tls13_validate_record_header,
tls13_post_process_record,
tls_get_max_records_default,
tls_write_records_default
tls_write_records_default,
tls_allocate_write_buffers_default,
tls_initialise_write_packets_default
};

View File

@ -10,6 +10,7 @@
#include <openssl/evp.h>
#include <openssl/core_names.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include "../../ssl_local.h"
#include "../record_local.h"
#include "recmethod_local.h"
@ -542,6 +543,104 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
return ret;
}
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
# ifndef OPENSSL_NO_COMP
# define MAX_PREFIX_LEN ((SSL3_ALIGN_PAYLOAD - 1) \
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \
+ SSL3_RT_HEADER_LENGTH \
+ SSL3_RT_MAX_COMPRESSED_OVERHEAD)
# else
# define MAX_PREFIX_LEN ((SSL3_ALIGN_PAYLOAD - 1) \
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \
+ SSL3_RT_HEADER_LENGTH)
# endif /* OPENSSL_NO_COMP */
#else
# ifndef OPENSSL_NO_COMP
# define MAX_PREFIX_LEN (SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \
+ SSL3_RT_HEADER_LENGTH \
+ SSL3_RT_MAX_COMPRESSED_OVERHEAD)
# else
# define MAX_PREFIX_LEN (SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \
+ SSL3_RT_HEADER_LENGTH)
# endif /* OPENSSL_NO_COMP */
#endif
/* This function is also used by the SSLv3 implementation */
int tls1_allocate_write_buffers(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl, size_t *prefix)
{
/* Do we need to add an empty record prefix? */
*prefix = rl->need_empty_fragments
&& templates[0].type == SSL3_RT_APPLICATION_DATA;
/*
* In the prefix case we can allocate a much smaller buffer. Otherwise we
* just allocate the default buffer size
*/
if (!tls_setup_write_buffer(rl, numtempl + *prefix,
*prefix ? MAX_PREFIX_LEN : 0, 0)) {
/* RLAYERfatal() already called */
return 0;
}
return 1;
}
/* This function is also used by the SSLv3 implementation */
int tls1_initialise_write_packets(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl,
OSSL_RECORD_TEMPLATE *prefixtempl,
WPACKET *pkt,
SSL3_BUFFER *bufs,
size_t *wpinited)
{
size_t align = 0;
SSL3_BUFFER *wb;
size_t prefix;
/* Do we need to add an empty record prefix? */
prefix = rl->need_empty_fragments
&& templates[0].type == SSL3_RT_APPLICATION_DATA;
if (prefix) {
/*
* countermeasure against known-IV weakness in CBC ciphersuites (see
* http://www.openssl.org/~bodo/tls-cbc.txt)
*/
prefixtempl->buf = NULL;
prefixtempl->version = templates[0].version;
prefixtempl->buflen = 0;
prefixtempl->type = SSL3_RT_APPLICATION_DATA;
wb = &bufs[0];
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1
- ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
SSL3_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
*wpinited = 1;
if (!WPACKET_allocate_bytes(&pkt[0], align, NULL)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return tls_initialise_write_packets_default(rl, templates, numtempl,
NULL,
pkt + prefix, bufs + prefix,
wpinited);
}
/* TLSv1.0, TLSv1.1 and TLSv1.2 all use the same funcs */
struct record_functions_st tls_1_funcs = {
tls1_set_crypto_state,
@ -553,7 +652,9 @@ struct record_functions_st tls_1_funcs = {
tls_default_validate_record_header,
tls_default_post_process_record,
tls_get_max_records_multiblock,
tls_write_records_multiblock /* Defined in tls_multib.c */
tls_write_records_multiblock, /* Defined in tls_multib.c */
tls1_allocate_write_buffers,
tls1_initialise_write_packets
};
struct record_functions_st dtls_1_funcs = {
@ -566,5 +667,7 @@ struct record_functions_st dtls_1_funcs = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};

View File

@ -13,6 +13,7 @@
#include <openssl/err.h>
#include <openssl/core_names.h>
#include <openssl/comp.h>
#include <openssl/ssl.h>
#include "internal/e_os.h"
#include "internal/packet.h"
#include "../../ssl_local.h"
@ -115,28 +116,6 @@ static void tls_release_write_buffer_int(OSSL_RECORD_LAYER *rl, size_t start)
}
}
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
# ifndef OPENSSL_NO_COMP
# define MAX_PREFIX_LEN ((SSL3_ALIGN_PAYLOAD - 1) \
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \
+ SSL3_RT_HEADER_LENGTH \
+ SSL3_RT_MAX_COMPRESSED_OVERHEAD)
# else
# define MAX_PREFIX_LEN ((SSL3_ALIGN_PAYLOAD - 1) \
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \
+ SSL3_RT_HEADER_LENGTH)
# endif /* OPENSSL_NO_COMP */
#else
# ifndef OPENSSL_NO_COMP
# define MAX_PREFIX_LEN (SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \
+ SSL3_RT_HEADER_LENGTH \
+ SSL3_RT_MAX_COMPRESSED_OVERHEAD)
# else
# define MAX_PREFIX_LEN (SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \
+ SSL3_RT_HEADER_LENGTH)
# endif /* OPENSSL_NO_COMP */
#endif
int tls_setup_write_buffer(OSSL_RECORD_LAYER *rl, size_t numwpipes,
size_t firstlen, size_t nextlen)
{
@ -1479,7 +1458,7 @@ size_t tls_get_max_records_default(OSSL_RECORD_LAYER *rl, int type, size_t len,
* it, then return the preferred number of pipelines.
*/
if (rl->max_pipelines > 0
&& rl->enc_ctx!= NULL
&& rl->enc_ctx != NULL
&& (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(rl->enc_ctx))
& EVP_CIPH_FLAG_PIPELINE) != 0
&& RLAYER_USE_EXPLICIT_IV(rl)) {
@ -1501,6 +1480,59 @@ size_t tls_get_max_records(OSSL_RECORD_LAYER *rl, int type, size_t len,
return rl->funcs->get_max_records(rl, type, len, maxfrag, preffrag);
}
int tls_allocate_write_buffers_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl,
size_t *prefix)
{
if (!tls_setup_write_buffer(rl, numtempl, 0, 0)) {
/* RLAYERfatal() already called */
return 0;
}
return 1;
}
int tls_initialise_write_packets_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl,
OSSL_RECORD_TEMPLATE *prefixtempl,
WPACKET *pkt,
SSL3_BUFFER *bufs,
size_t *wpinited)
{
WPACKET *thispkt;
size_t j, align;
SSL3_BUFFER *wb;
for (j = 0; j < numtempl; j++) {
thispkt = &pkt[j];
wb = &bufs[j];
wb->type = templates[j].type;
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1
- ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
SSL3_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(thispkt, SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
(*wpinited)++;
if (!WPACKET_allocate_bytes(thispkt, align, NULL)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
int tls_write_records_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl)
@ -1511,15 +1543,12 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
SSL3_RECORD *thiswr;
unsigned char *recordstart;
int mac_size = 0, ret = 0;
size_t align = 0;
SSL3_BUFFER *wb;
size_t len, wpinited = 0;
size_t j, prefix = 0;
int using_ktls;
OSSL_RECORD_TEMPLATE prefixtempl;
OSSL_RECORD_TEMPLATE *thistempl;
if (rl->md_ctx != NULL && EVP_MD_CTX_get0_md(rl->md_ctx) != NULL) {
mac_size = EVP_MD_CTX_get_size(rl->md_ctx);
if (mac_size < 0) {
@ -1528,16 +1557,14 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
}
}
/* Do we need to add an empty record prefix? */
prefix = rl->need_empty_fragments
&& templates[0].type == SSL3_RT_APPLICATION_DATA;
if (!rl->funcs->allocate_write_buffers(rl, templates, numtempl, &prefix)) {
/* RLAYERfatal() already called */
goto err;
}
/*
* In the prefix case we can allocate a much smaller buffer. Otherwise we
* just allocate the default buffer size
*/
if (!tls_setup_write_buffer(rl, numtempl + prefix,
prefix ? MAX_PREFIX_LEN : 0, 0)) {
if (!rl->funcs->initialise_write_packets(rl, templates, numtempl,
&prefixtempl, pkt, rl->wbuf,
&wpinited)) {
/* RLAYERfatal() already called */
goto err;
}
@ -1548,65 +1575,6 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
goto err;
}
if (prefix) {
/*
* countermeasure against known-IV weakness in CBC ciphersuites (see
* http://www.openssl.org/~bodo/tls-cbc.txt)
*/
prefixtempl.buf = NULL;
prefixtempl.version = templates[0].version;
prefixtempl.buflen = 0;
prefixtempl.type = SSL3_RT_APPLICATION_DATA;
wpinited = 1;
wb = &rl->wbuf[0];
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1
- ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
SSL3_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(&pkt[0], align, NULL)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
wpinited = 1;
}
for (j = 0; j < numtempl; j++) {
thispkt = &pkt[prefix + j];
wb = &rl->wbuf[prefix + j];
wb->type = templates[j].type;
if (using_ktls) {
/*
* ktls doesn't modify the buffer, but to avoid a warning we need
* to discard the const qualifier.
* This doesn't leak memory because the buffers have been
* released when switching to ktls.
*/
SSL3_BUFFER_set_buf(wb, (unsigned char *)templates[j].buf);
SSL3_BUFFER_set_offset(wb, 0);
SSL3_BUFFER_set_app_buffer(wb, 1);
} else {
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
align = (size_t)SSL3_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1
- ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
SSL3_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(thispkt, SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(thispkt, align, NULL)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
wpinited++;
}
}
/* Clear our SSL3_RECORD structures */
memset(wr, 0, sizeof(wr));
for (j = 0; j < numtempl + prefix; j++) {
@ -1616,8 +1584,7 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
thispkt = &pkt[j];
thiswr = &wr[j];
thistempl = (j == 0 && prefix == 1) ? &prefixtempl :
&templates[j - prefix];
thistempl = (j < prefix) ? &prefixtempl : &templates[j - prefix];
/*
* In TLSv1.3, once encrypting, we always use application data for the
@ -1796,13 +1763,12 @@ int tls_write_records_default(OSSL_RECORD_LAYER *rl,
}
}
for (j = 0; j < prefix + numtempl; j++) {
for (j = 0; j < numtempl + prefix; j++) {
size_t origlen;
thispkt = &pkt[j];
thiswr = &wr[j];
thistempl = (prefix == 1 && j == 0) ? &prefixtempl
: &templates[j - prefix];
thistempl = (j < prefix) ? &prefixtempl : &templates[j - prefix];
if (using_ktls)
goto mac_done;

View File

@ -144,7 +144,9 @@ struct record_functions_st tls_any_funcs = {
tls_validate_record_header,
tls_default_post_process_record,
tls_get_max_records_default,
tls_write_records_default
tls_write_records_default,
tls_allocate_write_buffers_default,
tls_initialise_write_packets_default
};
static int dtls_any_set_protocol_version(OSSL_RECORD_LAYER *rl, int vers)
@ -166,5 +168,7 @@ struct record_functions_st dtls_any_funcs = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};