diff options
author | Todd Short <tshort@akamai.com> | 2017-04-05 12:35:25 -0400 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2017-05-02 09:44:43 +0100 |
commit | c649d10d3fee9fe22e4ae6bdf7f8117b91b92b03 (patch) | |
tree | e72effbded8ac2531b21ead7c2d95ee26d1652cc /ssl | |
parent | 20ee2bf138323c6688b6e8d71d695cf2bd53f857 (diff) | |
download | openssl-c649d10d3fee9fe22e4ae6bdf7f8117b91b92b03.tar.gz |
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.c | 15 | ||||
-rw-r--r-- | ssl/packet_locl.h | 3 | ||||
-rw-r--r-- | ssl/record/rec_layer_s3.c | 37 | ||||
-rw-r--r-- | ssl/ssl_conf.c | 22 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 61 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 10 |
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; }; |