Don't call read_bytes in read_change_cipher_spec. Change-Id: If7d50e43c8ea28c5eed38209f31d481fb57bf225 Reviewed-on: https://boringssl-review.googlesource.com/8175 Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index 4f05f0f..d0a884a 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c
@@ -208,22 +208,42 @@ } int dtls1_read_change_cipher_spec(SSL *ssl) { - uint8_t byte; - int ret = dtls1_read_bytes(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, - 1 /* len */, 0 /* no peek */); - if (ret <= 0) { - return ret; - } - assert(ret == 1); + SSL3_RECORD *rr = &ssl->s3->rrec; - if (ssl->s3->rrec.length != 0 || byte != SSL3_MT_CCS) { +again: + if (rr->length == 0) { + int ret = dtls1_get_record(ssl); + if (ret <= 0) { + return ret; + } + } + + /* Drop handshake records silently. The epochs match, so this must be a + * retransmit of a message we already received. */ + if (rr->type == SSL3_RT_HANDSHAKE) { + rr->length = 0; + goto again; + } + + /* Other record types are illegal in this epoch. Note all application data + * records come in the encrypted epoch. */ + if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); + return -1; + } + + if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) { OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return -1; } ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, - SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1); + SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, rr->length); + + rr->length = 0; + ssl_read_buffer_discard(ssl); return 1; } @@ -241,7 +261,6 @@ * 'type' is one of the following: * * - SSL3_RT_HANDSHAKE (when dtls1_get_message calls us) - * - SSL3_RT_CHANGE_CIPHER_SPEC (when dtls1_read_change_cipher_spec calls us) * - SSL3_RT_APPLICATION_DATA (when dtls1_read_app_data calls us) * * If we don't have stored data to work from, read a DTLS record first (possibly @@ -254,8 +273,7 @@ unsigned int n; SSL3_RECORD *rr; - if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE && - type != SSL3_RT_CHANGE_CIPHER_SPEC) || + if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE) || (peek && type != SSL3_RT_APPLICATION_DATA)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1; @@ -327,14 +345,7 @@ } if (rr->type == SSL3_RT_HANDSHAKE) { - if (type != SSL3_RT_APPLICATION_DATA) { - /* Out-of-order handshake record while looking for ChangeCipherSpec. Drop - * it silently. */ - assert(type == SSL3_RT_CHANGE_CIPHER_SPEC); - rr->length = 0; - goto start; - } - + assert(type == SSL3_RT_APPLICATION_DATA); /* Parse the first fragment header to determine if this is a pre-CCS or * post-CCS handshake record. DTLS resets handshake message numbers on each * handshake, so renegotiations and retransmissions are ambiguous. */
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index bbf4f5f..2396a7f 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c
@@ -316,22 +316,32 @@ } int ssl3_read_change_cipher_spec(SSL *ssl) { - uint8_t byte; - int ret = ssl3_read_bytes(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1 /* len */, - 0 /* no peek */); - if (ret <= 0) { - return ret; - } - assert(ret == 1); + SSL3_RECORD *rr = &ssl->s3->rrec; - if (ssl->s3->rrec.length != 0 || byte != SSL3_MT_CCS) { + if (rr->length == 0) { + int ret = ssl3_get_record(ssl); + if (ret <= 0) { + return ret; + } + } + + if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); + return -1; + } + + if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) { OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return -1; } ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, - SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1); + SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, rr->length); + + rr->length = 0; + ssl_read_buffer_discard(ssl); return 1; } @@ -362,7 +372,6 @@ * 'type' is one of the following: * * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) - * - SSL3_RT_CHANGE_CIPHER_SPEC (when ssl3_read_change_cipher_spec calls us) * - SSL3_RT_APPLICATION_DATA (when ssl3_read_app_data calls us) * * If we don't have stored data to work from, read a SSL/TLS record first @@ -375,8 +384,7 @@ unsigned int n; SSL3_RECORD *rr; - if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE && - type != SSL3_RT_CHANGE_CIPHER_SPEC) || + if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE) || (peek && type != SSL3_RT_APPLICATION_DATA)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return -1;