summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorTodd Short <tshort@akamai.com>2017-04-05 12:35:25 -0400
committerMatt Caswell <matt@openssl.org>2017-05-02 09:44:43 +0100
commitc649d10d3fee9fe22e4ae6bdf7f8117b91b92b03 (patch)
treee72effbded8ac2531b21ead7c2d95ee26d1652cc /ssl
parent20ee2bf138323c6688b6e8d71d695cf2bd53f857 (diff)
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: Tim Hudson <tjh@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/3130)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/packet.c15
-rw-r--r--ssl/packet_locl.h3
-rw-r--r--ssl/record/rec_layer_s3.c37
-rw-r--r--ssl/ssl_conf.c22
-rw-r--r--ssl/ssl_lib.c61
-rw-r--r--ssl/ssl_locl.h10
6 files changed, 143 insertions, 5 deletions
diff --git a/ssl/packet.c b/ssl/packet.c
index 3479f1fed8..d081f557e7 100644
--- a/ssl/packet.c
+++ b/ssl/packet.c
@@ -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;
diff --git a/ssl/packet_locl.h b/ssl/packet_locl.h
index 67b49994f7..8e553e62b5 100644
--- a/ssl/packet_locl.h
+++ b/ssl/packet_locl.h
@@ -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
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index 14c6778ae6..43c4a949d7 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -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);
+ }
}
/*
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
index 4b4619279e..484bb61feb 100644
--- a/ssl/ssl_conf.c
+++ b/ssl/ssl_conf.c
@@ -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 */
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index c59aa847e4..d1a1f027d9 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -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.
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 15065c7d98..1d3a207c78 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -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;
};