Saved Finished messages are twelve bytes.
We only save them at TLS 1.0 through 1.2. This saves 104 bytes of
per-connection memory.
Change-Id: If397bdc10e40f0194cba01024e0e9857d6b812f0
Reviewed-on: https://boringssl-review.googlesource.com/11571
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 7ff5e39..8d105aa 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -4366,9 +4366,9 @@
unsigned session_reused:1;
/* Connection binding to prevent renegotiation attacks */
- uint8_t previous_client_finished[EVP_MAX_MD_SIZE];
+ uint8_t previous_client_finished[12];
uint8_t previous_client_finished_len;
- uint8_t previous_server_finished[EVP_MAX_MD_SIZE];
+ uint8_t previous_server_finished[12];
uint8_t previous_server_finished_len;
int send_connection_binding;
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 0e0c059..cb5afab 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -254,13 +254,21 @@
return 0;
}
- /* Copy the finished so we can use it for renegotiation checks. */
- if (ssl->server) {
- memcpy(ssl->s3->previous_server_finished, finished, finished_len);
- ssl->s3->previous_server_finished_len = finished_len;
- } else {
- memcpy(ssl->s3->previous_client_finished, finished, finished_len);
- ssl->s3->previous_client_finished_len = finished_len;
+ /* Copy the Finished so we can use it for renegotiation checks. */
+ if (ssl->version != SSL3_VERSION) {
+ if (finished_len > sizeof(ssl->s3->previous_client_finished) ||
+ finished_len > sizeof(ssl->s3->previous_server_finished)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ if (ssl->server) {
+ memcpy(ssl->s3->previous_server_finished, finished, finished_len);
+ ssl->s3->previous_server_finished_len = finished_len;
+ } else {
+ memcpy(ssl->s3->previous_client_finished, finished, finished_len);
+ ssl->s3->previous_client_finished_len = finished_len;
+ }
}
CBB cbb, body;
@@ -303,13 +311,21 @@
return -1;
}
- /* Copy the finished so we can use it for renegotiation checks. */
- if (ssl->server) {
- memcpy(ssl->s3->previous_client_finished, finished, finished_len);
- ssl->s3->previous_client_finished_len = finished_len;
- } else {
- memcpy(ssl->s3->previous_server_finished, finished, finished_len);
- ssl->s3->previous_server_finished_len = finished_len;
+ /* Copy the Finished so we can use it for renegotiation checks. */
+ if (ssl->version != SSL3_VERSION) {
+ if (finished_len > sizeof(ssl->s3->previous_client_finished) ||
+ finished_len > sizeof(ssl->s3->previous_server_finished)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ if (ssl->server) {
+ memcpy(ssl->s3->previous_client_finished, finished, finished_len);
+ ssl->s3->previous_client_finished_len = finished_len;
+ } else {
+ memcpy(ssl->s3->previous_server_finished, finished, finished_len);
+ ssl->s3->previous_server_finished_len = finished_len;
+ }
}
return 1;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 06595d2..02c713b 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -720,6 +720,9 @@
return 1;
}
+ assert(ssl->s3->initial_handshake_complete ==
+ (ssl->s3->previous_client_finished_len != 0));
+
CBB contents, prev_finished;
if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
@@ -765,6 +768,10 @@
/* Check for logic errors */
assert(!expected_len || ssl->s3->previous_client_finished_len);
assert(!expected_len || ssl->s3->previous_server_finished_len);
+ assert(ssl->s3->initial_handshake_complete ==
+ (ssl->s3->previous_client_finished_len != 0));
+ assert(ssl->s3->initial_handshake_complete ==
+ (ssl->s3->previous_server_finished_len != 0));
/* Parse out the extension contents. */
CBS renegotiated_connection;
@@ -823,10 +830,9 @@
return 0;
}
- /* Check that the extension matches */
- if (!CBS_mem_equal(&renegotiated_connection,
- ssl->s3->previous_client_finished,
- ssl->s3->previous_client_finished_len)) {
+ /* Check that the extension matches. We do not support renegotiation as a
+ * server, so this must be empty. */
+ if (CBS_len(&renegotiated_connection) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
*out_alert = SSL_AD_HANDSHAKE_FAILURE;
return 0;
@@ -838,19 +844,17 @@
}
static int ext_ri_add_serverhello(SSL *ssl, CBB *out) {
+ /* Renegotiation isn't supported as a server so this function should never be
+ * called after the initial handshake. */
+ assert(!ssl->s3->initial_handshake_complete);
+
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
- CBB contents, prev_finished;
if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
- !CBB_add_u16_length_prefixed(out, &contents) ||
- !CBB_add_u8_length_prefixed(&contents, &prev_finished) ||
- !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished,
- ssl->s3->previous_client_finished_len) ||
- !CBB_add_bytes(&prev_finished, ssl->s3->previous_server_finished,
- ssl->s3->previous_server_finished_len) ||
- !CBB_flush(out)) {
+ !CBB_add_u16(out, 1 /* length */) ||
+ !CBB_add_u8(out, 0 /* empty renegotiation info */)) {
return 0;
}