提交 bafe524b 编写于 作者: M Matt Caswell

Restructure the write code

Move the multiblock code into a separate file and introduce the usage of
record_functions_st for some write functions.
Reviewed-by: NHugo Landau <hlandau@openssl.org>
Reviewed-by: NRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19198)
上级 4fed6ee1
......@@ -5,7 +5,7 @@ ENDIF
SOURCE[../../../libssl]=\
tls_common.c ssl3_meth.c tls1_meth.c tls13_meth.c tlsany_meth.c \
dtls_meth.c $KTLSSRC
dtls_meth.c tls_multib.c $KTLSSRC
# For shared builds we need to include the sources needed in providers
# (ssl3_cbc.c) in libssl as well.
......
......@@ -481,13 +481,15 @@ static int ktls_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
static struct record_functions_st ossl_ktls_funcs = {
ktls_set_crypto_state,
ktls_read_n,
tls_get_more_records,
ktls_cipher,
NULL,
tls_default_set_protocol_version,
ktls_read_n,
tls_get_more_records,
ktls_validate_record_header,
ktls_post_process_record
ktls_post_process_record,
tls_get_max_records_default,
tls_write_records_default
};
static int
......
......@@ -38,11 +38,6 @@ struct record_functions_st
const EVP_MD *md,
const SSL_COMP *comp);
int (*read_n)(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
int clearold, size_t *readbytes);
int (*get_more_records)(OSSL_RECORD_LAYER *rl);
/*
* Returns:
* 0: if the record is publicly invalid, or an internal error, or AEAD
......@@ -58,11 +53,27 @@ struct record_functions_st
/* Return 1 for success or 0 for error */
int (*set_protocol_version)(OSSL_RECORD_LAYER *rl, int version);
/* Read related functions */
int (*read_n)(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
int clearold, size_t *readbytes);
int (*get_more_records)(OSSL_RECORD_LAYER *rl);
/* Return 1 for success or 0 for error */
int (*validate_record_header)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec);
/* Return 1 for success or 0 for error */
int (*post_process_record)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec);
/* Write related functions */
size_t (*get_max_records)(OSSL_RECORD_LAYER *rl, int type, size_t len,
size_t maxfrag, size_t *preffrag);
/* Return 1 for success or 0 for error */
int (*write_records)(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates,
size_t numtempl);
};
struct ossl_record_layer_st
......@@ -314,3 +325,18 @@ void tls_get_state(OSSL_RECORD_LAYER *rl, const char **shortstr,
const char **longstr);
int tls_set_options(OSSL_RECORD_LAYER *rl, const OSSL_PARAM *options);
int tls_setup_read_buffer(OSSL_RECORD_LAYER *rl);
int tls_setup_write_buffer(OSSL_RECORD_LAYER *rl, size_t numwpipes,
size_t firstlen, size_t nextlen);
int tls_write_records_multiblock(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl);
size_t tls_get_max_records_default(OSSL_RECORD_LAYER *rl, int type, size_t len,
size_t maxfrag, size_t *preffrag);
size_t tls_get_max_records_multiblock(OSSL_RECORD_LAYER *rl, int type,
size_t len, size_t maxfrag,
size_t *preffrag);
int tls_write_records_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl);
......@@ -295,11 +295,13 @@ static int ssl3_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
struct record_functions_st ssl_3_0_funcs = {
ssl3_set_crypto_state,
tls_default_read_n,
tls_get_more_records,
ssl3_cipher,
ssl3_mac,
tls_default_set_protocol_version,
tls_default_read_n,
tls_get_more_records,
tls_default_validate_record_header,
tls_default_post_process_record
tls_default_post_process_record,
tls_get_max_records_default,
tls_write_records_default
};
......@@ -240,11 +240,13 @@ static int tls13_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
struct record_functions_st tls_1_3_funcs = {
tls13_set_crypto_state,
tls_default_read_n,
tls_get_more_records,
tls13_cipher,
NULL,
tls_default_set_protocol_version,
tls_default_read_n,
tls_get_more_records,
tls13_validate_record_header,
tls13_post_process_record
tls13_post_process_record,
tls_get_max_records_default,
tls_write_records_default
};
......@@ -522,22 +522,26 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
/* TLSv1.0, TLSv1.1 and TLSv1.2 all use the same funcs */
struct record_functions_st tls_1_funcs = {
tls1_set_crypto_state,
tls_default_read_n,
tls_get_more_records,
tls1_cipher,
tls1_mac,
tls_default_set_protocol_version,
tls_default_read_n,
tls_get_more_records,
tls_default_validate_record_header,
tls_default_post_process_record
tls_default_post_process_record,
tls_get_max_records_multiblock,
tls_write_records_multiblock /* Defined in tls_multib.c */
};
struct record_functions_st dtls_1_funcs = {
tls1_set_crypto_state,
tls_default_read_n,
dtls_get_more_records,
tls1_cipher,
tls1_mac,
tls_default_set_protocol_version,
tls_default_read_n,
dtls_get_more_records,
NULL,
NULL,
NULL,
NULL
};
......@@ -18,15 +18,6 @@
#include "../record_local.h"
#include "recmethod_local.h"
#if defined(OPENSSL_SMALL_FOOTPRINT) || \
!( defined(AES_ASM) && ( \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) ) \
)
# undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
#endif
static void tls_int_free(OSSL_RECORD_LAYER *rl);
void ossl_rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason,
......@@ -145,8 +136,8 @@ static void tls_release_write_buffer_int(OSSL_RECORD_LAYER *rl, size_t start)
# endif /* OPENSSL_NO_COMP */
#endif
static int tls_setup_write_buffer(OSSL_RECORD_LAYER *rl, size_t numwpipes,
size_t firstlen, size_t nextlen)
int tls_setup_write_buffer(OSSL_RECORD_LAYER *rl, size_t numwpipes,
size_t firstlen, size_t nextlen)
{
unsigned char *p;
size_t align = 0, headerlen;
......@@ -1453,44 +1444,12 @@ size_t tls_get_max_record_len(OSSL_RECORD_LAYER *rl)
return 0;
}
static int tls_is_multiblock_capable(OSSL_RECORD_LAYER *rl, int type,
size_t len, size_t fraglen)
{
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
/* TODO(RECLAYER): REMOVE ME */
SSL_CONNECTION *s = rl->cbarg;
if (type == SSL3_RT_APPLICATION_DATA
&& len >= 4 * fraglen
&& s->compress == NULL
&& rl->msg_callback == NULL
&& !rl->use_etm
&& RLAYER_USE_EXPLICIT_IV(rl)
&& !BIO_get_ktls_send(s->wbio)
&& (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx))
& EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) != 0)
return 1;
#endif
return 0;
}
size_t tls_get_max_records(OSSL_RECORD_LAYER *rl, int type, size_t len,
size_t maxfrag, size_t *preffrag)
size_t tls_get_max_records_default(OSSL_RECORD_LAYER *rl, int type, size_t len,
size_t maxfrag, size_t *preffrag)
{
/* TODO(RECLAYER): Remove me */
SSL_CONNECTION *s = rl->cbarg;
if (tls_is_multiblock_capable(rl, type, len, *preffrag)) {
/* minimize address aliasing conflicts */
if ((*preffrag & 0xfff) == 0)
*preffrag -= 512;
if (len >= 8 * (*preffrag))
return 8;
return 4;
}
/*
* TODO(RECLYAER): There is no test for the pipelining code. We should add
* one.
......@@ -1516,114 +1475,15 @@ size_t tls_get_max_records(OSSL_RECORD_LAYER *rl, int type, size_t len,
return 1;
}
static int tls_write_records_multiblock(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl)
size_t tls_get_max_records(OSSL_RECORD_LAYER *rl, int type, size_t len,
size_t maxfrag, size_t *preffrag)
{
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
size_t i;
size_t totlen;
SSL3_BUFFER *wb;
/* TODO(RECLAYER): Remove me */
SSL_CONNECTION *s = rl->cbarg;
if (numtempl != 4 && numtempl != 8)
return 0;
/*
* Check templates have contiguous buffers and are all the same type and
* length
*/
for (i = 1; i < numtempl; i++) {
if (templates[i - 1].type != templates[i].type
|| templates[i - 1].buflen != templates[i].buflen
|| templates[i - 1].buf + templates[i - 1].buflen
!= templates[i].buf)
return 0;
}
totlen = templates[0].buflen * numtempl;
if (!tls_is_multiblock_capable(rl, templates[0].type, totlen,
templates[0].buflen))
return 0;
/*
* If we get this far, then multiblock is suitable
* Depending on platform multi-block can deliver several *times*
* better performance. Downside is that it has to allocate
* jumbo buffer to accommodate up to 8 records, but the
* compromise is considered worthy.
*/
unsigned char aad[13];
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
size_t packlen;
int packleni;
/*
* Allocate jumbo buffer. This will get freed next time we do a non
* multiblock write in the call to tls_setup_write_buffer() - the different
* buffer sizes will be spotted and the buffer reallocated.
*/
packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
(int)templates[0].buflen, NULL);
packlen *= numtempl;
if (!tls_setup_write_buffer(rl, 1, packlen, packlen)) {
/* RLAYERfatal() already called */
return -1;
}
wb = &rl->wbuf[0];
mb_param.interleave = numtempl;
memcpy(aad, s->rlayer.write_sequence, 8);
aad[8] = templates[0].type;
aad[9] = (unsigned char)(templates[0].version >> 8);
aad[10] = (unsigned char)(templates[0].version);
aad[11] = 0;
aad[12] = 0;
mb_param.out = NULL;
mb_param.inp = aad;
mb_param.len = totlen;
packleni = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
sizeof(mb_param), &mb_param);
packlen = (size_t)packleni;
if (packleni <= 0 || packlen > wb->len) { /* never happens */
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
mb_param.out = wb->buf;
mb_param.inp = templates[0].buf;
mb_param.len = totlen;
if (EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
sizeof(mb_param), &mb_param) <= 0) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
s->rlayer.write_sequence[7] += mb_param.interleave;
if (s->rlayer.write_sequence[7] < mb_param.interleave) {
int j = 6;
while (j >= 0 && (++s->rlayer.write_sequence[j--]) == 0) ;
}
wb->offset = 0;
wb->left = packlen;
return 1;
#else /* !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK */
return 0;
#endif
return rl->funcs->get_max_records(rl, type, len, maxfrag, preffrag);
}
static int tls_write_records_standard(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl)
int tls_write_records_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl)
{
WPACKET pkt[SSL_MAX_PIPELINES + 1];
SSL3_RECORD wr[SSL_MAX_PIPELINES + 1];
......@@ -2049,8 +1909,6 @@ static int tls_write_records_standard(OSSL_RECORD_LAYER *rl,
int tls_write_records(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates,
size_t numtempl)
{
int ret;
/* Check we don't have pending data waiting to write */
if (!ossl_assert(rl->nextwbuf >= rl->numwpipes
|| SSL3_BUFFER_get_left(&rl->wbuf[rl->nextwbuf]) == 0)) {
......@@ -2058,18 +1916,10 @@ int tls_write_records(OSSL_RECORD_LAYER *rl, OSSL_RECORD_TEMPLATE *templates,
return OSSL_RECORD_RETURN_FATAL;
}
ret = tls_write_records_multiblock(rl, templates, numtempl);
if (ret < 0) {
if (!rl->funcs->write_records(rl, templates, numtempl)) {
/* RLAYERfatal already called */
return OSSL_RECORD_RETURN_FATAL;
}
if (ret == 0) {
/* Multiblock wasn't suitable so just do a standard write */
if (!tls_write_records_standard(rl, templates, numtempl)) {
/* RLAYERfatal already called */
return OSSL_RECORD_RETURN_FATAL;
}
}
rl->nextwbuf = 0;
/* we now just need to write the buffers */
......
/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "../../ssl_local.h"
#include "../record_local.h"
#include "recmethod_local.h"
#if defined(OPENSSL_SMALL_FOOTPRINT) \
|| !(defined(AES_ASM) && (defined(__x86_64) \
|| defined(__x86_64__) \
|| defined(_M_AMD64) \
|| defined(_M_X64)))
# undef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
#endif
static int tls_is_multiblock_capable(OSSL_RECORD_LAYER *rl, int type,
size_t len, size_t fraglen)
{
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
/* TODO(RECLAYER): REMOVE ME */
SSL_CONNECTION *s = rl->cbarg;
if (type == SSL3_RT_APPLICATION_DATA
&& len >= 4 * fraglen
&& s->compress == NULL
&& rl->msg_callback == NULL
&& !rl->use_etm
&& RLAYER_USE_EXPLICIT_IV(rl)
&& !BIO_get_ktls_send(s->wbio)
&& (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx))
& EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) != 0)
return 1;
#endif
return 0;
}
size_t tls_get_max_records_multiblock(OSSL_RECORD_LAYER *rl, int type,
size_t len, size_t maxfrag,
size_t *preffrag)
{
if (tls_is_multiblock_capable(rl, type, len, *preffrag)) {
/* minimize address aliasing conflicts */
if ((*preffrag & 0xfff) == 0)
*preffrag -= 512;
if (len >= 8 * (*preffrag))
return 8;
return 4;
}
return tls_get_max_records_default(rl, type, len, maxfrag, preffrag);
}
/*
* Write records using the multiblock method.
*
* Returns 1 on success, 0 if multiblock isn't suitable (non-fatal error), or
* -1 on fatal error.
*/
static int tls_write_records_multiblock_int(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl)
{
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
size_t i;
size_t totlen;
SSL3_BUFFER *wb;
/* TODO(RECLAYER): Remove me */
SSL_CONNECTION *s = rl->cbarg;
unsigned char aad[13];
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
size_t packlen;
int packleni;
if (numtempl != 4 && numtempl != 8)
return 0;
/*
* Check templates have contiguous buffers and are all the same type and
* length
*/
for (i = 1; i < numtempl; i++) {
if (templates[i - 1].type != templates[i].type
|| templates[i - 1].buflen != templates[i].buflen
|| templates[i - 1].buf + templates[i - 1].buflen
!= templates[i].buf)
return 0;
}
totlen = templates[0].buflen * numtempl;
if (!tls_is_multiblock_capable(rl, templates[0].type, totlen,
templates[0].buflen))
return 0;
/*
* If we get this far, then multiblock is suitable
* Depending on platform multi-block can deliver several *times*
* better performance. Downside is that it has to allocate
* jumbo buffer to accommodate up to 8 records, but the
* compromise is considered worthy.
*/
/*
* Allocate jumbo buffer. This will get freed next time we do a non
* multiblock write in the call to tls_setup_write_buffer() - the different
* buffer sizes will be spotted and the buffer reallocated.
*/
packlen = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
(int)templates[0].buflen, NULL);
packlen *= numtempl;
if (!tls_setup_write_buffer(rl, 1, packlen, packlen)) {
/* RLAYERfatal() already called */
return -1;
}
wb = &rl->wbuf[0];
mb_param.interleave = numtempl;
memcpy(aad, s->rlayer.write_sequence, 8);
aad[8] = templates[0].type;
aad[9] = (unsigned char)(templates[0].version >> 8);
aad[10] = (unsigned char)(templates[0].version);
aad[11] = 0;
aad[12] = 0;
mb_param.out = NULL;
mb_param.inp = aad;
mb_param.len = totlen;
packleni = EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
sizeof(mb_param), &mb_param);
packlen = (size_t)packleni;
if (packleni <= 0 || packlen > wb->len) { /* never happens */
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
mb_param.out = wb->buf;
mb_param.inp = templates[0].buf;
mb_param.len = totlen;
if (EVP_CIPHER_CTX_ctrl(s->enc_write_ctx,
EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
sizeof(mb_param), &mb_param) <= 0) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
s->rlayer.write_sequence[7] += mb_param.interleave;
if (s->rlayer.write_sequence[7] < mb_param.interleave) {
int j = 6;
while (j >= 0 && (++s->rlayer.write_sequence[j--]) == 0) ;
}
wb->offset = 0;
wb->left = packlen;
return 1;
#else /* !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK */
return 0;
#endif
}
int tls_write_records_multiblock(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl)
{
int ret;
ret = tls_write_records_multiblock_int(rl, templates, numtempl);
if (ret < 0) {
/* RLAYERfatal already called */
return 0;
}
if (ret == 0) {
/* Multiblock wasn't suitable so just do a standard write */
if (!tls_write_records_default(rl, templates, numtempl)) {
/* RLAYERfatal already called */
return 0;
}
}
return 1;
}
......@@ -136,13 +136,15 @@ static int tls_any_set_protocol_version(OSSL_RECORD_LAYER *rl, int vers)
struct record_functions_st tls_any_funcs = {
tls_any_set_crypto_state,
tls_default_read_n,
tls_get_more_records,
tls_any_cipher,
NULL,
tls_any_set_protocol_version,
tls_default_read_n,
tls_get_more_records,
tls_validate_record_header,
tls_default_post_process_record
tls_default_post_process_record,
tls_get_max_records_default,
tls_write_records_default
};
static int dtls_any_set_protocol_version(OSSL_RECORD_LAYER *rl, int vers)
......@@ -156,11 +158,13 @@ static int dtls_any_set_protocol_version(OSSL_RECORD_LAYER *rl, int vers)
struct record_functions_st dtls_any_funcs = {
tls_any_set_crypto_state,
tls_default_read_n,
dtls_get_more_records,
tls_any_cipher,
NULL,
dtls_any_set_protocol_version,
tls_default_read_n,
dtls_get_more_records,
NULL,
NULL,
NULL,
NULL
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册