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 \
{"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: \
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) \
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.
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
--- /dev/null
+=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
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
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;
/* 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
}
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);
+ }
}
/*
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;
#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 */
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));
(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.
/* 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 {
*/
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;
};
# 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.
"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) {
--- /dev/null
+# 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
+
+
--- /dev/null
+# -*- 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" },
+ },
+);
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: