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;