Add CBB_zero to set a CBB to the zero state.
One tedious thing about using CBB is that you can't safely CBB_cleanup
until CBB_init is successful, which breaks the general 'goto err' style
of cleanup. This makes it possible:
CBB_zero ~ EVP_MD_CTX_init
CBB_init ~ EVP_DigestInit
CBB_cleanup ~ EVP_MD_CTX_cleanup
Change-Id: I085ecc4405715368886dc4de02285a47e7fc4c52
Reviewed-on: https://boringssl-review.googlesource.com/5267
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/bytestring/bytestring_test.cc b/crypto/bytestring/bytestring_test.cc
index 870d7c6..e987e1b 100644
--- a/crypto/bytestring/bytestring_test.cc
+++ b/crypto/bytestring/bytestring_test.cc
@@ -649,6 +649,14 @@
return true;
}
+static int TestZero() {
+ CBB cbb;
+ CBB_zero(&cbb);
+ // Calling |CBB_cleanup| on a zero-state |CBB| must not crash.
+ CBB_cleanup(&cbb);
+ return 1;
+}
+
int main(void) {
CRYPTO_library_init();
@@ -665,7 +673,8 @@
!TestCBBASN1() ||
!TestBerConvert() ||
!TestASN1Uint64() ||
- !TestGetOptionalASN1Bool()) {
+ !TestGetOptionalASN1Bool() ||
+ !TestZero()) {
return 1;
}
diff --git a/crypto/bytestring/cbb.c b/crypto/bytestring/cbb.c
index 290d16f..b9291ce 100644
--- a/crypto/bytestring/cbb.c
+++ b/crypto/bytestring/cbb.c
@@ -20,6 +20,10 @@
#include <openssl/mem.h>
+void CBB_zero(CBB *cbb) {
+ memset(cbb, 0, sizeof(CBB));
+}
+
static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
struct cbb_buffer_st *base;
diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h
index 8583c4e..3419275 100644
--- a/include/openssl/bytestring.h
+++ b/include/openssl/bytestring.h
@@ -248,6 +248,12 @@
char is_top_level;
};
+/* CBB_zero sets an uninitialised |cbb| to the zero state. It must be
+ * initialised with |CBB_init| or |CBB_init_fixed| before use, but it is safe to
+ * call |CBB_cleanup| without a successful |CBB_init|. This may be used for more
+ * uniform cleanup of a |CBB|. */
+OPENSSL_EXPORT void CBB_zero(CBB *cbb);
+
/* CBB_init initialises |cbb| with |initial_capacity|. Since a |CBB| grows as
* needed, the |initial_capacity| is just a hint. It returns one on success or
* zero on error. */
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index f8724ba..74fc201 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -592,18 +592,15 @@
goto err;
}
+ /* Reconstruct the assembled message. */
+ size_t len;
CBB cbb;
+ CBB_zero(&cbb);
if (!BUF_MEM_grow(s->init_buf,
(size_t)frag->msg_header.msg_len +
DTLS1_HM_HEADER_LENGTH) ||
- !CBB_init_fixed(&cbb, (uint8_t *)s->init_buf->data, s->init_buf->max)) {
- OPENSSL_PUT_ERROR(SSL, dtls1_get_message, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Reconstruct the assembled message. */
- size_t len;
- if (!CBB_add_u8(&cbb, frag->msg_header.type) ||
+ !CBB_init_fixed(&cbb, (uint8_t *)s->init_buf->data, s->init_buf->max) ||
+ !CBB_add_u8(&cbb, frag->msg_header.type) ||
!CBB_add_u24(&cbb, frag->msg_header.msg_len) ||
!CBB_add_u16(&cbb, frag->msg_header.seq) ||
!CBB_add_u24(&cbb, 0 /* frag_off */) ||
@@ -611,7 +608,7 @@
!CBB_add_bytes(&cbb, frag->fragment, frag->msg_header.msg_len) ||
!CBB_finish(&cbb, NULL, &len)) {
CBB_cleanup(&cbb);
- OPENSSL_PUT_ERROR(SSL, dtls1_get_message, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(SSL, dtls1_get_message, ERR_R_MALLOC_FAILURE);
goto err;
}
assert(len == (size_t)frag->msg_header.msg_len + DTLS1_HM_HEADER_LENGTH);
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 1d9b164..b5c35f0 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1963,19 +1963,16 @@
uint8_t *new_pms;
size_t new_pms_len;
- if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len)) {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ CBB_zero(&cbb);
+ if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len) ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
!CBB_add_bytes(&child, pms, pms_len) ||
!CBB_add_u16_length_prefixed(&cbb, &child) ||
!CBB_add_bytes(&child, psk, psk_len) ||
!CBB_finish(&cbb, &new_pms, &new_pms_len)) {
CBB_cleanup(&cbb);
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
- ERR_R_INTERNAL_ERROR);
+ ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_cleanse(pms, pms_len);
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 0a26689..b699b18 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -747,12 +747,10 @@
rand_len);
/* Write out an equivalent SSLv3 ClientHello. */
+ CBB_zero(&client_hello);
if (!CBB_init_fixed(&client_hello, (uint8_t *)s->init_buf->data,
- s->init_buf->max)) {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_MALLOC_FAILURE);
- return -1;
- }
- if (!CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) ||
+ s->init_buf->max) ||
+ !CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) ||
!CBB_add_u24_length_prefixed(&client_hello, &hello_body) ||
!CBB_add_u16(&hello_body, version) ||
!CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) ||
@@ -760,7 +758,7 @@
!CBB_add_u8(&hello_body, 0) ||
!CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) {
CBB_cleanup(&client_hello);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_MALLOC_FAILURE);
return -1;
}
@@ -1977,18 +1975,15 @@
uint8_t *new_data;
size_t new_len;
- if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len)) {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+ CBB_zero(&new_premaster);
+ if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) ||
+ !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
!CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
!CBB_add_u16_length_prefixed(&new_premaster, &child) ||
!CBB_add_bytes(&child, psk, psk_len) ||
!CBB_finish(&new_premaster, &new_data, &new_len)) {
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange,
- ERR_R_INTERNAL_ERROR);
+ ERR_R_MALLOC_FAILURE);
CBB_cleanup(&new_premaster);
goto err;
}
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 76052df..531e0d5 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -163,11 +163,9 @@
return 0;
}
- if (!CBB_init(&cbb, 0)) {
- return 0;
- }
-
- if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) ||
+ CBB_zero(&cbb);
+ if (!CBB_init(&cbb, 0) ||
+ !CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION) ||
!CBB_add_asn1_uint64(&session, in->ssl_version) ||
!CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 61546ca..91c66a4 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2582,11 +2582,9 @@
return 0;
}
- if (!CBB_init(&cbb, 4 + 16 + 1 + premaster_len * 2 + 1)) {
- return 0;
- }
-
- if (!CBB_add_bytes(&cbb, (const uint8_t *)"RSA ", 4) ||
+ CBB_zero(&cbb);
+ if (!CBB_init(&cbb, 4 + 16 + 1 + premaster_len * 2 + 1) ||
+ !CBB_add_bytes(&cbb, (const uint8_t *)"RSA ", 4) ||
/* Only the first 8 bytes of the encrypted premaster secret are
* logged. */
!cbb_add_hex(&cbb, encrypted_premaster, 8) ||
@@ -2624,11 +2622,9 @@
return 0;
}
- if (!CBB_init(&cbb, 14 + 64 + 1 + master_len * 2 + 1)) {
- return 0;
- }
-
- if (!CBB_add_bytes(&cbb, (const uint8_t *)"CLIENT_RANDOM ", 14) ||
+ CBB_zero(&cbb);
+ if (!CBB_init(&cbb, 14 + 64 + 1 + master_len * 2 + 1) ||
+ !CBB_add_bytes(&cbb, (const uint8_t *)"CLIENT_RANDOM ", 14) ||
!cbb_add_hex(&cbb, client_random, 32) ||
!CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
!cbb_add_hex(&cbb, master, master_len) ||