From 0a87d0ac628685a1b420851f1614829a952cda5f Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Mon, 20 Feb 2017 16:35:03 +0000 Subject: Parse the early_data extension We also skip any early_data that subsequently gets sent. Later commits will process it if we can. Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/2737) --- ssl/record/ssl3_record.c | 11 +++++++++++ ssl/ssl_locl.h | 3 +++ ssl/statem/extensions.c | 3 ++- ssl/statem/extensions_srvr.c | 13 +++++++++++++ ssl/statem/statem.c | 12 ++++++++++++ ssl/statem/statem.h | 1 + ssl/statem/statem_locl.h | 2 ++ 7 files changed, 44 insertions(+), 1 deletion(-) diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index 3868bb5..4a1c041 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -424,6 +424,17 @@ int ssl3_get_record(SSL *s) * -1: if the padding is invalid */ if (enc_err == 0) { + if (num_recs == 1 && ossl_statem_skip_early_data(s)) { + /* + * We assume this is unreadable early_data - we treat it like an + * empty record + */ + thisrr = &rr[0]; + thisrr->length = 0; + thisrr->read = 1; + RECORD_LAYER_set_numrpipes(&s->rlayer, 1); + return 1; + } al = SSL_AD_DECRYPTION_FAILED; SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); goto f_err; diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index a168972..2aef000 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1176,6 +1176,9 @@ struct ssl_st { /* Set to one if we have negotiated ETM */ int use_etm; + + /* Set to 1 if we are expecting to receive early data */ + int expect_early_data; } ext; /* Parsed form of the ClientHello, kept around across early_cb calls. */ diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index a2efd0a..ccc60b6 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -138,7 +138,8 @@ static const EXTENSION_DEFINITION ext_defs[] = { { TLSEXT_TYPE_early_data, EXT_CLIENT_HELLO | EXT_TLS1_3_ENCRYPTED_EXTENSIONS, - NULL, NULL, NULL, NULL, tls_construct_ctos_early_data, NULL + NULL, tls_parse_ctos_early_data, NULL, NULL, + tls_construct_ctos_early_data, NULL }, #ifndef OPENSSL_NO_EC { diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index 690cc30..8994ab9 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -162,6 +162,19 @@ int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, } #endif +int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx, int *al) +{ + if (PACKET_remaining(pkt) != 0) { + *al = SSL_AD_DECODE_ERROR; + return 0; + } + + s->ext.expect_early_data = 1; + + return 1; +} + #ifndef OPENSSL_NO_EC int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c index 10d794e..9ec8e85 100644 --- a/ssl/statem/statem.c +++ b/ssl/statem/statem.c @@ -151,6 +151,18 @@ void ossl_statem_set_in_handshake(SSL *s, int inhand) s->statem.in_handshake--; } +/* Are we in a sensible state to skip over unreadable early data? */ +int ossl_statem_skip_early_data(SSL *s) +{ + if (!s->ext.expect_early_data) + return 0; + + if (s->statem.hand_state != TLS_ST_SW_FINISHED) + return 0; + + return 1; +} + void ossl_statem_set_hello_verify_done(SSL *s) { s->statem.state = MSG_FLOW_UNINITED; diff --git a/ssl/statem/statem.h b/ssl/statem/statem.h index 906f2ec..5bb74d0 100644 --- a/ssl/statem/statem.h +++ b/ssl/statem/statem.h @@ -122,6 +122,7 @@ int ossl_statem_in_error(const SSL *s); void ossl_statem_set_in_init(SSL *s, int init); int ossl_statem_get_in_handshake(SSL *s); void ossl_statem_set_in_handshake(SSL *s, int inhand); +__owur int ossl_statem_skip_early_data(SSL *s); void ossl_statem_set_hello_verify_done(SSL *s); __owur int ossl_statem_app_data_allowed(SSL *s); #ifndef OPENSSL_NO_SCTP diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h index 99eb8ed..02c3679 100644 --- a/ssl/statem/statem_locl.h +++ b/ssl/statem/statem_locl.h @@ -191,6 +191,8 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context, int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al); #endif +int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context, + X509 *x, size_t chainidx, int *al); #ifndef OPENSSL_NO_EC int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al); -- cgit v1.1