summaryrefslogtreecommitdiffstats
path: root/ssl/d1_srvr.c
diff options
context:
space:
mode:
authorEmilia Kasper <emilia@openssl.org>2014-11-19 17:01:36 +0100
committerEmilia Kasper <emilia@openssl.org>2014-11-20 14:57:15 +0100
commite94a6c0ede623960728415b68650a595e48f5a43 (patch)
tree9ac092e0c94be7bbaeab1a766d4015dbe65896ca /ssl/d1_srvr.c
parentde2c7504ebd4ec15334ae151a31917753468f86f (diff)
Ensure SSL3_FLAGS_CCS_OK (or d1->change_cipher_spec_ok for DTLS) is reset
once the ChangeCipherSpec message is received. Previously, the server would set the flag once at SSL3_ST_SR_CERT_VRFY and again at SSL3_ST_SR_FINISHED. This would allow a second CCS to arrive and would corrupt the server state. (Because the first CCS would latch the correct keys and subsequent CCS messages would have to be encrypted, a MitM attacker cannot exploit this, though.) Thanks to Joeri de Ruiter for reporting this issue. Reviewed-by: Matt Caswell <matt@openssl.org>
Diffstat (limited to 'ssl/d1_srvr.c')
-rw-r--r--ssl/d1_srvr.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 1d2201de45..aef38bb754 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -264,6 +264,9 @@ int dtls1_accept(SSL *s)
}
s->init_num=0;
+ s->d1->change_cipher_spec_ok = 0;
+ /* Should have been reset by ssl3_get_finished, too. */
+ s->s3->change_cipher_spec = 0;
if (s->state != SSL_ST_RENEGOTIATE)
{
@@ -694,8 +697,14 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SR_CERT_VRFY_A:
case SSL3_ST_SR_CERT_VRFY_B:
-
- s->d1->change_cipher_spec_ok = 1;
+ /*
+ * This *should* be the first time we enable CCS, but be
+ * extra careful about surrounding code changes. We need
+ * to set this here because we don't know if we're
+ * expecting a CertificateVerify or not.
+ */
+ if (!s->s3->change_cipher_spec)
+ s->d1->change_cipher_spec_ok = 1;
/* we should decide if we expected this one */
ret=ssl3_get_cert_verify(s);
if (ret <= 0) goto end;
@@ -711,7 +720,18 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SR_FINISHED_A:
case SSL3_ST_SR_FINISHED_B:
- s->d1->change_cipher_spec_ok = 1;
+ /*
+ * Enable CCS for resumed handshakes.
+ * In a full handshake, we end up here through
+ * SSL3_ST_SR_CERT_VRFY_B, so change_cipher_spec_ok was
+ * already set. Receiving a CCS clears the flag, so make
+ * sure not to re-enable it to ban duplicates.
+ * s->s3->change_cipher_spec is set when a CCS is
+ * processed in d1_pkt.c, and remains set until
+ * the client's Finished message is read.
+ */
+ if (!s->s3->change_cipher_spec)
+ s->d1->change_cipher_spec_ok = 1;
ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
SSL3_ST_SR_FINISHED_B);
if (ret <= 0) goto end;