summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2017-11-07 16:36:51 +0000
committerMatt Caswell <matt@openssl.org>2017-12-14 15:06:37 +0000
commitfdd9236747d7b843f1f5644b3e95580b80d9a598 (patch)
tree0ee2807af2f47eb15e3932bf075963aba4a0d597 /ssl
parent2d729db2f0c047e64c580342f6fba0d99b2ada50 (diff)
Drop CCS messages received in the TLSv1.3 handshake
Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/4701)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/record/ssl3_record.c37
-rw-r--r--ssl/ssl_err.c4
-rw-r--r--ssl/ssl_locl.h3
3 files changed, 41 insertions, 3 deletions
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index 213f00104d..c1776e98f1 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -333,8 +333,11 @@ int ssl3_get_record(SSL *s)
}
}
- if (SSL_IS_TLS13(s) && s->enc_read_ctx != NULL
- && thisrr->type != SSL3_RT_APPLICATION_DATA) {
+ if (SSL_IS_TLS13(s)
+ && s->enc_read_ctx != NULL
+ && thisrr->type != SSL3_RT_APPLICATION_DATA
+ && (thisrr->type != SSL3_RT_CHANGE_CIPHER_SPEC
+ || !SSL_IS_FIRST_HANDSHAKE(s))) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_SSL3_GET_RECORD, SSL_R_BAD_RECORD_TYPE);
return -1;
@@ -444,6 +447,36 @@ int ssl3_get_record(SSL *s)
& EVP_CIPH_FLAG_PIPELINE)
&& ssl3_record_app_data_waiting(s));
+ if (num_recs == 1
+ && thisrr->type == SSL3_RT_CHANGE_CIPHER_SPEC
+ && SSL_IS_TLS13(s)
+ && SSL_IS_FIRST_HANDSHAKE(s)) {
+ /*
+ * CCS messages must be exactly 1 byte long, containing the value 0x01
+ */
+ if (thisrr->length != 1 || thisrr->data[0] != 0x01) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL3_GET_RECORD,
+ SSL_R_INVALID_CCS_MESSAGE);
+ return -1;
+ }
+ /*
+ * CCS messages are ignored in TLSv1.3. We treat it like an empty
+ * handshake record
+ */
+ thisrr->type = SSL3_RT_HANDSHAKE;
+ RECORD_LAYER_inc_empty_record_count(&s->rlayer);
+ if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
+ > MAX_EMPTY_RECORDS) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
+ SSL_R_UNEXPECTED_CCS_MESSAGE);
+ return -1;
+ }
+ thisrr->read = 1;
+ RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
+
+ return 1;
+ }
+
/*
* If in encrypt-then-mac mode calculate mac from encrypted record. All
* the details below are public so no timing details can leak.
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index fa02b21b9d..3322685c19 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -852,6 +852,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INSUFFICIENT_SECURITY),
"insufficient security"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_ALERT), "invalid alert"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CCS_MESSAGE),
+ "invalid ccs message"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CERTIFICATE_OR_ALG),
"invalid certificate or alg"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMMAND), "invalid command"},
@@ -1125,6 +1127,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"unable to load ssl3 md5 routines"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),
"unable to load ssl3 sha1 routines"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_CCS_MESSAGE),
+ "unexpected ccs message"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_END_OF_EARLY_DATA),
"unexpected end of early data"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_MESSAGE), "unexpected message"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index c2d63fa100..23cb31ab69 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -326,7 +326,8 @@
(SSL_IS_TLS13(s) || (s)->early_data_state == SSL_EARLY_DATA_WRITING \
|| (s)->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
-# define SSL_IS_FIRST_HANDSHAKE(S) ((s)->s3->tmp.finish_md_len == 0)
+# define SSL_IS_FIRST_HANDSHAKE(S) ((s)->s3->tmp.finish_md_len == 0 \
+ || (s)->s3->tmp.peer_finish_md_len == 0)
/* See if we need explicit IV */
# define SSL_USE_EXPLICIT_IV(s) \