mirror of
https://github.com/openssl/openssl.git
synced 2024-11-21 01:15:20 +08:00
Extend TLSv1.3 record layer padding API calls
Added SSL_set_block_padding_ex() and SSL_CTX_set_block_padding_ex() to allow separate padding block size values for handshake messages and application data messages. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/24796)
This commit is contained in:
parent
b544047c99
commit
21dfb97596
@ -227,9 +227,15 @@ deprecated alternative commands below.
|
||||
|
||||
=item B<-record_padding> I<padding>
|
||||
|
||||
Attempts to pad TLSv1.3 records so that they are a multiple of B<padding>
|
||||
in length on send. A B<padding> of 0 or 1 turns off padding. Otherwise,
|
||||
the B<padding> must be >1 or <=16384.
|
||||
Controls use of TLSv1.3 record layer padding. B<padding> is a string of the
|
||||
form "number[,number]" where the (required) first number is the padding block
|
||||
size (in octets) for application data, and the optional second number is the
|
||||
padding block size for handshake and alert messages. If the optional second
|
||||
number is omitted, the same padding will be applied to all messages.
|
||||
|
||||
Padding attempts to pad TLSv1.3 records so that they are a multiple of the set
|
||||
length on send. A value of 0 or 1 turns off padding as relevant. Otherwise, the
|
||||
values must be >1 or <=16384.
|
||||
|
||||
=item B<-debug_broken_protocol>
|
||||
|
||||
@ -359,9 +365,15 @@ operations are permitted.
|
||||
|
||||
=item B<RecordPadding>
|
||||
|
||||
Attempts to pad TLSv1.3 records so that they are a multiple of B<value> in
|
||||
length on send. A B<value> of 0 or 1 turns off padding. Otherwise, the
|
||||
B<value> must be >1 or <=16384.
|
||||
Controls use of TLSv1.3 record layer padding. B<value> is a string of the form
|
||||
"number[,number]" where the (required) first number is the padding block size
|
||||
(in octets) for application data, and the optional second number is the padding
|
||||
block size for handshake and alert messages. If the optional second number is
|
||||
omitted, the same padding will be applied to all messages.
|
||||
|
||||
Padding attempts to pad TLSv1.3 records so that they are a multiple of the set
|
||||
length on send. A value of 0 or 1 turns off padding as relevant. Otherwise, the
|
||||
values must be >1 or <=16384.
|
||||
|
||||
=item B<SignatureAlgorithms>
|
||||
|
||||
|
@ -9,7 +9,9 @@ SSL_set_record_padding_callback_arg,
|
||||
SSL_CTX_get_record_padding_callback_arg,
|
||||
SSL_get_record_padding_callback_arg,
|
||||
SSL_CTX_set_block_padding,
|
||||
SSL_set_block_padding - install callback to specify TLS 1.3 record padding
|
||||
SSL_CTX_set_block_padding_ex,
|
||||
SSL_set_block_padding,
|
||||
SSL_set_block_padding_ex - install callback to specify TLS 1.3 record padding
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
@ -26,6 +28,8 @@ SSL_set_block_padding - install callback to specify TLS 1.3 record padding
|
||||
|
||||
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);
|
||||
int SSL_set_block_padding(SSL *ssl, size_t block_size);
|
||||
int SSL_CTX_set_block_padding_ex(SSL_CTX *ctx, size_t app_block_size, size_t hs_block_size);
|
||||
int SSL_set_block_padding_ex(SSL *ssl, size_t app_block_size, size_t hs_block_size);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
@ -46,6 +50,10 @@ SSL_CTX_set_block_padding() and SSL_set_block_padding() pads the record to a mul
|
||||
of the B<block_size>. A B<block_size> of 0 or 1 disables block padding. The limit of
|
||||
B<block_size> is SSL3_RT_MAX_PLAIN_LENGTH.
|
||||
|
||||
SSL_CTX_set_block_padding_ex() and SSL_set_block_padding_ex() do similarly but
|
||||
allow the caller to separately specify the padding block size to be applied to
|
||||
handshake and application data messages.
|
||||
|
||||
The callback is invoked for every record before encryption.
|
||||
The B<type> parameter is the TLS record type that is being processed; may be
|
||||
one of SSL3_RT_APPLICATION_DATA, SSL3_RT_HANDSHAKE, or SSL3_RT_ALERT.
|
||||
|
@ -2263,6 +2263,8 @@ void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
|
||||
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
|
||||
void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx);
|
||||
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);
|
||||
int SSL_CTX_set_block_padding_ex(SSL_CTX *ctx, size_t app_block_size,
|
||||
size_t hs_block_size);
|
||||
|
||||
int SSL_set_record_padding_callback(SSL *ssl,
|
||||
size_t (*cb) (SSL *ssl, int type,
|
||||
@ -2270,7 +2272,8 @@ int SSL_set_record_padding_callback(SSL *ssl,
|
||||
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg);
|
||||
void *SSL_get_record_padding_callback_arg(const SSL *ssl);
|
||||
int SSL_set_block_padding(SSL *ssl, size_t block_size);
|
||||
|
||||
int SSL_set_block_padding_ex(SSL *ssl, size_t app_block_size,
|
||||
size_t hs_block_size);
|
||||
int SSL_set_num_tickets(SSL *s, size_t num_tickets);
|
||||
size_t SSL_get_num_tickets(const SSL *s);
|
||||
int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
|
||||
|
@ -324,6 +324,7 @@ struct ossl_record_layer_st
|
||||
|
||||
/* TLSv1.3 record padding */
|
||||
size_t block_padding;
|
||||
size_t hs_padding;
|
||||
|
||||
/* Only used by SSLv3 */
|
||||
unsigned char mac_secret[EVP_MAX_MD_SIZE];
|
||||
|
@ -335,22 +335,51 @@ static int tls13_add_record_padding(OSSL_RECORD_LAYER *rl,
|
||||
size_t padding = 0;
|
||||
size_t max_padding = rl->max_frag_len - rlen;
|
||||
|
||||
/*
|
||||
* We might want to change the "else if" below so that
|
||||
* library-added padding can still happen even if there
|
||||
* is an application-layer callback. The reason being
|
||||
* the application may not be aware that the effectivness
|
||||
* of ECH could be damaged if the callback e.g. only
|
||||
* padded application data. However, doing so would be
|
||||
* a change that could break some application that has
|
||||
* a client and server that both know what padding they
|
||||
* like, and that dislike any other padding. That'd need
|
||||
* one of those to have been updated though so the
|
||||
* probability may be low enough that we could change
|
||||
* the "else if" below to just an "if" and pick the
|
||||
* larger of the library and callback's idea of padding.
|
||||
* (Still subject to max_padding though.)
|
||||
*/
|
||||
if (rl->padding != NULL) {
|
||||
padding = rl->padding(rl->cbarg, thistempl->type, rlen);
|
||||
} else if (rl->block_padding > 0) {
|
||||
size_t mask = rl->block_padding - 1;
|
||||
size_t remainder;
|
||||
} else if (rl->block_padding > 0 || rl->hs_padding > 0) {
|
||||
size_t mask, bp = 0, remainder;
|
||||
|
||||
/* optimize for power of 2 */
|
||||
if ((rl->block_padding & mask) == 0)
|
||||
remainder = rlen & mask;
|
||||
else
|
||||
remainder = rlen % rl->block_padding;
|
||||
/* don't want to add a block of padding if we don't have to */
|
||||
if (remainder == 0)
|
||||
padding = 0;
|
||||
else
|
||||
padding = rl->block_padding - remainder;
|
||||
/*
|
||||
* pad handshake or alert messages based on |hs_padding|
|
||||
* but application data based on |block_padding|
|
||||
*/
|
||||
if (thistempl->type == SSL3_RT_HANDSHAKE && rl->hs_padding > 0)
|
||||
bp = rl->hs_padding;
|
||||
else if (thistempl->type == SSL3_RT_ALERT && rl->hs_padding > 0)
|
||||
bp = rl->hs_padding;
|
||||
else if (thistempl->type == SSL3_RT_APPLICATION_DATA
|
||||
&& rl->block_padding > 0)
|
||||
bp = rl->block_padding;
|
||||
if (bp > 0) {
|
||||
mask = bp - 1;
|
||||
/* optimize for power of 2 */
|
||||
if ((bp & mask) == 0)
|
||||
remainder = rlen & mask;
|
||||
else
|
||||
remainder = rlen % bp;
|
||||
/* don't want to add a block of padding if we don't have to */
|
||||
if (remainder == 0)
|
||||
padding = 0;
|
||||
else
|
||||
padding = bp - remainder;
|
||||
}
|
||||
}
|
||||
if (padding > 0) {
|
||||
/* do not allow the record to exceed max plaintext length */
|
||||
|
@ -1218,6 +1218,12 @@ int tls_set_options(OSSL_RECORD_LAYER *rl, const OSSL_PARAM *options)
|
||||
ERR_raise(ERR_LIB_SSL, SSL_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate_const(options,
|
||||
OSSL_LIBSSL_RECORD_LAYER_PARAM_HS_PADDING);
|
||||
if (p != NULL && !OSSL_PARAM_get_size_t(p, &rl->hs_padding)) {
|
||||
ERR_raise(ERR_LIB_SSL, SSL_R_FAILED_TO_GET_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (rl->level == OSSL_RECORD_PROTECTION_LEVEL_APPLICATION) {
|
||||
|
@ -1288,6 +1288,8 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
|
||||
} else {
|
||||
*opts++ = OSSL_PARAM_construct_size_t(OSSL_LIBSSL_RECORD_LAYER_PARAM_BLOCK_PADDING,
|
||||
&s->rlayer.block_padding);
|
||||
*opts++ = OSSL_PARAM_construct_size_t(OSSL_LIBSSL_RECORD_LAYER_PARAM_HS_PADDING,
|
||||
&s->rlayer.hs_padding);
|
||||
}
|
||||
*opts = OSSL_PARAM_construct_end();
|
||||
|
||||
|
@ -113,6 +113,7 @@ typedef struct record_layer_st {
|
||||
size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg);
|
||||
void *record_padding_arg;
|
||||
size_t block_padding;
|
||||
size_t hs_padding;
|
||||
|
||||
/* How many records we have read from the record layer */
|
||||
size_t num_recs;
|
||||
|
@ -649,20 +649,44 @@ static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* |value| input is "<number[,number]>"
|
||||
* where the first number is the padding block size for
|
||||
* application data, and the optional second is the
|
||||
* padding block size for handshake messages
|
||||
*/
|
||||
static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value)
|
||||
{
|
||||
int rv = 0;
|
||||
int block_size = atoi(value);
|
||||
size_t block_padding = 0, hs_padding = 0;
|
||||
char *commap = NULL, *copy = NULL;
|
||||
|
||||
copy = OPENSSL_strdup(value);
|
||||
if (copy == NULL)
|
||||
return 0;
|
||||
commap = strstr(copy, ",");
|
||||
if (commap != NULL) {
|
||||
*commap = '\0';
|
||||
if (*(commap + 1) == '\0') {
|
||||
OPENSSL_free(copy);
|
||||
return 0;
|
||||
}
|
||||
hs_padding = (size_t) atoi(commap + 1);
|
||||
}
|
||||
block_padding = (size_t) atoi(copy);
|
||||
if (commap == NULL)
|
||||
hs_padding = block_padding;
|
||||
OPENSSL_free(copy);
|
||||
/*
|
||||
* All we care about is a non-negative value,
|
||||
* All we care about are non-negative values,
|
||||
* the setters check the range
|
||||
*/
|
||||
if (block_size >= 0) {
|
||||
if (block_padding >= 0 || hs_padding >= 0) {
|
||||
if (cctx->ctx)
|
||||
rv = SSL_CTX_set_block_padding(cctx->ctx, block_size);
|
||||
rv = SSL_CTX_set_block_padding_ex(cctx->ctx, block_padding,
|
||||
hs_padding);
|
||||
if (cctx->ssl)
|
||||
rv = SSL_set_block_padding(cctx->ssl, block_size);
|
||||
rv = SSL_set_block_padding_ex(cctx->ssl, block_padding, hs_padding);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -785,6 +785,7 @@ SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, const SSL_METHOD *method)
|
||||
s->rlayer.record_padding_cb = ctx->record_padding_cb;
|
||||
s->rlayer.record_padding_arg = ctx->record_padding_arg;
|
||||
s->rlayer.block_padding = ctx->block_padding;
|
||||
s->rlayer.hs_padding = ctx->hs_padding;
|
||||
s->sid_ctx_length = ctx->sid_ctx_length;
|
||||
if (!ossl_assert(s->sid_ctx_length <= sizeof(s->sid_ctx)))
|
||||
goto err;
|
||||
@ -5713,21 +5714,35 @@ void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx)
|
||||
return ctx->record_padding_arg;
|
||||
}
|
||||
|
||||
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size)
|
||||
int SSL_CTX_set_block_padding_ex(SSL_CTX *ctx, size_t app_block_size,
|
||||
size_t hs_block_size)
|
||||
{
|
||||
if (IS_QUIC_CTX(ctx) && block_size > 1)
|
||||
if (IS_QUIC_CTX(ctx) && (app_block_size > 1 || hs_block_size > 1))
|
||||
return 0;
|
||||
|
||||
/* block size of 0 or 1 is basically no padding */
|
||||
if (block_size == 1)
|
||||
if (app_block_size == 1) {
|
||||
ctx->block_padding = 0;
|
||||
else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH)
|
||||
ctx->block_padding = block_size;
|
||||
else
|
||||
} else if (app_block_size <= SSL3_RT_MAX_PLAIN_LENGTH) {
|
||||
ctx->block_padding = app_block_size;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (hs_block_size == 1) {
|
||||
ctx->hs_padding = 0;
|
||||
} else if (hs_block_size <= SSL3_RT_MAX_PLAIN_LENGTH) {
|
||||
ctx->hs_padding = hs_block_size;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size)
|
||||
{
|
||||
return SSL_CTX_set_block_padding_ex(ctx, block_size, block_size);
|
||||
}
|
||||
|
||||
int SSL_set_record_padding_callback(SSL *ssl,
|
||||
size_t (*cb) (SSL *ssl, int type,
|
||||
size_t len, void *arg))
|
||||
@ -5766,23 +5781,39 @@ void *SSL_get_record_padding_callback_arg(const SSL *ssl)
|
||||
return sc->rlayer.record_padding_arg;
|
||||
}
|
||||
|
||||
int SSL_set_block_padding(SSL *ssl, size_t block_size)
|
||||
int SSL_set_block_padding_ex(SSL *ssl, size_t app_block_size,
|
||||
size_t hs_block_size)
|
||||
{
|
||||
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
|
||||
|
||||
if (sc == NULL || (IS_QUIC(ssl) && block_size > 1))
|
||||
if (sc == NULL
|
||||
|| (IS_QUIC(ssl)
|
||||
&& (app_block_size > 1 || hs_block_size > 1)))
|
||||
return 0;
|
||||
|
||||
/* block size of 0 or 1 is basically no padding */
|
||||
if (block_size == 1)
|
||||
if (app_block_size == 1) {
|
||||
sc->rlayer.block_padding = 0;
|
||||
else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH)
|
||||
sc->rlayer.block_padding = block_size;
|
||||
else
|
||||
} else if (app_block_size <= SSL3_RT_MAX_PLAIN_LENGTH) {
|
||||
sc->rlayer.block_padding = app_block_size;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (hs_block_size == 1) {
|
||||
sc->rlayer.hs_padding = 0;
|
||||
} else if (hs_block_size <= SSL3_RT_MAX_PLAIN_LENGTH) {
|
||||
sc->rlayer.hs_padding = hs_block_size;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SSL_set_block_padding(SSL *ssl, size_t block_size)
|
||||
{
|
||||
return SSL_set_block_padding_ex(ssl, block_size, block_size);
|
||||
}
|
||||
|
||||
int SSL_set_num_tickets(SSL *s, size_t num_tickets)
|
||||
{
|
||||
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
|
||||
|
@ -1126,6 +1126,7 @@ struct ssl_ctx_st {
|
||||
size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg);
|
||||
void *record_padding_arg;
|
||||
size_t block_padding;
|
||||
size_t hs_padding;
|
||||
|
||||
/* Session ticket appdata */
|
||||
SSL_CTX_generate_session_ticket_fn generate_ticket_cb;
|
||||
|
@ -11104,6 +11104,8 @@ static size_t record_pad_cb(SSL *s, int type, size_t len, void *arg)
|
||||
* Test 1: Record padding callback on the SSL
|
||||
* Test 2: Record block padding on the SSL_CTX
|
||||
* Test 3: Record block padding on the SSL
|
||||
* Test 4: Extended record block padding on the SSL_CTX
|
||||
* Test 5: Extended record block padding on the SSL
|
||||
*/
|
||||
static int test_tls13_record_padding(int idx)
|
||||
{
|
||||
@ -11133,6 +11135,10 @@ static int test_tls13_record_padding(int idx)
|
||||
goto end;
|
||||
if (!TEST_true(SSL_CTX_set_block_padding(cctx, 512)))
|
||||
goto end;
|
||||
} else if (idx == 4) {
|
||||
/* pad only handshake/alert messages */
|
||||
if (!TEST_true(SSL_CTX_set_block_padding_ex(cctx, 0, 512)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
|
||||
@ -11151,6 +11157,16 @@ static int test_tls13_record_padding(int idx)
|
||||
goto end;
|
||||
if (!TEST_true(SSL_set_block_padding(clientssl, 512)))
|
||||
goto end;
|
||||
} else if (idx == 5) {
|
||||
/* Exceeding the max plain length should fail */
|
||||
if (!TEST_false(SSL_set_block_padding_ex(clientssl, 0,
|
||||
SSL3_RT_MAX_PLAIN_LENGTH + 1)))
|
||||
goto end;
|
||||
/* pad server and client handshake only */
|
||||
if (!TEST_true(SSL_set_block_padding_ex(clientssl, 0, 512)))
|
||||
goto end;
|
||||
if (!TEST_true(SSL_set_block_padding_ex(serverssl, 0, 512)))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
|
||||
@ -12637,7 +12653,7 @@ int setup_tests(void)
|
||||
ADD_TEST(test_load_dhfile);
|
||||
#ifndef OSSL_NO_USABLE_TLS1_3
|
||||
ADD_TEST(test_read_ahead_key_change);
|
||||
ADD_ALL_TESTS(test_tls13_record_padding, 4);
|
||||
ADD_ALL_TESTS(test_tls13_record_padding, 6);
|
||||
#endif
|
||||
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3)
|
||||
ADD_ALL_TESTS(test_serverinfo_custom, 4);
|
||||
|
@ -584,3 +584,5 @@ SSL_poll 584 3_3_0 EXIST::FUNCTION:
|
||||
SSL_SESSION_get_time_ex 585 3_3_0 EXIST::FUNCTION:
|
||||
SSL_SESSION_set_time_ex 586 3_3_0 EXIST::FUNCTION:
|
||||
SSL_CTX_flush_sessions_ex 587 3_4_0 EXIST::FUNCTION:
|
||||
SSL_CTX_set_block_padding_ex ? 3_4_0 EXIST::FUNCTION:
|
||||
SSL_set_block_padding_ex ? 3_4_0 EXIST::FUNCTION:
|
||||
|
@ -506,6 +506,7 @@ my %params = (
|
||||
'LIBSSL_RECORD_LAYER_PARAM_MAX_FRAG_LEN' => "max_frag_len",
|
||||
'LIBSSL_RECORD_LAYER_PARAM_MAX_EARLY_DATA' => "max_early_data",
|
||||
'LIBSSL_RECORD_LAYER_PARAM_BLOCK_PADDING' => "block_padding",
|
||||
'LIBSSL_RECORD_LAYER_PARAM_HS_PADDING' => "hs_padding",
|
||||
);
|
||||
|
||||
# Generate string based macros for public consumption
|
||||
|
Loading…
Reference in New Issue
Block a user