Fix for CVE-2014-0224
Only accept change cipher spec when it is expected instead of at any
time. This prevents premature setting of session keys before the master
secret is determined which an attacker could use as a MITM attack.
Thanks to KIKUCHI Masashi (Lepidum Co. Ltd.) for reporting this issue
and providing the initial fix this patch is based on.
(Imported from upstream's 77719aefb8f549ccc7f04222174889615d62057b)
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 90d425f..de7b9a4 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -601,6 +601,7 @@
case SSL3_ST_CR_FINISHED_A:
case SSL3_ST_CR_FINISHED_B:
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
SSL3_ST_CR_FINISHED_B);
if (ret <= 0) goto end;
@@ -1050,6 +1051,7 @@
OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
goto f_err;
}
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
s->hit=1;
}
else /* a miss or crap from the other end */
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 95e50d6..874665b 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -1324,6 +1324,15 @@
goto f_err;
}
+ if (!(s->s3->flags & SSL3_FLAGS_CCS_OK))
+ {
+ al=SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_CCS_RECEIVED_EARLY);
+ goto f_err;
+ }
+
+ s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
+
rr->length=0;
if (s->msg_callback)
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 0147967..1fc10a3 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -646,6 +646,7 @@
case SSL3_ST_SR_CERT_VRFY_A:
case SSL3_ST_SR_CERT_VRFY_B:
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
/* we should decide if we expected this one */
ret=ssl3_get_cert_verify(s);
if (ret <= 0) goto end;
@@ -664,6 +665,7 @@
channel_id = s->s3->tlsext_channel_id_valid;
#endif
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
if (next_proto_neg)
s->state=SSL3_ST_SR_NEXT_PROTO_A;
else if (channel_id)
@@ -698,6 +700,7 @@
case SSL3_ST_SR_FINISHED_A:
case SSL3_ST_SR_FINISHED_B:
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
SSL3_ST_SR_FINISHED_B);
if (ret <= 0) goto end;
@@ -737,7 +740,6 @@
s->state=SSL3_ST_SW_KEY_EXCH_A;
s->init_num=0;
break;
-
#endif
case SSL3_ST_SW_CHANGE_A:
diff --git a/ssl/ssl3.h b/ssl/ssl3.h
index 25f5f12..1d3be7b 100644
--- a/ssl/ssl3.h
+++ b/ssl/ssl3.h
@@ -404,6 +404,7 @@
#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008
#define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010
#define TLS1_FLAGS_KEEP_HANDSHAKE 0x0020
+#define SSL3_FLAGS_CCS_OK 0x0080
/* SSL3_FLAGS_SGC_RESTART_DONE is set when we
* restart a handshake because of MS SGC and so prevents us