Hi,

This patch is for CVE-2016-8610.
See http://seclists.org/oss-sec/2016/q4/224 .

- Don't allow too many consecutive warning alerts up to MAX_WARN_ALERT_COUNT

OpenSSL seems not to fix this issue on branch 1.0.1.
Then I refer to these 2 commits on branch 1.0.2.

  - Don't allow too many consecutive warning alerts
    
https://github.com/openssl/openssl/commit/22646a075e75991b4e8f5d67171e45a6aead5b48
  - Add missing error string for SSL_R_TOO_MANY_WARN_ALERTS
    
https://github.com/openssl/openssl/commit/f1f97699cb5e01f1b7e37f4c92df1a9bce6772f5

With this patch, I could build LibreSSL portable and confirmed all regressions 
were passed.
But, I could not test by POC or exploit code since it is not opened.

This patch is created by command `cvs diff -Nau`.
ok ?

Index: lib/libssl/d1_pkt.c
===================================================================
RCS file: /cvs/src/lib/libssl/d1_pkt.c,v
retrieving revision 1.48
diff -u -p -a -u -r1.48 d1_pkt.c
--- lib/libssl/d1_pkt.c 11 Sep 2015 18:08:21 -0000      1.48
+++ lib/libssl/d1_pkt.c 26 Oct 2016 09:35:28 -0000
@@ -722,6 +722,13 @@ start:
                goto start;
        }
 
+       /*
+        * Reset the count of consecutive warning alerts if we've got a 
non-empty
+        * record that isn't an alert.
+        */
+       if (rr->type != SSL3_RT_ALERT && rr->length != 0)
+               s->cert->alert_count = 0;
+
        /* we now have a packet which can be read and processed */
 
        if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
@@ -932,15 +939,21 @@ start:
                        cb(s, SSL_CB_READ_ALERT, j);
                }
 
-               if (alert_level == 1) /* warning */
-               {
+               if (alert_level == SSL3_AL_WARNING) {
                        s->s3->warn_alert = alert_descr;
+
+                       s->cert->alert_count++;
+                       if (s->cert->alert_count == MAX_WARN_ALERT_COUNT) {
+                               al = SSL_AD_UNEXPECTED_MESSAGE;
+                               SSLerr(SSL_F_DTLS1_READ_BYTES, 
SSL_R_TOO_MANY_WARN_ALERTS);
+                               goto f_err;
+                       }
+
                        if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
                                s->shutdown |= SSL_RECEIVED_SHUTDOWN;
                                return (0);
                        }
-               } else if (alert_level == 2) /* fatal */
-               {
+               } else if (alert_level == SSL3_AL_FATAL) {
                        s->rwstate = SSL_NOTHING;
                        s->s3->fatal_alert = alert_descr;
                        SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_AD_REASON_OFFSET + 
alert_descr);
Index: lib/libssl/s3_pkt.c
===================================================================
RCS file: /cvs/src/lib/libssl/s3_pkt.c,v
retrieving revision 1.58
diff -u -p -a -u -r1.58 s3_pkt.c
--- lib/libssl/s3_pkt.c 10 Jul 2016 23:07:34 -0000      1.58
+++ lib/libssl/s3_pkt.c 26 Oct 2016 09:35:29 -0000
@@ -914,6 +914,13 @@ start:
                        return (ret);
        }
 
+       /*
+        * Reset the count of consecutive warning alerts if we've got a 
non-empty
+        * record that isn't an alert.
+        */
+       if (rr->type != SSL3_RT_ALERT && rr->length != 0)
+               s->cert->alert_count = 0;
+
        /* we now have a packet which can be read and processed */
 
        if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
@@ -1103,9 +1110,17 @@ start:
                        cb(s, SSL_CB_READ_ALERT, j);
                }
 
-               if (alert_level == 1) {
+               if (alert_level == SSL3_AL_WARNING) {
                        /* warning */
                        s->s3->warn_alert = alert_descr;
+
+                       s->cert->alert_count++;
+                       if (s->cert->alert_count == MAX_WARN_ALERT_COUNT) {
+                               al = SSL_AD_UNEXPECTED_MESSAGE;
+                               SSLerr(SSL_F_SSL3_READ_BYTES, 
SSL_R_TOO_MANY_WARN_ALERTS);
+                               goto f_err;
+                       }
+
                        if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
                                s->shutdown |= SSL_RECEIVED_SHUTDOWN;
                                return (0);
@@ -1125,7 +1140,7 @@ start:
                                    SSL_R_NO_RENEGOTIATION);
                                goto f_err;
                        }
-               } else if (alert_level == 2) {
+               } else if (alert_level == SSL3_AL_FATAL) {
                        /* fatal */
                        s->rwstate = SSL_NOTHING;
                        s->s3->fatal_alert = alert_descr;
Index: lib/libssl/ssl.h
===================================================================
RCS file: /cvs/src/lib/libssl/ssl.h,v
retrieving revision 1.96
diff -u -p -a -u -r1.96 ssl.h
--- lib/libssl/ssl.h    25 Oct 2015 16:07:04 -0000      1.96
+++ lib/libssl/ssl.h    26 Oct 2016 09:35:30 -0000
@@ -2329,6 +2329,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST            157
 #define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
 #define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG   234
+#define SSL_R_TOO_MANY_WARN_ALERTS                      409
 #define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER           235
 #define SSL_R_UNABLE_TO_DECODE_DH_CERTS                         236
 #define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS               313
Index: lib/libssl/ssl_err.c
===================================================================
RCS file: /cvs/src/lib/libssl/ssl_err.c,v
retrieving revision 1.29
diff -u -p -a -u -r1.29 ssl_err.c
--- lib/libssl/ssl_err.c        22 Feb 2015 15:54:27 -0000      1.29
+++ lib/libssl/ssl_err.c        26 Oct 2016 09:35:30 -0000
@@ -549,6 +549,7 @@ static ERR_STRING_DATA SSL_str_reasons[]
        {ERR_REASON(SSL_R_TLS_HEARTBEAT_PENDING) , "heartbeat request already 
pending"},
        {ERR_REASON(SSL_R_TLS_ILLEGAL_EXPORTER_LABEL), "tls illegal exporter 
label"},
        {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST), "tls invalid 
ecpointformat list"},
+       {ERR_REASON(SSL_R_TOO_MANY_WARN_ALERTS), "too many warn alerts"},
        {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST), "tls 
peer did not respond with certificate list"},
        {ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG), "tls rsa 
encrypted value length is wrong"},
        {ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER), "tried to use 
unsupported cipher"},
Index: lib/libssl/ssl_locl.h
===================================================================
RCS file: /cvs/src/lib/libssl/ssl_locl.h,v
retrieving revision 1.130
diff -u -p -a -u -r1.130 ssl_locl.h
--- lib/libssl/ssl_locl.h       19 Oct 2016 16:38:40 -0000      1.130
+++ lib/libssl/ssl_locl.h       26 Oct 2016 09:35:31 -0000
@@ -425,6 +425,8 @@ typedef struct cert_pkey_st {
        const EVP_MD *digest;
 } CERT_PKEY;
 
+#define MAX_WARN_ALERT_COUNT    5
+
 typedef struct cert_st {
        /* Current active set */
        CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array
@@ -448,6 +450,9 @@ typedef struct cert_st {
        CERT_PKEY pkeys[SSL_PKEY_NUM];
 
        int references; /* >1 only if SSL_copy_session_id is used */
+
+       /* Count of the number of consecutive warning alerts received */
+       unsigned int alert_count;
 } CERT;
 
 

Reply via email to