Give SSL_HANDSHAKE a constructor and destructor.
SSL_HANDSHAKE is large so I have not attempted to fully switch it to
scopers in this CL. This is just a preparatory step so that we can start
switching its fields to scopers.
(I also anticipate we'll want a bssl::Array<uint8_t> to replace the
pointer/length pairs.)
Bug: 132
Change-Id: I1538d3fc7f9c7385cd8c44a7b99b5c76e8a8768c
Reviewed-on: https://boringssl-review.googlesource.com/18244
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
diff --git a/ssl/internal.h b/ssl/internal.h
index fe3d9fd..74f20f3 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1077,6 +1077,9 @@
};
struct SSL_HANDSHAKE {
+ explicit SSL_HANDSHAKE(SSL *ssl);
+ ~SSL_HANDSHAKE();
+
/* ssl is a non-owning pointer to the parent |SSL| object. */
SSL *ssl;
@@ -1087,45 +1090,45 @@
/* wait contains the operation |do_tls13_handshake| is currently blocking on
* or |ssl_hs_ok| if none. */
- enum ssl_hs_wait_t wait;
+ enum ssl_hs_wait_t wait = ssl_hs_ok;
/* state contains one of the SSL3_ST_* values. */
- int state;
+ int state = SSL_ST_INIT;
/* next_state is used when SSL_ST_FLUSH_DATA is entered */
- int next_state;
+ int next_state = 0;
/* tls13_state is the internal state for the TLS 1.3 handshake. Its values
* depend on |do_tls13_handshake| but the starting state is always zero. */
- int tls13_state;
+ int tls13_state = 0;
/* min_version is the minimum accepted protocol version, taking account both
* |SSL_OP_NO_*| and |SSL_CTX_set_min_proto_version| APIs. */
- uint16_t min_version;
+ uint16_t min_version = 0;
/* max_version is the maximum accepted protocol version, taking account both
* |SSL_OP_NO_*| and |SSL_CTX_set_max_proto_version| APIs. */
- uint16_t max_version;
+ uint16_t max_version = 0;
/* session_id is the session ID in the ClientHello, used for the experimental
* TLS 1.3 variant. */
- uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
- uint8_t session_id_len;
+ uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH] = {0};
+ uint8_t session_id_len = 0;
- size_t hash_len;
- uint8_t secret[EVP_MAX_MD_SIZE];
- uint8_t early_traffic_secret[EVP_MAX_MD_SIZE];
- uint8_t client_handshake_secret[EVP_MAX_MD_SIZE];
- uint8_t server_handshake_secret[EVP_MAX_MD_SIZE];
- uint8_t client_traffic_secret_0[EVP_MAX_MD_SIZE];
- uint8_t server_traffic_secret_0[EVP_MAX_MD_SIZE];
- uint8_t expected_client_finished[EVP_MAX_MD_SIZE];
+ size_t hash_len = 0;
+ uint8_t secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t early_traffic_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t client_handshake_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t server_handshake_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t client_traffic_secret_0[EVP_MAX_MD_SIZE] = {0};
+ uint8_t server_traffic_secret_0[EVP_MAX_MD_SIZE] = {0};
+ uint8_t expected_client_finished[EVP_MAX_MD_SIZE] = {0};
union {
/* sent is a bitset where the bits correspond to elements of kExtensions
* in t1_lib.c. Each bit is set if that extension was sent in a
* ClientHello. It's not used by servers. */
- uint32_t sent;
+ uint32_t sent = 0;
/* received is a bitset, like |sent|, but is used by servers to record
* which extensions were received from a client. */
uint32_t received;
@@ -1135,7 +1138,7 @@
/* sent is a bitset where the bits correspond to elements of
* |client_custom_extensions| in the |SSL_CTX|. Each bit is set if that
* extension was sent in a ClientHello. It's not used by servers. */
- uint16_t sent;
+ uint16_t sent = 0;
/* received is a bitset, like |sent|, but is used by servers to record
* which custom extensions were received from a client. The bits here
* correspond to |server_custom_extensions|. */
@@ -1144,7 +1147,7 @@
/* retry_group is the group ID selected by the server in HelloRetryRequest in
* TLS 1.3. */
- uint16_t retry_group;
+ uint16_t retry_group = 0;
/* ecdh_ctx is the current ECDH instance. */
SSL_ECDH_CTX ecdh_ctx;
@@ -1153,82 +1156,82 @@
SSL_TRANSCRIPT transcript;
/* cookie is the value of the cookie received from the server, if any. */
- uint8_t *cookie;
- size_t cookie_len;
+ uint8_t *cookie = nullptr;
+ size_t cookie_len = 0;
/* key_share_bytes is the value of the previously sent KeyShare extension by
* the client in TLS 1.3. */
- uint8_t *key_share_bytes;
- size_t key_share_bytes_len;
+ uint8_t *key_share_bytes = nullptr;
+ size_t key_share_bytes_len = 0;
/* ecdh_public_key, for servers, is the key share to be sent to the client in
* TLS 1.3. */
- uint8_t *ecdh_public_key;
- size_t ecdh_public_key_len;
+ uint8_t *ecdh_public_key = nullptr;
+ size_t ecdh_public_key_len = 0;
/* peer_sigalgs are the signature algorithms that the peer supports. These are
* taken from the contents of the signature algorithms extension for a server
* or from the CertificateRequest for a client. */
- uint16_t *peer_sigalgs;
+ uint16_t *peer_sigalgs = nullptr;
/* num_peer_sigalgs is the number of entries in |peer_sigalgs|. */
- size_t num_peer_sigalgs;
+ size_t num_peer_sigalgs = 0;
/* peer_supported_group_list contains the supported group IDs advertised by
* the peer. This is only set on the server's end. The server does not
* advertise this extension to the client. */
- uint16_t *peer_supported_group_list;
- size_t peer_supported_group_list_len;
+ uint16_t *peer_supported_group_list = nullptr;
+ size_t peer_supported_group_list_len = 0;
/* peer_key is the peer's ECDH key for a TLS 1.2 client. */
- uint8_t *peer_key;
- size_t peer_key_len;
+ uint8_t *peer_key = nullptr;
+ size_t peer_key_len = 0;
/* server_params, in a TLS 1.2 server, stores the ServerKeyExchange
* parameters. It has client and server randoms prepended for signing
* convenience. */
- uint8_t *server_params;
- size_t server_params_len;
+ uint8_t *server_params = nullptr;
+ size_t server_params_len = 0;
/* peer_psk_identity_hint, on the client, is the psk_identity_hint sent by the
* server when using a TLS 1.2 PSK key exchange. */
- char *peer_psk_identity_hint;
+ char *peer_psk_identity_hint = nullptr;
/* ca_names, on the client, contains the list of CAs received in a
* CertificateRequest message. */
- STACK_OF(CRYPTO_BUFFER) *ca_names;
+ STACK_OF(CRYPTO_BUFFER) *ca_names = nullptr;
/* cached_x509_ca_names contains a cache of parsed versions of the elements
* of |ca_names|. */
- STACK_OF(X509_NAME) *cached_x509_ca_names;
+ STACK_OF(X509_NAME) *cached_x509_ca_names = nullptr;
/* certificate_types, on the client, contains the set of certificate types
* received in a CertificateRequest message. */
- uint8_t *certificate_types;
- size_t num_certificate_types;
+ uint8_t *certificate_types = nullptr;
+ size_t num_certificate_types = 0;
/* hostname, on the server, is the value of the SNI extension. */
- char *hostname;
+ char *hostname = nullptr;
/* local_pubkey is the public key we are authenticating as. */
- EVP_PKEY *local_pubkey;
+ EVP_PKEY *local_pubkey = nullptr;
/* peer_pubkey is the public key parsed from the peer's leaf certificate. */
- EVP_PKEY *peer_pubkey;
+ EVP_PKEY *peer_pubkey = nullptr;
/* new_session is the new mutable session being established by the current
* handshake. It should not be cached. */
- SSL_SESSION *new_session;
+ SSL_SESSION *new_session = nullptr;
/* early_session is the session corresponding to the current 0-RTT state on
* the client if |in_early_data| is true. */
- SSL_SESSION *early_session;
+ SSL_SESSION *early_session = nullptr;
/* new_cipher is the cipher being negotiated in this handshake. */
- const SSL_CIPHER *new_cipher;
+ const SSL_CIPHER *new_cipher = nullptr;
/* key_block is the record-layer key block for TLS 1.2 and earlier. */
- uint8_t *key_block;
- uint8_t key_block_len;
+ uint8_t *key_block = nullptr;
+ uint8_t key_block_len = 0;
/* scts_requested is one if the SCT extension is in the ClientHello. */
unsigned scts_requested:1;
@@ -1294,15 +1297,15 @@
unsigned pending_private_key_op:1;
/* client_version is the value sent or received in the ClientHello version. */
- uint16_t client_version;
+ uint16_t client_version = 0;
/* early_data_read is the amount of early data that has been read by the
* record layer. */
- uint16_t early_data_read;
+ uint16_t early_data_read = 0;
/* early_data_written is the amount of early data that has been written by the
* record layer. */
- uint16_t early_data_written;
+ uint16_t early_data_written = 0;
};
SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl);
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc
index 63e6917..ae0022b 100644
--- a/ssl/s3_both.cc
+++ b/ssl/s3_both.cc
@@ -132,64 +132,72 @@
namespace bssl {
+SSL_HANDSHAKE::SSL_HANDSHAKE(SSL *ssl_arg)
+ : ssl(ssl_arg),
+ scts_requested(0),
+ needs_psk_binder(0),
+ received_hello_retry_request(0),
+ accept_psk_mode(0),
+ cert_request(0),
+ certificate_status_expected(0),
+ ocsp_stapling_requested(0),
+ should_ack_sni(0),
+ in_false_start(0),
+ in_early_data(0),
+ early_data_offered(0),
+ can_early_read(0),
+ can_early_write(0),
+ next_proto_neg_seen(0),
+ ticket_expected(0),
+ extended_master_secret(0),
+ pending_private_key_op(0) {
+ OPENSSL_memset(&ecdh_ctx, 0, sizeof(ecdh_ctx));
+ OPENSSL_memset(&transcript, 0, sizeof(transcript));
+}
+
+SSL_HANDSHAKE::~SSL_HANDSHAKE() {
+ OPENSSL_cleanse(secret, sizeof(secret));
+ OPENSSL_cleanse(early_traffic_secret, sizeof(early_traffic_secret));
+ OPENSSL_cleanse(client_handshake_secret, sizeof(client_handshake_secret));
+ OPENSSL_cleanse(server_handshake_secret, sizeof(server_handshake_secret));
+ OPENSSL_cleanse(client_traffic_secret_0, sizeof(client_traffic_secret_0));
+ OPENSSL_cleanse(server_traffic_secret_0, sizeof(server_traffic_secret_0));
+ SSL_ECDH_CTX_cleanup(&ecdh_ctx);
+ SSL_TRANSCRIPT_cleanup(&transcript);
+ OPENSSL_free(cookie);
+ OPENSSL_free(key_share_bytes);
+ OPENSSL_free(ecdh_public_key);
+ SSL_SESSION_free(new_session);
+ SSL_SESSION_free(early_session);
+ OPENSSL_free(peer_sigalgs);
+ OPENSSL_free(peer_supported_group_list);
+ OPENSSL_free(peer_key);
+ OPENSSL_free(server_params);
+ OPENSSL_free(peer_psk_identity_hint);
+ sk_CRYPTO_BUFFER_pop_free(ca_names, CRYPTO_BUFFER_free);
+ ssl->ctx->x509_method->hs_flush_cached_ca_names(this);
+ OPENSSL_free(certificate_types);
+
+ if (key_block != NULL) {
+ OPENSSL_cleanse(key_block, key_block_len);
+ OPENSSL_free(key_block);
+ }
+
+ OPENSSL_free(hostname);
+ EVP_PKEY_free(peer_pubkey);
+ EVP_PKEY_free(local_pubkey);
+}
+
SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) {
- SSL_HANDSHAKE *hs = (SSL_HANDSHAKE *)OPENSSL_malloc(sizeof(SSL_HANDSHAKE));
- if (hs == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return NULL;
+ UniquePtr<SSL_HANDSHAKE> hs = MakeUnique<SSL_HANDSHAKE>(ssl);
+ if (!hs ||
+ !SSL_TRANSCRIPT_init(&hs->transcript)) {
+ return nullptr;
}
- OPENSSL_memset(hs, 0, sizeof(SSL_HANDSHAKE));
- hs->ssl = ssl;
- hs->wait = ssl_hs_ok;
- hs->state = SSL_ST_INIT;
- if (!SSL_TRANSCRIPT_init(&hs->transcript)) {
- ssl_handshake_free(hs);
- return NULL;
- }
- return hs;
+ return hs.release();
}
-void ssl_handshake_free(SSL_HANDSHAKE *hs) {
- if (hs == NULL) {
- return;
- }
-
- OPENSSL_cleanse(hs->secret, sizeof(hs->secret));
- OPENSSL_cleanse(hs->early_traffic_secret, sizeof(hs->early_traffic_secret));
- OPENSSL_cleanse(hs->client_handshake_secret,
- sizeof(hs->client_handshake_secret));
- OPENSSL_cleanse(hs->server_handshake_secret,
- sizeof(hs->server_handshake_secret));
- OPENSSL_cleanse(hs->client_traffic_secret_0,
- sizeof(hs->client_traffic_secret_0));
- OPENSSL_cleanse(hs->server_traffic_secret_0,
- sizeof(hs->server_traffic_secret_0));
- SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
- SSL_TRANSCRIPT_cleanup(&hs->transcript);
- OPENSSL_free(hs->cookie);
- OPENSSL_free(hs->key_share_bytes);
- OPENSSL_free(hs->ecdh_public_key);
- SSL_SESSION_free(hs->new_session);
- SSL_SESSION_free(hs->early_session);
- OPENSSL_free(hs->peer_sigalgs);
- OPENSSL_free(hs->peer_supported_group_list);
- OPENSSL_free(hs->peer_key);
- OPENSSL_free(hs->server_params);
- OPENSSL_free(hs->peer_psk_identity_hint);
- sk_CRYPTO_BUFFER_pop_free(hs->ca_names, CRYPTO_BUFFER_free);
- hs->ssl->ctx->x509_method->hs_flush_cached_ca_names(hs);
- OPENSSL_free(hs->certificate_types);
-
- if (hs->key_block != NULL) {
- OPENSSL_cleanse(hs->key_block, hs->key_block_len);
- OPENSSL_free(hs->key_block);
- }
-
- OPENSSL_free(hs->hostname);
- EVP_PKEY_free(hs->peer_pubkey);
- EVP_PKEY_free(hs->local_pubkey);
- OPENSSL_free(hs);
-}
+void ssl_handshake_free(SSL_HANDSHAKE *hs) { Delete(hs); }
int ssl_check_message_type(SSL *ssl, int type) {
if (ssl->s3->tmp.message_type != type) {