From 4e8548e80e12ee73db77417ea159c58751bf4b06 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 5 Jul 2018 14:40:39 +0100 Subject: [PATCH 1/1] Introduce the recv_max_early_data setting Previoulsy we just had max_early_data which controlled both the value of max early_data that we advertise in tickets *and* the amount of early_data that we are willing to receive from clients. This doesn't work too well in the case where we want to reduce a previously advertised max_early_data value. In that case clients with old, stale tickets may attempt to send us more early data than we are willing to receive. Instead of rejecting the early data we abort the connection if that happens. To avoid this we introduce a new "recv_max_early_data" value. The old max_early_data becomes the value that is advertised in tickets while recv_max_early_data is the maximum we will tolerate from clients. Fixes #6647 Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/6655) --- include/openssl/ssl.h | 4 ++++ ssl/record/ssl3_record.c | 11 ++++++++--- ssl/ssl_lib.c | 35 +++++++++++++++++++++++++++++++++++ ssl/ssl_locl.h | 22 ++++++++++++++++++++-- util/libssl.num | 4 ++++ 5 files changed, 71 insertions(+), 5 deletions(-) diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index bbcfb3c0b3..2376828e70 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -919,6 +919,10 @@ int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data); uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx); int SSL_set_max_early_data(SSL *s, uint32_t max_early_data); uint32_t SSL_get_max_early_data(const SSL *s); +int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data); +uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx); +int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data); +uint32_t SSL_get_recv_max_early_data(const SSL *s); #ifdef __cplusplus } diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index ae510b2ec9..ad478bf375 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -103,7 +103,7 @@ static int ssl3_record_app_data_waiting(SSL *s) int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send) { - uint32_t max_early_data = s->max_early_data; + uint32_t max_early_data; SSL_SESSION *sess = s->session; /* @@ -120,9 +120,14 @@ int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send) } sess = s->psksession; } - if (!s->server - || (s->hit && sess->ext.max_early_data < s->max_early_data)) + + if (!s->server) max_early_data = sess->ext.max_early_data; + else if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED) + max_early_data = s->recv_max_early_data; + else + max_early_data = s->recv_max_early_data < sess->ext.max_early_data + ? s->recv_max_early_data : sess->ext.max_early_data; if (max_early_data == 0) { SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 1387067b30..38391fd2c0 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -700,6 +700,7 @@ SSL *SSL_new(SSL_CTX *ctx) s->mode = ctx->mode; s->max_cert_list = ctx->max_cert_list; s->max_early_data = ctx->max_early_data; + s->recv_max_early_data = ctx->recv_max_early_data; s->num_tickets = ctx->num_tickets; /* Shallow copy of the ciphersuites stack */ @@ -3039,6 +3040,16 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) */ ret->max_early_data = 0; + /* + * Default recv_max_early_data is a fully loaded single record. Could be + * split across multiple records in practice. We set this differently to + * max_early_data so that, in the default case, we do not advertise any + * support for early_data, but if a client were to send us some (e.g. + * because of an old, stale ticket) then we will tolerate it and skip over + * it. + */ + ret->recv_max_early_data = SSL3_RT_MAX_PLAIN_LENGTH; + /* By default we send two session tickets automatically in TLSv1.3 */ ret->num_tickets = 2; @@ -5376,6 +5387,30 @@ uint32_t SSL_get_max_early_data(const SSL *s) return s->max_early_data; } +int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data) +{ + ctx->recv_max_early_data = recv_max_early_data; + + return 1; +} + +uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx) +{ + return ctx->recv_max_early_data; +} + +int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data) +{ + s->recv_max_early_data = recv_max_early_data; + + return 1; +} + +uint32_t SSL_get_recv_max_early_data(const SSL *s) +{ + return s->recv_max_early_data; +} + __owur unsigned int ssl_get_max_send_fragment(const SSL *ssl) { /* Return any active Max Fragment Len extension */ diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 6a2edeb190..0bf3f16f35 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1032,9 +1032,18 @@ struct ssl_ctx_st { */ SSL_CTX_keylog_cb_func keylog_callback; - /* The maximum number of bytes that can be sent as early data */ + /* + * The maximum number of bytes advertised in session tickets that can be + * sent as early data. + */ uint32_t max_early_data; + /* + * The maximum number of bytes of early data that a server will tolerate + * (which should be at least as much as max_early_data). + */ + uint32_t recv_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; @@ -1406,8 +1415,17 @@ struct ssl_st { ASYNC_WAIT_CTX *waitctx; size_t asyncrw; - /* The maximum number of plaintext bytes that can be sent as early data */ + /* + * The maximum number of bytes advertised in session tickets that can be + * sent as early data. + */ uint32_t max_early_data; + /* + * The maximum number of bytes of early data that a server will tolerate + * (which should be at least as much as max_early_data). + */ + uint32_t recv_max_early_data; + /* * The number of bytes of early data received so far. If we accepted early * data then this is a count of the plaintext bytes. If we rejected it then diff --git a/util/libssl.num b/util/libssl.num index df6a71e1b5..9b6d266144 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -492,3 +492,7 @@ SSL_get_num_tickets 492 1_1_1 EXIST::FUNCTION: SSL_CTX_set_num_tickets 493 1_1_1 EXIST::FUNCTION: SSL_CTX_set_allow_early_data_cb 494 1_1_1 EXIST::FUNCTION: SSL_set_allow_early_data_cb 495 1_1_1 EXIST::FUNCTION: +SSL_set_recv_max_early_data 496 1_1_1 EXIST::FUNCTION: +SSL_get_recv_max_early_data 497 1_1_1 EXIST::FUNCTION: +SSL_CTX_get_recv_max_early_data 498 1_1_1 EXIST::FUNCTION: +SSL_CTX_set_recv_max_early_data 499 1_1_1 EXIST::FUNCTION: -- 2.34.1