diff options
author | Matt Caswell <matt@openssl.org> | 2018-07-05 14:40:39 +0100 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2018-07-06 09:26:39 +0100 |
commit | 4e8548e80e12ee73db77417ea159c58751bf4b06 (patch) | |
tree | f12810ac428b10649ffa576bbae991b84f86c7fd /ssl | |
parent | 2ddee136ec4157598b0679f9d5a5097ed77c4c01 (diff) |
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 <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/6655)
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/record/ssl3_record.c | 11 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 35 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 22 |
3 files changed, 63 insertions, 5 deletions
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,9 +1415,18 @@ 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 * this is a count of the ciphertext bytes. |