summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsthen <>2014-06-05 20:37:50 +0000
committersthen <>2014-06-05 20:37:50 +0000
commitd0f81948182201e2d50b1bf34f37b39db21f3427 (patch)
tree75a4be322eca1c095fef6d94be90a5c49bca9dca
parent6b4aaa5fd8098da7212b3f78e87aa3e3ea7841ad (diff)
downloadopenbsd-d0f81948182201e2d50b1bf34f37b39db21f3427.tar.gz
openbsd-d0f81948182201e2d50b1bf34f37b39db21f3427.tar.bz2
openbsd-d0f81948182201e2d50b1bf34f37b39db21f3427.zip
MFC ChangeCipherSpec fixes (CVE-2014-0224 and additional safeguard), ok jsing@
"Be selective as to when ChangeCipherSpec messages will be accepted. Without this an early ChangeCipherSpec message would result in session keys being generated, along with the Finished hash for the handshake, using an empty master secret." From s3_clnt.c r1.64, s3_pkt.c r1.42, s3_srvr.c r1.59, ssl3.h r1.19 - note that the ssl3.h change has been applied to s3_locl.h instead to simplify patching. "Ensure that we do not process a ChangeCipherSpec with an empty master secret. This is an additional safeguard against early ChangeCipherSpec handling." From s3_pkt.c:1.43
-rw-r--r--src/lib/libssl/src/ssl/s3_clnt.c3
-rw-r--r--src/lib/libssl/src/ssl/s3_pkt.c10
-rw-r--r--src/lib/libssl/src/ssl/s3_srvr.c7
-rw-r--r--src/lib/libssl/src/ssl/ssl_locl.h6
4 files changed, 22 insertions, 4 deletions
diff --git a/src/lib/libssl/src/ssl/s3_clnt.c b/src/lib/libssl/src/ssl/s3_clnt.c
index b80d052e1f..397e148f11 100644
--- a/src/lib/libssl/src/ssl/s3_clnt.c
+++ b/src/lib/libssl/src/ssl/s3_clnt.c
@@ -559,7 +559,7 @@ int ssl3_connect(SSL *s)
559 559
560 case SSL3_ST_CR_FINISHED_A: 560 case SSL3_ST_CR_FINISHED_A:
561 case SSL3_ST_CR_FINISHED_B: 561 case SSL3_ST_CR_FINISHED_B:
562 562 s->s3->flags |= SSL3_FLAGS_CCS_OK;
563 ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, 563 ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
564 SSL3_ST_CR_FINISHED_B); 564 SSL3_ST_CR_FINISHED_B);
565 if (ret <= 0) goto end; 565 if (ret <= 0) goto end;
@@ -917,6 +917,7 @@ int ssl3_get_server_hello(SSL *s)
917 SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); 917 SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
918 goto f_err; 918 goto f_err;
919 } 919 }
920 s->s3->flags |= SSL3_FLAGS_CCS_OK;
920 s->hit=1; 921 s->hit=1;
921 } 922 }
922 else /* a miss or crap from the other end */ 923 else /* a miss or crap from the other end */
diff --git a/src/lib/libssl/src/ssl/s3_pkt.c b/src/lib/libssl/src/ssl/s3_pkt.c
index 04a47bf2cb..9da0c2ca81 100644
--- a/src/lib/libssl/src/ssl/s3_pkt.c
+++ b/src/lib/libssl/src/ssl/s3_pkt.c
@@ -1300,6 +1300,14 @@ start:
1300 goto f_err; 1300 goto f_err;
1301 } 1301 }
1302 1302
1303 /* Check that we should be receiving a Change Cipher Spec. */
1304 if (!(s->s3->flags & SSL3_FLAGS_CCS_OK)) {
1305 al = SSL_AD_UNEXPECTED_MESSAGE;
1306 SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_CCS_RECEIVED_EARLY);
1307 goto f_err;
1308 }
1309 s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
1310
1303 rr->length=0; 1311 rr->length=0;
1304 1312
1305 if (s->msg_callback) 1313 if (s->msg_callback)
@@ -1434,7 +1442,7 @@ int ssl3_do_change_cipher_spec(SSL *s)
1434 1442
1435 if (s->s3->tmp.key_block == NULL) 1443 if (s->s3->tmp.key_block == NULL)
1436 { 1444 {
1437 if (s->session == NULL) 1445 if (s->session == NULL || s->session->master_key_length == 0)
1438 { 1446 {
1439 /* might happen if dtls1_read_bytes() calls this */ 1447 /* might happen if dtls1_read_bytes() calls this */
1440 SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY); 1448 SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY);
diff --git a/src/lib/libssl/src/ssl/s3_srvr.c b/src/lib/libssl/src/ssl/s3_srvr.c
index 118939fabb..673ced236e 100644
--- a/src/lib/libssl/src/ssl/s3_srvr.c
+++ b/src/lib/libssl/src/ssl/s3_srvr.c
@@ -670,6 +670,7 @@ int ssl3_accept(SSL *s)
670 670
671 case SSL3_ST_SR_CERT_VRFY_A: 671 case SSL3_ST_SR_CERT_VRFY_A:
672 case SSL3_ST_SR_CERT_VRFY_B: 672 case SSL3_ST_SR_CERT_VRFY_B:
673 s->s3->flags |= SSL3_FLAGS_CCS_OK;
673 674
674 /* we should decide if we expected this one */ 675 /* we should decide if we expected this one */
675 ret=ssl3_get_cert_verify(s); 676 ret=ssl3_get_cert_verify(s);
@@ -698,6 +699,7 @@ int ssl3_accept(SSL *s)
698 699
699 case SSL3_ST_SR_FINISHED_A: 700 case SSL3_ST_SR_FINISHED_A:
700 case SSL3_ST_SR_FINISHED_B: 701 case SSL3_ST_SR_FINISHED_B:
702 s->s3->flags |= SSL3_FLAGS_CCS_OK;
701 ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, 703 ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
702 SSL3_ST_SR_FINISHED_B); 704 SSL3_ST_SR_FINISHED_B);
703 if (ret <= 0) goto end; 705 if (ret <= 0) goto end;
@@ -767,9 +769,10 @@ int ssl3_accept(SSL *s)
767#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) 769#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
768 s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; 770 s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
769#else 771#else
770 if (s->s3->next_proto_neg_seen) 772 if (s->s3->next_proto_neg_seen) {
773 s->s3->flags |= SSL3_FLAGS_CCS_OK;
771 s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A; 774 s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A;
772 else 775 } else
773 s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; 776 s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
774#endif 777#endif
775 } 778 }
diff --git a/src/lib/libssl/src/ssl/ssl_locl.h b/src/lib/libssl/src/ssl/ssl_locl.h
index 7fc110df64..33bc1d46d0 100644
--- a/src/lib/libssl/src/ssl/ssl_locl.h
+++ b/src/lib/libssl/src/ssl/ssl_locl.h
@@ -165,6 +165,12 @@
165#include <openssl/ssl.h> 165#include <openssl/ssl.h>
166#include <openssl/symhacks.h> 166#include <openssl/symhacks.h>
167 167
168/*
169 * Macro defined here rather than in ssl.h for -stable, avoiding
170 * the need to update installed headers before building.
171 */
172#define SSL3_FLAGS_CCS_OK 0x0080
173
168#ifdef OPENSSL_BUILD_SHLIBSSL 174#ifdef OPENSSL_BUILD_SHLIBSSL
169# undef OPENSSL_EXTERN 175# undef OPENSSL_EXTERN
170# define OPENSSL_EXTERN OPENSSL_EXPORT 176# define OPENSSL_EXTERN OPENSSL_EXPORT