]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Check max_early_data against the amount of early data we actually receive
authorMatt Caswell <matt@openssl.org>
Thu, 23 Feb 2017 14:29:36 +0000 (14:29 +0000)
committerMatt Caswell <matt@openssl.org>
Thu, 2 Mar 2017 17:44:15 +0000 (17:44 +0000)
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2737)

include/openssl/ssl.h
ssl/record/ssl3_record.c
ssl/ssl_err.c
ssl/ssl_locl.h

index d2f9fc6daa600f3739cce1fa0f297f446e0dc102..934bb23b186a92935fb1ff26faec92fb279ed814 100644 (file)
@@ -2154,6 +2154,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST        385
 # define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE               370
 # define SSL_F_DTLS_PROCESS_HELLO_VERIFY                  386
+# define SSL_F_EARLY_DATA_COUNT_OK                        532
 # define SSL_F_FINAL_EC_PT_FORMATS                        485
 # define SSL_F_FINAL_EMS                                  486
 # define SSL_F_FINAL_KEY_SHARE                            503
@@ -2679,6 +2680,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST             157
 # define SSL_R_TOO_MANY_KEY_UPDATES                       132
 # define SSL_R_TOO_MANY_WARN_ALERTS                       409
+# define SSL_R_TOO_MUCH_EARLY_DATA                        164
 # define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS             314
 # define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS       239
 # define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES           242
index 3228bda4b9afd4a1a6b59cea8744b67ac46c26a5..aebead23952ce0d6a7f2c7e6d5349d5d9de75da7 100644 (file)
@@ -101,6 +101,36 @@ 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)
+{
+    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
+     */
+    if (s->session->ext.max_early_data < s->max_early_data)
+        max_early_data = s->max_early_data;
+
+    if (max_early_data == 0) {
+        *al = SSL_AD_UNEXPECTED_MESSAGE;
+        SSLerr(SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
+        return 0;
+    }
+
+    /* If we are dealing with ciphertext we need to allow for the overhead */
+    max_early_data += overhead;
+
+    s->early_data_count += length;
+    if (s->early_data_count > max_early_data) {
+        *al = SSL_AD_UNEXPECTED_MESSAGE;
+        SSLerr(SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
+        return 0;
+    }
+
+    return 1;
+}
+
 /*
  * MAX_EMPTY_RECORDS defines the number of consecutive, empty records that
  * will be processed per call to ssl3_get_record. Without this limit an
@@ -139,6 +169,7 @@ int ssl3_get_record(SSL *s)
     int imac_size;
     size_t num_recs = 0, max_recs, j;
     PACKET pkt, sslv2pkt;
+    size_t first_rec_len;
 
     rr = RECORD_LAYER_get_rrec(&s->rlayer);
     rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
@@ -415,6 +446,8 @@ int ssl3_get_record(SSL *s)
         }
     }
 
+    first_rec_len = rr[0].length;
+
     enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0);
 
     /*-
@@ -429,7 +462,13 @@ int ssl3_get_record(SSL *s)
              * Valid early_data that we cannot decrypt might fail here as
              * publicly invalid. We treat it like an empty record.
              */
+
             thisrr = &rr[0];
+
+            if (!early_data_count_ok(s, thisrr->length,
+                                     EARLY_DATA_CIPHERTEXT_OVERHEAD, &al))
+                goto f_err;
+
             thisrr->length = 0;
             thisrr->read = 1;
             RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
@@ -513,6 +552,15 @@ int ssl3_get_record(SSL *s)
              * We assume this is unreadable early_data - we treat it like an
              * empty record
              */
+
+            /*
+             * The record length may have been modified by the mac check above
+             * so we use the previously saved value
+             */
+            if (!early_data_count_ok(s, first_rec_len,
+                                     EARLY_DATA_CIPHERTEXT_OVERHEAD, &al))
+                goto f_err;
+
             thisrr = &rr[0];
             thisrr->length = 0;
             thisrr->read = 1;
@@ -604,6 +652,13 @@ int ssl3_get_record(SSL *s)
         }
     }
 
+    if (s->early_data_state == SSL_EARLY_DATA_READING) {
+        thisrr = &rr[0];
+        if (thisrr->type == SSL3_RT_APPLICATION_DATA
+                && !early_data_count_ok(s, thisrr->length, 0, &al))
+            goto f_err;
+    }
+
     RECORD_LAYER_set_numrpipes(&s->rlayer, num_recs);
     return 1;
 
index d896ff9e58a6bdc5d7e605317919e8c146505f14..c622ef3c4aa32f9251cb9ec97aaf4458049a7833 100644 (file)
@@ -52,6 +52,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE),
      "dtls_get_reassembled_message"},
     {ERR_FUNC(SSL_F_DTLS_PROCESS_HELLO_VERIFY), "dtls_process_hello_verify"},
+    {ERR_FUNC(SSL_F_EARLY_DATA_COUNT_OK), "early_data_count_ok"},
     {ERR_FUNC(SSL_F_FINAL_EC_PT_FORMATS), "final_ec_pt_formats"},
     {ERR_FUNC(SSL_F_FINAL_EMS), "final_ems"},
     {ERR_FUNC(SSL_F_FINAL_KEY_SHARE), "final_key_share"},
@@ -788,6 +789,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
      "tls invalid ecpointformat list"},
     {ERR_REASON(SSL_R_TOO_MANY_KEY_UPDATES), "too many key updates"},
     {ERR_REASON(SSL_R_TOO_MANY_WARN_ALERTS), "too many warn alerts"},
+    {ERR_REASON(SSL_R_TOO_MUCH_EARLY_DATA), "too much early data"},
     {ERR_REASON(SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS),
      "unable to find ecdh parameters"},
     {ERR_REASON(SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS),
index f8492789f1a79abd2916421650baab9db91626e1..2151d631e81973ce598a8f7939cf7466e3fc62c7 100644 (file)
@@ -626,6 +626,18 @@ typedef enum {
     SSL_EARLY_DATA_FINISHED_READING
 } SSL_EARLY_DATA_STATE;
 
+/*
+ * We check that the amount of unreadable early data doesn't exceed
+ * max_early_data. max_early_data is given in plaintext bytes. However if it is
+ * unreadable then we only know the number of ciphertext bytes. We also don't
+ * know how much the overhead should be because it depends on the ciphersuite.
+ * We make a small allowance. We assume 5 records of actual data plus the end
+ * of early data alert record. Each record has a tag and a content type byte.
+ * The longest tag length we know of is EVP_GCM_TLS_TAG_LEN. We don't count the
+ * content of the alert record either which is 2 bytes.
+ */
+# define EARLY_DATA_CIPHERTEXT_OVERHEAD ((6 * (EVP_GCM_TLS_TAG_LEN + 1)) + 2)
+
 #define MAX_COMPRESSIONS_SIZE   255
 
 struct ssl_comp_st {
@@ -1245,8 +1257,14 @@ struct ssl_st {
     ASYNC_WAIT_CTX *waitctx;
     size_t asyncrw;
 
-    /* The maximum number of bytes that can be sent as early data */
+    /* The maximum number of plaintext bytes that can be sent as early data */
     uint32_t 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.
+     */
+    uint32_t early_data_count;
 
     CRYPTO_RWLOCK *lock;
 };