From: Matt Caswell Date: Fri, 24 Feb 2017 11:40:49 +0000 (+0000) Subject: Skip early_data if appropriate after a HelloRetryRequest X-Git-Tag: OpenSSL_1_1_1-pre1~2150 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=a832b5ef7a6080a6a66d1135c80c9aaf5570fc02;p=oweals%2Fopenssl.git Skip early_data if appropriate after a HelloRetryRequest Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/2737) --- diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index 6fa272c77a..1dc2956478 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -1565,6 +1565,21 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, if (ossl_statem_app_data_allowed(s)) { s->s3->in_read_app_data = 2; return -1; + } else if (ossl_statem_skip_early_data(s)) { + /* + * This can happen after a client sends a CH followed by early_data, + * but the server responds with a HelloRetryRequest. The server + * reads the next record from the client expecting to find a + * plaintext ClientHello but gets a record which appears to be + * application data. The trial decrypt "works" because null + * decryption was applied. We just skip it and move on to the next + * record. + */ + if (!early_data_count_ok(s, rr->length, + EARLY_DATA_CIPHERTEXT_OVERHEAD, &al)) + goto f_err; + SSL3_RECORD_set_read(rr); + goto start; } else { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_UNEXPECTED_RECORD); diff --git a/ssl/record/record_locl.h b/ssl/record/record_locl.h index 6394835404..e249918ef4 100644 --- a/ssl/record/record_locl.h +++ b/ssl/record/record_locl.h @@ -115,3 +115,4 @@ __owur int tls1_cbc_remove_padding(const SSL *s, size_t block_size, size_t mac_size); int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap); __owur int dtls1_get_record(SSL *s); +int early_data_count_ok(SSL *s, size_t length, size_t overhead, int *al); diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index aebead2395..50582d1a73 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -101,16 +101,16 @@ static int ssl3_record_app_data_waiting(SSL *s) return 1; } -static int early_data_count_ok(SSL *s, size_t length, size_t overhead, int *al) +int early_data_count_ok(SSL *s, size_t length, size_t overhead, int *al) { uint32_t max_early_data = s->max_early_data; /* * We go with the lowest out of the max early data set in the session - * and the configured max_early_data + * and the configured max_early_data. */ - if (s->session->ext.max_early_data < s->max_early_data) - max_early_data = s->max_early_data; + if (s->hit && s->session->ext.max_early_data < s->max_early_data) + max_early_data = s->session->ext.max_early_data; if (max_early_data == 0) { *al = SSL_AD_UNEXPECTED_MESSAGE; diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c index 9c74a2932e..2c202f4deb 100644 --- a/ssl/statem/statem.c +++ b/ssl/statem/statem.c @@ -157,8 +157,13 @@ int ossl_statem_skip_early_data(SSL *s) if (s->ext.early_data != SSL_EARLY_DATA_REJECTED) return 0; - if (s->statem.hand_state != TLS_ST_SW_FINISHED) - return 0; + if (s->hello_retry_request) { + if (s->statem.hand_state != TLS_ST_SW_HELLO_RETRY_REQUEST) + return 0; + } else { + if (s->statem.hand_state != TLS_ST_SW_FINISHED) + return 0; + } return 1; }