提交 c649d10d 编写于 作者: T Todd Short 提交者: Matt Caswell

TLS1.3 Padding

Add padding callback for application control
Standard block_size callback
Documentation and tests included
Configuration file/s_client/s_srver option
Reviewed-by: NTim Hudson <tjh@openssl.org>
Reviewed-by: NMatt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3130)
上级 20ee2bf1
......@@ -214,7 +214,7 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_LEGACYCONN, \
OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_STRICT, OPT_S_SIGALGS, \
OPT_S_CLIENTSIGALGS, OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, \
OPT_S_DHPARAM, OPT_S_DEBUGBROKE, OPT_S_COMP, \
OPT_S_DHPARAM, OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \
OPT_S__LAST
# define OPT_S_OPTIONS \
......@@ -251,9 +251,12 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
{"cipher", OPT_S_CIPHER, 's', "Specify cipher list to be used"}, \
{"dhparam", OPT_S_DHPARAM, '<', \
"DH parameter file to use, in cert file if not specified"}, \
{"record_padding", OPT_S_RECORD_PADDING, 's', \
"Block size to pad TLS 1.3 records to."}, \
{"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \
"Perform all sorts of protocol violations for testing purposes"}
# define OPT_S_CASES \
OPT_S__FIRST: case OPT_S__LAST: break; \
case OPT_S_NOSSL3: \
......@@ -277,6 +280,7 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
case OPT_S_NAMEDCURVE: \
case OPT_S_CIPHER: \
case OPT_S_DHPARAM: \
case OPT_S_RECORD_PADDING: \
case OPT_S_DEBUGBROKE
#define IS_NO_PROT_FLAG(o) \
......
......@@ -110,6 +110,12 @@ Attempts to use the file B<value> as the set of temporary DH parameters for
the appropriate context. This option is only supported if certificate
operations are permitted.
=item B<-record_padding>
Attempts to pad TLS 1.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.
=item B<-min_protocol>, B<-max_protocol>
Sets the minimum and maximum supported protocol.
......@@ -236,6 +242,12 @@ Attempts to use the file B<value> as the set of temporary DH parameters for
the appropriate context. This option is only supported if certificate
operations are permitted.
=item B<RecordPadding>
Attempts to pad TLS 1.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.
=item B<SignatureAlgorithms>
This sets the supported signature algorithms for TLS v1.2. For clients this
......
=pod
=head1 NAME
SSL_CTX_set_record_padding_callback,
SSL_set_record_padding_callback,
SSL_CTX_set_record_padding_callback_arg,
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
=head1 SYNOPSIS
#include <openssl/ssl.h>
void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx, size_t (*cb)(SSL *s, int type, size_t len, void *arg));
void SSL_set_record_padding_callback(SSL *ssl, size_t (*cb)(SSL *s, int type, size_t len, void *arg));
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
void *SSL_CTX_get_record_padding_callback_arg(SSL_CTX *ctx);
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg);
void *SSL_get_record_padding_callback_arg(SSL *ssl);
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);
int SSL_set_block_padding(SSL *ssl, size_t block_size);
=head1 DESCRIPTION
SSL_CTX_set_record_padding_callback() or SSL_set_record_padding_callback()
can be used to assign a callback function I<cb> to specify the padding
for TLS 1.3 records. The value set in B<ctx> is copied to a new SSL by SSL_new().
SSL_CTX_set_record_padding_callback_arg() and SSL_set_record_padding_callback_arg()
assign a value B<arg> that is passed to the callback when it is invoked. The value
set in B<ctx> is copied to a new SSL by SSL_new().
SSL_CTX_get_record_padding_callback_arg() and SSL_get_record_padding_callback_arg()
retrieve the B<arg> value that is passed to the callback.
SSL_CTX_set_block_padding() and SSL_set_block_padding() pads the record to a multiple
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.
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.
The B<len> parameter is the current plaintext length of the record before encryption.
The B<arg> parameter is the value set via SSL_CTX_set_record_padding_callback_arg()
or SSL_set_record_padding_callback_arg().
=head1 RETURN VALUES
The SSL_CTX_get_record_padding_callback_arg() and SSL_get_record_padding_callback_arg()
functions return the B<arg> value assignd in the corresponding set functions.
The SSL_CTX_set_block_padding() and SSL_set_block_padding() functions return 1 on success
or 0 if B<block_size> is too large.
The B<cb> returns the number of padding bytes to add to the record. A return of 0
indicates no padding will be added. A return value that causes the record to
exceed the maximum record size (SSL3_RT_MAX_PLAIN_LENGTH) will pad out to the
maximum record size.
=head1 NOTES
The default behavior is to add no padding to the record.
A user-supplied padding callback function will override the behavior set by
SSL_set_block_padding() or SSL_CTX_set_block_padding(). Setting the user-supplied
callback to NULL will restore the configured block padding behavior.
These functions only apply to TLS 1.3 records being written.
Padding bytes are not added in constant-time.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_new(3)>
=head1 HISTORY
The record padding API was added for TLS 1.3 support in OpenSSL 1.1.1.
=head1 COPYRIGHT
Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (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
L<https://www.openssl.org/source/license.html>.
=cut
......@@ -1952,6 +1952,21 @@ void SSL_set_not_resumable_session_callback(SSL *ssl,
int (*cb) (SSL *ssl,
int
is_forward_secure));
void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
size_t (*cb) (SSL *ssl, int type,
size_t len, void *arg));
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
void *SSL_CTX_get_record_padding_callback_arg(SSL_CTX *ctx);
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);
void SSL_set_record_padding_callback(SSL *ssl,
size_t (*cb) (SSL *ssl, int type,
size_t len, void *arg));
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg);
void *SSL_get_record_padding_callback_arg(SSL *ssl);
int SSL_set_block_padding(SSL *ssl, size_t block_size);
# if OPENSSL_API_COMPAT < 0x10100000L
# define SSL_cache_hit(s) SSL_session_reused(s)
# endif
......
......@@ -350,6 +350,21 @@ int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
return 1;
}
int WPACKET_memset(WPACKET *pkt, int ch, size_t len)
{
unsigned char *dest;
if (len == 0)
return 1;
if (!WPACKET_allocate_bytes(pkt, len, &dest))
return 0;
memset(dest, ch, len);
return 1;
}
int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
{
unsigned char *dest;
......
......@@ -833,6 +833,9 @@ int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize);
/* Copy |len| bytes of data from |*src| into the WPACKET. */
int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len);
/* Set |len| bytes of data to |ch| into the WPACKET. */
int WPACKET_memset(WPACKET *pkt, int ch, size_t len);
/*
* Copy |len| bytes of data from |*src| into the WPACKET and prefix with its
* length (consuming |lenbytes| of data for the length). Don't call this
......
......@@ -860,15 +860,44 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
}
if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) {
size_t padding = 0;
if (!WPACKET_put_bytes_u8(thispkt, type)) {
SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
goto err;
}
SSL3_RECORD_add_length(thiswr, 1);
/*
* TODO(TLS1.3): Padding goes here. Do we need an API to add this?
* For now, use no padding
*/
/* Add TLS1.3 padding */
if (s->record_padding_cb != NULL) {
size_t rlen = SSL3_RECORD_get_length(thiswr);
padding = s->record_padding_cb(s, type, rlen, s->record_padding_arg);
/* do not allow the record to exceed max plaintext length */
if (padding > (SSL3_RT_MAX_PLAIN_LENGTH - rlen))
padding = SSL3_RT_MAX_PLAIN_LENGTH - rlen;
} else if (s->block_padding > 0) {
size_t mask = s->block_padding - 1;
size_t remainder;
/* optimize for power of 2 */
if ((s->block_padding & mask) == 0)
remainder = SSL3_RECORD_get_length(thiswr) & mask;
else
remainder = SSL3_RECORD_get_length(thiswr) % s->block_padding;
/* don't want to add a block of padding if we don't have to */
if (remainder == 0)
padding = 0;
else
padding = s->block_padding - remainder;
}
if (padding > 0) {
if (!WPACKET_memset(thispkt, 0, padding)) {
SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
goto err;
}
SSL3_RECORD_add_length(thiswr, padding);
}
}
/*
......
......@@ -520,6 +520,25 @@ static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
return rv > 0;
}
#endif
static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value)
{
int rv = 0;
int block_size = atoi(value);
/*
* All we care about is a non-negative value,
* the setters check the range
*/
if (block_size >= 0) {
if (cctx->ctx)
rv = SSL_CTX_set_block_padding(cctx->ctx, block_size);
if (cctx->ssl)
rv = SSL_set_block_padding(cctx->ssl, block_size);
}
return rv;
}
typedef struct {
int (*cmd) (SSL_CONF_CTX *cctx, const char *value);
const char *str_file;
......@@ -598,8 +617,9 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
#ifndef OPENSSL_NO_DH
SSL_CONF_CMD(DHParameters, "dhparam",
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE)
SSL_CONF_TYPE_FILE),
#endif
SSL_CONF_CMD_STRING(RecordPadding, "record_padding", 0)
};
/* Supported switches: must match order of switches in ssl_conf_cmds */
......
......@@ -571,6 +571,9 @@ SSL *SSL_new(SSL_CTX *ctx)
s->msg_callback_arg = ctx->msg_callback_arg;
s->verify_mode = ctx->verify_mode;
s->not_resumable_session_cb = ctx->not_resumable_session_cb;
s->record_padding_cb = ctx->record_padding_cb;
s->record_padding_arg = ctx->record_padding_arg;
s->block_padding = ctx->block_padding;
s->sid_ctx_length = ctx->sid_ctx_length;
OPENSSL_assert(s->sid_ctx_length <= sizeof s->sid_ctx);
memcpy(&s->sid_ctx, &ctx->sid_ctx, sizeof(s->sid_ctx));
......@@ -3889,6 +3892,64 @@ void SSL_set_not_resumable_session_callback(SSL *ssl,
(void (*)(void))cb);
}
void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
size_t (*cb) (SSL *ssl, int type,
size_t len, void *arg))
{
ctx->record_padding_cb = cb;
}
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg)
{
ctx->record_padding_arg = arg;
}
void *SSL_CTX_get_record_padding_callback_arg(SSL_CTX *ctx)
{
return ctx->record_padding_arg;
}
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size)
{
/* block size of 0 or 1 is basically no padding */
if (block_size == 1)
ctx->block_padding = 0;
else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH)
ctx->block_padding = block_size;
else
return 0;
return 1;
}
void SSL_set_record_padding_callback(SSL *ssl,
size_t (*cb) (SSL *ssl, int type,
size_t len, void *arg))
{
ssl->record_padding_cb = cb;
}
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg)
{
ssl->record_padding_arg = arg;
}
void *SSL_get_record_padding_callback_arg(SSL *ssl)
{
return ssl->record_padding_arg;
}
int SSL_set_block_padding(SSL *ssl, size_t block_size)
{
/* block size of 0 or 1 is basically no padding */
if (block_size == 1)
ssl->block_padding = 0;
else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH)
ssl->block_padding = block_size;
else
return 0;
return 1;
}
/*
* Allocates new EVP_MD_CTX and sets pointer to it into given pointer
* variable, freeing EVP_MD_CTX previously stored in that variable, if any.
......
......@@ -973,6 +973,11 @@ struct ssl_ctx_st {
/* The maximum number of bytes that can be sent as early data */
uint32_t max_early_data;
/* TLS1.3 padding callback */
size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg);
void *record_padding_arg;
size_t block_padding;
};
struct ssl_st {
......@@ -1289,6 +1294,11 @@ struct ssl_st {
*/
uint32_t early_data_count;
/* TLS1.3 padding callback */
size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg);
void *record_padding_arg;
size_t block_padding;
CRYPTO_RWLOCK *lock;
};
......
......@@ -29,7 +29,7 @@ map { s/\^// } @conf_files if $^O eq "VMS";
# We hard-code the number of tests to double-check that the globbing above
# finds all files as expected.
plan tests => 23; # = scalar @conf_srcs
plan tests => 24; # = scalar @conf_srcs
# Some test results depend on the configuration of enabled protocols. We only
# verify generated sources in the default configuration.
......@@ -94,6 +94,7 @@ my %skip = (
"22-compression.conf" => disabled("zlib") || $no_tls,
"23-srp.conf" => (disabled("tls1") && disabled ("tls1_1")
&& disabled("tls1_2")) || disabled("srp"),
"24-padding.conf" => disabled("tls1_3"),
);
foreach my $conf (@conf_files) {
......
# Generated with generate_ssl_tests.pl
num_tests = 1
test-0 = 0-default
# ===========================================================
[0-default]
ssl_conf = 0-default-ssl
[0-default-ssl]
server = 0-default-server
client = 0-default-client
[0-default-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
MaxProtocol = TLSv1.3
MinProtocol = TLSv1.3
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
RecordPadding = 64
[0-default-client]
CipherString = DEFAULT
MaxProtocol = TLSv1.3
MinProtocol = TLSv1.3
RecordPadding = 11
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-0]
ExpectedResult = Success
# -*- mode: perl; -*-
# Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (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
## SSL test configurations
package ssltests;
our @tests = (
{
name => "default",
server => { "RecordPadding" => 64,
"MaxProtocol" => "TLSv1.3",
"MinProtocol" => "TLSv1.3" },
client => { "RecordPadding" => 11,
"MaxProtocol" => "TLSv1.3",
"MinProtocol" => "TLSv1.3" },
test => { "ExpectedResult" => "Success" },
},
);
......@@ -441,3 +441,11 @@ SSL_CTX_add1_CA_list 441 1_1_1 EXIST::FUNCTION:
SSL_CTX_get0_CA_list 442 1_1_1 EXIST::FUNCTION:
SSL_CTX_add_custom_ext 443 1_1_1 EXIST::FUNCTION:
SSL_SESSION_is_resumable 444 1_1_1 EXIST::FUNCTION:
SSL_CTX_set_record_padding_callback 445 1_1_1 EXIST::FUNCTION:
SSL_set_record_padding_callback 446 1_1_1 EXIST::FUNCTION:
SSL_CTX_set_block_padding 447 1_1_1 EXIST::FUNCTION:
SSL_CTX_get_record_padding_callback_arg 448 1_1_1 EXIST::FUNCTION:
SSL_get_record_padding_callback_arg 449 1_1_1 EXIST::FUNCTION:
SSL_set_block_padding 450 1_1_1 EXIST::FUNCTION:
SSL_set_record_padding_callback_arg 451 1_1_1 EXIST::FUNCTION:
SSL_CTX_set_record_padding_callback_arg 452 1_1_1 EXIST::FUNCTION:
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册