Drop CCS messages received in the TLSv1.3 handshake
authorMatt Caswell <matt@openssl.org>
Tue, 7 Nov 2017 16:36:51 +0000 (16:36 +0000)
committerMatt Caswell <matt@openssl.org>
Thu, 14 Dec 2017 15:06:37 +0000 (15:06 +0000)
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/4701)

crypto/err/openssl.txt
include/openssl/sslerr.h
ssl/record/ssl3_record.c
ssl/ssl_err.c
ssl/ssl_locl.h

index 4410314bc1facd2252185f191c4211a17682fa04..de7c50a0a0ed124d80a81b3b6e6081bd03bbcff4 100644 (file)
@@ -2453,6 +2453,7 @@ SSL_R_INCONSISTENT_EARLY_DATA_SNI:231:inconsistent early data sni
 SSL_R_INCONSISTENT_EXTMS:104:inconsistent extms
 SSL_R_INSUFFICIENT_SECURITY:241:insufficient security
 SSL_R_INVALID_ALERT:205:invalid alert
+SSL_R_INVALID_CCS_MESSAGE:260:invalid ccs message
 SSL_R_INVALID_CERTIFICATE_OR_ALG:238:invalid certificate or alg
 SSL_R_INVALID_COMMAND:280:invalid command
 SSL_R_INVALID_COMPRESSION_ALGORITHM:341:invalid compression algorithm
@@ -2463,7 +2464,7 @@ SSL_R_INVALID_MAX_EARLY_DATA:174:invalid max early data
 SSL_R_INVALID_NULL_CMD_NAME:385:invalid null cmd name
 SSL_R_INVALID_SEQUENCE_NUMBER:402:invalid sequence number
 SSL_R_INVALID_SERVERINFO_DATA:388:invalid serverinfo data
-SSL_R_INVALID_SESSION_ID:232:invalid session id
+SSL_R_INVALID_SESSION_ID:999:invalid session id
 SSL_R_INVALID_SRP_USERNAME:357:invalid srp username
 SSL_R_INVALID_STATUS_RESPONSE:328:invalid status response
 SSL_R_INVALID_TICKET_KEYS_LENGTH:325:invalid ticket keys length
@@ -2583,6 +2584,7 @@ SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS:239:\
        unable to find public key parameters
 SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES:242:unable to load ssl3 md5 routines
 SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES:243:unable to load ssl3 sha1 routines
+SSL_R_UNEXPECTED_CCS_MESSAGE:262:unexpected ccs message
 SSL_R_UNEXPECTED_END_OF_EARLY_DATA:178:unexpected end of early data
 SSL_R_UNEXPECTED_MESSAGE:244:unexpected message
 SSL_R_UNEXPECTED_RECORD:245:unexpected record
index 3199ab0ff420a429dce0084d024a4df1a1f1b2aa..9c86220336ce053df29e2f6f85709606a940933b 100644 (file)
@@ -533,6 +533,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_INCONSISTENT_EXTMS                         104
 # define SSL_R_INSUFFICIENT_SECURITY                      241
 # define SSL_R_INVALID_ALERT                              205
+# define SSL_R_INVALID_CCS_MESSAGE                        260
 # define SSL_R_INVALID_CERTIFICATE_OR_ALG                 238
 # define SSL_R_INVALID_COMMAND                            280
 # define SSL_R_INVALID_COMPRESSION_ALGORITHM              341
@@ -543,7 +544,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_INVALID_NULL_CMD_NAME                      385
 # define SSL_R_INVALID_SEQUENCE_NUMBER                    402
 # define SSL_R_INVALID_SERVERINFO_DATA                    388
-# define SSL_R_INVALID_SESSION_ID                         232
+# define SSL_R_INVALID_SESSION_ID                         999
 # define SSL_R_INVALID_SRP_USERNAME                       357
 # define SSL_R_INVALID_STATUS_RESPONSE                    328
 # define SSL_R_INVALID_TICKET_KEYS_LENGTH                 325
@@ -685,6 +686,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS       239
 # define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES           242
 # define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES          243
+# define SSL_R_UNEXPECTED_CCS_MESSAGE                     262
 # define SSL_R_UNEXPECTED_END_OF_EARLY_DATA               178
 # define SSL_R_UNEXPECTED_MESSAGE                         244
 # define SSL_R_UNEXPECTED_RECORD                          245
index 213f00104d488e8f6e1de7d6f48064532299c3ab..c1776e98f1cdff7bdf2b742dcc36b83cd70b2a8e 100644 (file)
@@ -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.
index fa02b21b9d23837c3260a11dcc9040d40418a34b..3322685c1905983544d9e9ad22d7f2e2cc02f885 100644 (file)
@@ -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"},
index c2d63fa100781499b6bc36bcca77499b048ddc36..23cb31ab69080b69b1be78c844f40278be3997bc 100644 (file)
     (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)  \