Convert SSL_TRANSCRIPT to C++.
Bug: 132
Change-Id: I2d7cb45d56e8dcb223fbc5838922fdbe6f28ded7
Reviewed-on: https://boringssl-review.googlesource.com/18264
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/d1_both.cc b/ssl/d1_both.cc
index 3a46977..50cca83 100644
--- a/ssl/d1_both.cc
+++ b/ssl/d1_both.cc
@@ -549,10 +549,10 @@
}
if (!is_ccs) {
- /* TODO(svaldez): Move this up a layer to fix abstraction for SSL_TRANSCRIPT
+ /* TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript
* on hs. */
if (ssl->s3->hs != NULL &&
- !SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript, data, len)) {
+ !ssl->s3->hs->transcript.Update(data, len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
OPENSSL_free(data);
return 0;
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index 4c85531..cac65f6 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -715,7 +715,7 @@
SSL *const ssl = hs->ssl;
/* The handshake buffer is reset on every ClientHello. Notably, in DTLS, we
* may send multiple ClientHellos if we receive HelloVerifyRequest. */
- if (!SSL_TRANSCRIPT_init(&hs->transcript)) {
+ if (!hs->transcript.Init()) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -1022,8 +1022,7 @@
/* Now that the cipher is known, initialize the handshake hash and hash the
* ServerHello. */
- if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
- c->algorithm_prf) ||
+ if (!hs->transcript.InitHash(ssl3_protocol_version(ssl), c->algorithm_prf) ||
!ssl_hash_current_message(hs)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
@@ -1034,7 +1033,7 @@
* buffer may be released. */
if (ssl->session != NULL ||
!ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
}
/* Only the NULL compression algorithm is supported. */
@@ -1382,7 +1381,7 @@
ssl->s3->tmp.reuse_message = 1;
/* If we get here we don't need the handshake buffer as we won't be doing
* client auth. */
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
return 1;
}
@@ -1478,7 +1477,7 @@
if (!ssl_has_certificate(ssl)) {
/* Without a client certificate, the handshake buffer may be released. */
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
/* In SSL 3.0, the Certificate message is replaced with a warning alert. */
if (ssl->version == SSL3_VERSION) {
@@ -1720,9 +1719,8 @@
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
- if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(
- &hs->transcript, digest, &digest_len, hs->new_session.get(),
- signature_algorithm)) {
+ if (!hs->transcript.GetSSL3CertVerifyHash(
+ digest, &digest_len, hs->new_session.get(), signature_algorithm)) {
return -1;
}
@@ -1733,10 +1731,9 @@
return -1;
}
} else {
- switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
- signature_algorithm,
- (const uint8_t *)hs->transcript.buffer->data,
- hs->transcript.buffer->length)) {
+ switch (ssl_private_key_sign(
+ hs, ptr, &sig_len, max_sig_len, signature_algorithm,
+ hs->transcript.buffer_data(), hs->transcript.buffer_len())) {
case ssl_private_key_success:
break;
case ssl_private_key_failure:
@@ -1753,7 +1750,7 @@
}
/* The handshake buffer is no longer necessary. */
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
return 1;
}
diff --git a/ssl/handshake_server.cc b/ssl/handshake_server.cc
index 48d3426..b57b67a 100644
--- a/ssl/handshake_server.cc
+++ b/ssl/handshake_server.cc
@@ -930,8 +930,8 @@
/* Now that all parameters are known, initialize the handshake hash and hash
* the ClientHello. */
- if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
- hs->new_cipher->algorithm_prf) ||
+ if (!hs->transcript.InitHash(ssl3_protocol_version(ssl),
+ hs->new_cipher->algorithm_prf) ||
!ssl_hash_current_message(hs)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
@@ -939,7 +939,7 @@
/* Release the handshake buffer if client authentication isn't required. */
if (!hs->cert_request) {
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
}
return 1;
@@ -1251,7 +1251,7 @@
if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0) {
/* No client certificate so the handshake buffer may be discarded. */
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
/* In SSL 3.0, sending no certificate is signaled by omitting the
* Certificate message. */
@@ -1540,7 +1540,7 @@
* CertificateVerify is required if and only if there's a client certificate.
* */
if (!hs->peer_pubkey) {
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
return 1;
}
@@ -1590,9 +1590,8 @@
if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
- if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(
- &hs->transcript, digest, &digest_len, hs->new_session.get(),
- signature_algorithm)) {
+ if (!hs->transcript.GetSSL3CertVerifyHash(
+ digest, &digest_len, hs->new_session.get(), signature_algorithm)) {
return -1;
}
@@ -1605,8 +1604,8 @@
} else {
sig_ok = ssl_public_key_verify(
ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
- hs->peer_pubkey.get(), (const uint8_t *)hs->transcript.buffer->data,
- hs->transcript.buffer->length);
+ hs->peer_pubkey.get(), hs->transcript.buffer_data(),
+ hs->transcript.buffer_len());
}
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
@@ -1621,7 +1620,7 @@
/* The handshake buffer is no longer necessary, and we may hash the current
* message.*/
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
if (!ssl_hash_current_message(hs)) {
return -1;
}
diff --git a/ssl/internal.h b/ssl/internal.h
index 160247a..f7d1cde 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -365,75 +365,75 @@
/* Transcript layer. */
-/* SSL_TRANSCRIPT maintains the handshake transcript as a combination of a
+/* SSLTranscript maintains the handshake transcript as a combination of a
* buffer and running hash. */
-struct SSL_TRANSCRIPT {
- /* buffer, if non-NULL, contains the handshake transcript. */
- BUF_MEM *buffer;
+class SSLTranscript {
+ public:
+ SSLTranscript();
+ ~SSLTranscript();
+
+ /* Init initializes the handshake transcript. If called on an existing
+ * transcript, it resets the transcript and hash. It returns true on success
+ * and false on failure. */
+ bool Init();
+
+ /* InitHash initializes the handshake hash based on the PRF and contents of
+ * the handshake transcript. Subsequent calls to |Update| will update the
+ * rolling hash. It returns one on success and zero on failure. It is an error
+ * to call this function after the handshake buffer is released. */
+ bool InitHash(uint16_t version, int algorithm_prf);
+
+ const uint8_t *buffer_data() const {
+ return reinterpret_cast<const uint8_t *>(buffer_->data);
+ }
+ size_t buffer_len() const { return buffer_->length; }
+
+ /* FreeBuffer releases the handshake buffer. Subsequent calls to
+ * |Update| will not update the handshake buffer. */
+ void FreeBuffer();
+
+ /* DigestLen returns the length of the PRF hash. */
+ size_t DigestLen() const;
+
+ /* Digest returns the PRF hash. For TLS 1.1 and below, this is
+ * |EVP_md5_sha1|. */
+ const EVP_MD *Digest() const;
+
+ /* Update adds |in| to the handshake buffer and handshake hash, whichever is
+ * enabled. It returns true on success and false on failure. */
+ bool Update(const uint8_t *in, size_t in_len);
+
+ /* GetHash writes the handshake hash to |out| which must have room for at
+ * least |DigestLen| bytes. On success, it returns true and sets |*out_len| to
+ * the number of bytes written. Otherwise, it returns false. */
+ bool GetHash(uint8_t *out, size_t *out_len);
+
+ /* GetSSL3CertVerifyHash writes the SSL 3.0 CertificateVerify hash into the
+ * bytes pointed to by |out| and writes the number of bytes to
+ * |*out_len|. |out| must have room for |EVP_MAX_MD_SIZE| bytes. It returns
+ * one on success and zero on failure. */
+ bool GetSSL3CertVerifyHash(uint8_t *out, size_t *out_len,
+ const SSL_SESSION *session,
+ uint16_t signature_algorithm);
+
+ /* GetFinishedMAC computes the MAC for the Finished message into the bytes
+ * pointed by |out| and writes the number of bytes to |*out_len|. |out| must
+ * have room for |EVP_MAX_MD_SIZE| bytes. It returns true on success and false
+ * on failure. */
+ bool GetFinishedMAC(uint8_t *out, size_t *out_len, const SSL_SESSION *session,
+ bool from_server, uint16_t version);
+
+ private:
+ /* buffer_, if non-null, contains the handshake transcript. */
+ UniquePtr<BUF_MEM> buffer_;
/* hash, if initialized with an |EVP_MD|, maintains the handshake hash. For
* TLS 1.1 and below, it is the SHA-1 half. */
- EVP_MD_CTX hash;
+ ScopedEVP_MD_CTX hash_;
/* md5, if initialized with an |EVP_MD|, maintains the MD5 half of the
* handshake hash for TLS 1.1 and below. */
- EVP_MD_CTX md5;
+ ScopedEVP_MD_CTX md5_;
};
-/* SSL_TRANSCRIPT_init initializes the handshake transcript. If called on an
- * existing transcript, it resets the transcript and hash. It returns one on
- * success and zero on failure. */
-int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_init_hash initializes the handshake hash based on the PRF and
- * contents of the handshake transcript. Subsequent calls to
- * |SSL_TRANSCRIPT_update| will update the rolling hash. It returns one on
- * success and zero on failure. It is an error to call this function after the
- * handshake buffer is released. */
-int SSL_TRANSCRIPT_init_hash(SSL_TRANSCRIPT *transcript, uint16_t version,
- int algorithm_prf);
-
-/* SSL_TRANSCRIPT_cleanup cleans up the hash and transcript. */
-void SSL_TRANSCRIPT_cleanup(SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_free_buffer releases the handshake buffer. Subsequent calls to
- * |SSL_TRANSCRIPT_update| will not update the handshake buffer. */
-void SSL_TRANSCRIPT_free_buffer(SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_digest_len returns the length of the PRF hash. */
-size_t SSL_TRANSCRIPT_digest_len(const SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_md returns the PRF hash. For TLS 1.1 and below, this is
- * |EVP_md5_sha1|. */
-const EVP_MD *SSL_TRANSCRIPT_md(const SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_update adds |in| to the handshake buffer and handshake hash,
- * whichever is enabled. It returns one on success and zero on failure. */
-int SSL_TRANSCRIPT_update(SSL_TRANSCRIPT *transcript, const uint8_t *in,
- size_t in_len);
-
-/* SSL_TRANSCRIPT_get_hash writes the handshake hash to |out| which must have
- * room for at least |SSL_TRANSCRIPT_digest_len| bytes. On success, it returns
- * one and sets |*out_len| to the number of bytes written. Otherwise, it returns
- * zero. */
-int SSL_TRANSCRIPT_get_hash(const SSL_TRANSCRIPT *transcript, uint8_t *out,
- size_t *out_len);
-
-/* SSL_TRANSCRIPT_ssl3_cert_verify_hash writes the SSL 3.0 CertificateVerify
- * hash into the bytes pointed to by |out| and writes the number of bytes to
- * |*out_len|. |out| must have room for |EVP_MAX_MD_SIZE| bytes. It returns one
- * on success and zero on failure. */
-int SSL_TRANSCRIPT_ssl3_cert_verify_hash(SSL_TRANSCRIPT *transcript,
- uint8_t *out, size_t *out_len,
- const SSL_SESSION *session,
- int signature_algorithm);
-
-/* SSL_TRANSCRIPT_finish_mac computes the MAC for the Finished message into the
- * bytes pointed by |out| and writes the number of bytes to |*out_len|. |out|
- * must have room for |EVP_MAX_MD_SIZE| bytes. It returns one on success and
- * zero on failure. */
-int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out,
- size_t *out_len, const SSL_SESSION *session,
- int from_server, uint16_t version);
-
/* tls1_prf computes the PRF function for |ssl|. It writes |out_len| bytes to
* |out|, using |secret| as the secret and |label| as the label. |seed1| and
* |seed2| are concatenated to form the seed parameter. It returns one on
@@ -1152,7 +1152,7 @@
SSL_ECDH_CTX ecdh_ctx;
/* transcript is the current handshake transcript. */
- SSL_TRANSCRIPT transcript;
+ SSLTranscript transcript;
/* cookie is the value of the cookie received from the server, if any. */
uint8_t *cookie = nullptr;
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc
index 1c47c1c..2ac2837 100644
--- a/ssl/s3_both.cc
+++ b/ssl/s3_both.cc
@@ -152,7 +152,6 @@
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() {
@@ -163,7 +162,6 @@
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);
@@ -183,7 +181,7 @@
SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) {
UniquePtr<SSL_HANDSHAKE> hs = MakeUnique<SSL_HANDSHAKE>(ssl);
if (!hs ||
- !SSL_TRANSCRIPT_init(&hs->transcript)) {
+ !hs->transcript.Init()) {
return nullptr;
}
return hs.release();
@@ -283,10 +281,10 @@
} while (added < len);
ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg, len);
- /* TODO(svaldez): Move this up a layer to fix abstraction for SSL_TRANSCRIPT
- * on hs. */
+ /* TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript on
+ * hs. */
if (ssl->s3->hs != NULL &&
- !SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript, msg, len)) {
+ !ssl->s3->hs->transcript.Update(msg, len)) {
goto err;
}
ret = 1;
@@ -383,9 +381,8 @@
uint8_t finished[EVP_MAX_MD_SIZE];
size_t finished_len;
- if (!SSL_TRANSCRIPT_finish_mac(&hs->transcript, finished, &finished_len,
- session, ssl->server,
- ssl3_protocol_version(ssl))) {
+ if (!hs->transcript.GetFinishedMAC(finished, &finished_len, session,
+ ssl->server, ssl3_protocol_version(ssl))) {
return 0;
}
@@ -439,9 +436,9 @@
/* Snapshot the finished hash before incorporating the new message. */
uint8_t finished[EVP_MAX_MD_SIZE];
size_t finished_len;
- if (!SSL_TRANSCRIPT_finish_mac(&hs->transcript, finished, &finished_len,
- SSL_get_session(ssl), !ssl->server,
- ssl3_protocol_version(ssl)) ||
+ if (!hs->transcript.GetFinishedMAC(finished, &finished_len,
+ SSL_get_session(ssl), !ssl->server,
+ ssl3_protocol_version(ssl)) ||
!ssl_hash_current_message(hs)) {
return -1;
}
@@ -593,9 +590,8 @@
/* The V2ClientHello without the length is incorporated into the handshake
* hash. This is only ever called at the start of the handshake, so hs is
* guaranteed to be non-NULL. */
- if (!SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript,
- CBS_data(&v2_client_hello),
- CBS_len(&v2_client_hello))) {
+ if (!ssl->s3->hs->transcript.Update(CBS_data(&v2_client_hello),
+ CBS_len(&v2_client_hello))) {
return -1;
}
@@ -758,7 +754,7 @@
CBS cbs;
hs->ssl->method->get_current_message(hs->ssl, &cbs);
- return SSL_TRANSCRIPT_update(&hs->transcript, CBS_data(&cbs), CBS_len(&cbs));
+ return hs->transcript.Update(CBS_data(&cbs), CBS_len(&cbs));
}
void ssl3_release_current_message(SSL *ssl, int free_buffer) {
diff --git a/ssl/ssl_transcript.cc b/ssl/ssl_transcript.cc
index cd62a3d..4a00d0f 100644
--- a/ssl/ssl_transcript.cc
+++ b/ssl/ssl_transcript.cc
@@ -152,136 +152,115 @@
namespace bssl {
-int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript) {
- SSL_TRANSCRIPT_cleanup(transcript);
- transcript->buffer = BUF_MEM_new();
- return transcript->buffer != NULL;
+SSLTranscript::SSLTranscript() {}
+
+SSLTranscript::~SSLTranscript() {}
+
+bool SSLTranscript::Init() {
+ buffer_.reset(BUF_MEM_new());
+ if (!buffer_) {
+ return false;
+ }
+
+ hash_.Reset();
+ md5_.Reset();
+ return true;
}
-/* init_digest_with_data calls |EVP_DigestInit_ex| on |ctx| with |md| and then
+/* InitDigestWithData calls |EVP_DigestInit_ex| on |ctx| with |md| and then
* writes the data in |buf| to it. */
-static int init_digest_with_data(EVP_MD_CTX *ctx, const EVP_MD *md,
- const BUF_MEM *buf) {
+static bool InitDigestWithData(EVP_MD_CTX *ctx, const EVP_MD *md,
+ const BUF_MEM *buf) {
if (!EVP_DigestInit_ex(ctx, md, NULL)) {
- return 0;
+ return false;
}
EVP_DigestUpdate(ctx, buf->data, buf->length);
- return 1;
+ return true;
}
-int SSL_TRANSCRIPT_init_hash(SSL_TRANSCRIPT *transcript, uint16_t version,
- int algorithm_prf) {
+bool SSLTranscript::InitHash(uint16_t version, int algorithm_prf) {
const EVP_MD *md = ssl_get_handshake_digest(algorithm_prf, version);
/* To support SSL 3.0's Finished and CertificateVerify constructions,
* EVP_md5_sha1() is split into MD5 and SHA-1 halves. When SSL 3.0 is removed,
* we can simplify this. */
if (md == EVP_md5_sha1()) {
- if (!init_digest_with_data(&transcript->md5, EVP_md5(),
- transcript->buffer)) {
- return 0;
+ if (!InitDigestWithData(md5_.get(), EVP_md5(), buffer_.get())) {
+ return false;
}
md = EVP_sha1();
}
- if (!init_digest_with_data(&transcript->hash, md, transcript->buffer)) {
- return 0;
- }
-
- return 1;
+ return InitDigestWithData(hash_.get(), md, buffer_.get());
}
-void SSL_TRANSCRIPT_cleanup(SSL_TRANSCRIPT *transcript) {
- SSL_TRANSCRIPT_free_buffer(transcript);
- EVP_MD_CTX_cleanup(&transcript->hash);
- EVP_MD_CTX_cleanup(&transcript->md5);
+void SSLTranscript::FreeBuffer() {
+ buffer_.reset();
}
-void SSL_TRANSCRIPT_free_buffer(SSL_TRANSCRIPT *transcript) {
- BUF_MEM_free(transcript->buffer);
- transcript->buffer = NULL;
+size_t SSLTranscript::DigestLen() const {
+ return EVP_MD_size(Digest());
}
-size_t SSL_TRANSCRIPT_digest_len(const SSL_TRANSCRIPT *transcript) {
- return EVP_MD_size(SSL_TRANSCRIPT_md(transcript));
-}
-
-const EVP_MD *SSL_TRANSCRIPT_md(const SSL_TRANSCRIPT *transcript) {
- if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
+const EVP_MD *SSLTranscript::Digest() const {
+ if (EVP_MD_CTX_md(md5_.get()) != nullptr) {
return EVP_md5_sha1();
}
- return EVP_MD_CTX_md(&transcript->hash);
+ return EVP_MD_CTX_md(hash_.get());
}
-int SSL_TRANSCRIPT_update(SSL_TRANSCRIPT *transcript, const uint8_t *in,
- size_t in_len) {
+bool SSLTranscript::Update(const uint8_t *in, size_t in_len) {
/* Depending on the state of the handshake, either the handshake buffer may be
* active, the rolling hash, or both. */
- if (transcript->buffer != NULL) {
- size_t new_len = transcript->buffer->length + in_len;
+ if (buffer_) {
+ size_t new_len = buffer_->length + in_len;
if (new_len < in_len) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
- return 0;
+ return false;
}
- if (!BUF_MEM_grow(transcript->buffer, new_len)) {
- return 0;
+ if (!BUF_MEM_grow(buffer_.get(), new_len)) {
+ return false;
}
- OPENSSL_memcpy(transcript->buffer->data + new_len - in_len, in, in_len);
+ OPENSSL_memcpy(buffer_->data + new_len - in_len, in, in_len);
}
- if (EVP_MD_CTX_md(&transcript->hash) != NULL) {
- EVP_DigestUpdate(&transcript->hash, in, in_len);
+ if (EVP_MD_CTX_md(hash_.get()) != NULL) {
+ EVP_DigestUpdate(hash_.get(), in, in_len);
}
- if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
- EVP_DigestUpdate(&transcript->md5, in, in_len);
+ if (EVP_MD_CTX_md(md5_.get()) != NULL) {
+ EVP_DigestUpdate(md5_.get(), in, in_len);
}
- return 1;
+ return true;
}
-int SSL_TRANSCRIPT_get_hash(const SSL_TRANSCRIPT *transcript, uint8_t *out,
- size_t *out_len) {
- int ret = 0;
- EVP_MD_CTX ctx;
- EVP_MD_CTX_init(&ctx);
+bool SSLTranscript::GetHash(uint8_t *out, size_t *out_len) {
+ ScopedEVP_MD_CTX ctx;
unsigned md5_len = 0;
- if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
- if (!EVP_MD_CTX_copy_ex(&ctx, &transcript->md5) ||
- !EVP_DigestFinal_ex(&ctx, out, &md5_len)) {
- goto err;
+ if (EVP_MD_CTX_md(md5_.get()) != NULL) {
+ if (!EVP_MD_CTX_copy_ex(ctx.get(), md5_.get()) ||
+ !EVP_DigestFinal_ex(ctx.get(), out, &md5_len)) {
+ return false;
}
}
unsigned len;
- if (!EVP_MD_CTX_copy_ex(&ctx, &transcript->hash) ||
- !EVP_DigestFinal_ex(&ctx, out + md5_len, &len)) {
- goto err;
+ if (!EVP_MD_CTX_copy_ex(ctx.get(), hash_.get()) ||
+ !EVP_DigestFinal_ex(ctx.get(), out + md5_len, &len)) {
+ return false;
}
*out_len = md5_len + len;
- ret = 1;
-
-err:
- EVP_MD_CTX_cleanup(&ctx);
- return ret;
+ return true;
}
-static int ssl3_handshake_mac(SSL_TRANSCRIPT *transcript,
- const SSL_SESSION *session,
- const EVP_MD_CTX *ctx_template,
- const char *sender, size_t sender_len,
- uint8_t *p, size_t *out_len) {
- unsigned int len;
- size_t npad, n;
- unsigned int i;
- uint8_t md_buf[EVP_MAX_MD_SIZE];
- EVP_MD_CTX ctx;
-
- EVP_MD_CTX_init(&ctx);
- if (!EVP_MD_CTX_copy_ex(&ctx, ctx_template)) {
- EVP_MD_CTX_cleanup(&ctx);
+static bool SSL3HandshakeMAC(const SSL_SESSION *session,
+ const EVP_MD_CTX *ctx_template, const char *sender,
+ size_t sender_len, uint8_t *p, size_t *out_len) {
+ ScopedEVP_MD_CTX ctx;
+ if (!EVP_MD_CTX_copy_ex(ctx.get(), ctx_template)) {
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
- return 0;
+ return false;
}
static const uint8_t kPad1[48] = {
@@ -298,89 +277,83 @@
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
};
- n = EVP_MD_CTX_size(&ctx);
+ size_t n = EVP_MD_CTX_size(ctx.get());
- npad = (48 / n) * n;
- if (sender != NULL) {
- EVP_DigestUpdate(&ctx, sender, sender_len);
- }
- EVP_DigestUpdate(&ctx, session->master_key, session->master_key_length);
- EVP_DigestUpdate(&ctx, kPad1, npad);
- EVP_DigestFinal_ex(&ctx, md_buf, &i);
+ size_t npad = (48 / n) * n;
+ EVP_DigestUpdate(ctx.get(), sender, sender_len);
+ EVP_DigestUpdate(ctx.get(), session->master_key, session->master_key_length);
+ EVP_DigestUpdate(ctx.get(), kPad1, npad);
+ unsigned md_buf_len;
+ uint8_t md_buf[EVP_MAX_MD_SIZE];
+ EVP_DigestFinal_ex(ctx.get(), md_buf, &md_buf_len);
- if (!EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL)) {
- EVP_MD_CTX_cleanup(&ctx);
+ if (!EVP_DigestInit_ex(ctx.get(), EVP_MD_CTX_md(ctx.get()), NULL)) {
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
- return 0;
+ return false;
}
- EVP_DigestUpdate(&ctx, session->master_key, session->master_key_length);
- EVP_DigestUpdate(&ctx, kPad2, npad);
- EVP_DigestUpdate(&ctx, md_buf, i);
- EVP_DigestFinal_ex(&ctx, p, &len);
-
- EVP_MD_CTX_cleanup(&ctx);
+ EVP_DigestUpdate(ctx.get(), session->master_key, session->master_key_length);
+ EVP_DigestUpdate(ctx.get(), kPad2, npad);
+ EVP_DigestUpdate(ctx.get(), md_buf, md_buf_len);
+ unsigned len;
+ EVP_DigestFinal_ex(ctx.get(), p, &len);
*out_len = len;
- return 1;
+ return true;
}
-int SSL_TRANSCRIPT_ssl3_cert_verify_hash(SSL_TRANSCRIPT *transcript,
- uint8_t *out, size_t *out_len,
- const SSL_SESSION *session,
- int signature_algorithm) {
- if (SSL_TRANSCRIPT_md(transcript) != EVP_md5_sha1()) {
+bool SSLTranscript::GetSSL3CertVerifyHash(uint8_t *out, size_t *out_len,
+ const SSL_SESSION *session,
+ uint16_t signature_algorithm) {
+ if (Digest() != EVP_md5_sha1()) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return false;
}
if (signature_algorithm == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
size_t md5_len, len;
- if (!ssl3_handshake_mac(transcript, session, &transcript->md5, NULL, 0, out,
- &md5_len) ||
- !ssl3_handshake_mac(transcript, session, &transcript->hash, NULL, 0,
- out + md5_len, &len)) {
- return 0;
+ if (!SSL3HandshakeMAC(session, md5_.get(), NULL, 0, out, &md5_len) ||
+ !SSL3HandshakeMAC(session, hash_.get(), NULL, 0, out + md5_len, &len)) {
+ return false;
}
*out_len = md5_len + len;
- return 1;
+ return true;
}
if (signature_algorithm == SSL_SIGN_ECDSA_SHA1) {
- return ssl3_handshake_mac(transcript, session, &transcript->hash, NULL, 0,
- out, out_len);
+ return SSL3HandshakeMAC(session, hash_.get(), NULL, 0, out, out_len);
}
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return false;
}
-int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out,
- size_t *out_len, const SSL_SESSION *session,
- int from_server, uint16_t version) {
+bool SSLTranscript::GetFinishedMAC(uint8_t *out, size_t *out_len,
+ const SSL_SESSION *session, bool from_server,
+ uint16_t version) {
if (version == SSL3_VERSION) {
- if (SSL_TRANSCRIPT_md(transcript) != EVP_md5_sha1()) {
+ if (Digest() != EVP_md5_sha1()) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return false;
}
const char *sender = from_server ? SSL3_MD_SERVER_FINISHED_CONST
: SSL3_MD_CLIENT_FINISHED_CONST;
const size_t sender_len = 4;
size_t md5_len, len;
- if (!ssl3_handshake_mac(transcript, session, &transcript->md5, sender,
- sender_len, out, &md5_len) ||
- !ssl3_handshake_mac(transcript, session, &transcript->hash, sender,
- sender_len, out + md5_len, &len)) {
- return 0;
+ if (!SSL3HandshakeMAC(session, md5_.get(), sender, sender_len, out,
+ &md5_len) ||
+ !SSL3HandshakeMAC(session, hash_.get(), sender, sender_len,
+ out + md5_len, &len)) {
+ return false;
}
*out_len = md5_len + len;
- return 1;
+ return true;
}
/* At this point, the handshake should have released the handshake buffer on
* its own. */
- assert(transcript->buffer == NULL);
+ assert(!buffer_);
const char *label = TLS_MD_CLIENT_FINISH_CONST;
size_t label_len = TLS_MD_SERVER_FINISH_CONST_SIZE;
@@ -391,19 +364,19 @@
uint8_t digests[EVP_MAX_MD_SIZE];
size_t digests_len;
- if (!SSL_TRANSCRIPT_get_hash(transcript, digests, &digests_len)) {
- return 0;
+ if (!GetHash(digests, &digests_len)) {
+ return false;
}
static const size_t kFinishedLen = 12;
- if (!tls1_prf(SSL_TRANSCRIPT_md(transcript), out, kFinishedLen,
- session->master_key, session->master_key_length, label,
- label_len, digests, digests_len, NULL, 0)) {
- return 0;
+ if (!tls1_prf(Digest(), out, kFinishedLen, session->master_key,
+ session->master_key_length, label, label_len, digests,
+ digests_len, NULL, 0)) {
+ return false;
}
*out_len = kFinishedLen;
- return 1;
+ return true;
}
} // namespace bssl
diff --git a/ssl/t1_enc.cc b/ssl/t1_enc.cc
index 4fbc6c4..2349df0 100644
--- a/ssl/t1_enc.cc
+++ b/ssl/t1_enc.cc
@@ -443,10 +443,9 @@
if (hs->extended_master_secret) {
uint8_t digests[EVP_MAX_MD_SIZE];
size_t digests_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, digests, &digests_len) ||
- !tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
- SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
- TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+ if (!hs->transcript.GetHash(digests, &digests_len) ||
+ !tls1_prf(hs->transcript.Digest(), out, SSL3_MASTER_SECRET_SIZE,
+ premaster, premaster_len, TLS_MD_EXTENDED_MASTER_SECRET_CONST,
TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests,
digests_len, NULL, 0)) {
return 0;
@@ -460,11 +459,11 @@
return 0;
}
} else {
- if (!tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
- SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
- TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE,
- ssl->s3->client_random, SSL3_RANDOM_SIZE,
- ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
+ if (!tls1_prf(hs->transcript.Digest(), out, SSL3_MASTER_SECRET_SIZE,
+ premaster, premaster_len, TLS_MD_MASTER_SECRET_CONST,
+ TLS_MD_MASTER_SECRET_CONST_SIZE, ssl->s3->client_random,
+ SSL3_RANDOM_SIZE, ssl->s3->server_random,
+ SSL3_RANDOM_SIZE)) {
return 0;
}
}
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index 118bc4a..b4cd964 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -3443,7 +3443,7 @@
uint8_t hs_hash[EVP_MAX_MD_SIZE];
size_t hs_hash_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, hs_hash, &hs_hash_len)) {
+ if (!hs->transcript.GetHash(hs_hash, &hs_hash_len)) {
return 0;
}
SHA256_Update(&ctx, hs_hash, (size_t)hs_hash_len);
@@ -3469,9 +3469,8 @@
"original_handshake_hash is too small");
size_t digest_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript,
- hs->new_session->original_handshake_hash,
- &digest_len)) {
+ if (!hs->transcript.GetHash(hs->new_session->original_handshake_hash,
+ &digest_len)) {
return -1;
}
diff --git a/ssl/tls13_both.cc b/ssl/tls13_both.cc
index 90fbf1c..338975b 100644
--- a/ssl/tls13_both.cc
+++ b/ssl/tls13_both.cc
@@ -181,8 +181,7 @@
uint8_t context_hash[EVP_MAX_MD_SIZE];
size_t context_hash_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
- &context_hash_len) ||
+ if (!hs->transcript.GetHash(context_hash, &context_hash_len) ||
!CBB_add_bytes(cbb.get(), context_hash, context_hash_len) ||
!CBB_finish(cbb.get(), out, out_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
diff --git a/ssl/tls13_enc.cc b/ssl/tls13_enc.cc
index 14dbb9d..1ae4849 100644
--- a/ssl/tls13_enc.cc
+++ b/ssl/tls13_enc.cc
@@ -34,11 +34,11 @@
static int init_key_schedule(SSL_HANDSHAKE *hs, uint16_t version,
int algorithm_prf) {
- if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, version, algorithm_prf)) {
+ if (!hs->transcript.InitHash(version, algorithm_prf)) {
return 0;
}
- hs->hash_len = SSL_TRANSCRIPT_digest_len(&hs->transcript);
+ hs->hash_len = hs->transcript.DigestLen();
/* Initialize the secret to the zero key. */
OPENSSL_memset(hs->secret, 0, hs->hash_len);
@@ -52,7 +52,7 @@
return 0;
}
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
return 1;
}
@@ -64,9 +64,8 @@
int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
size_t len) {
- return HKDF_extract(hs->secret, &hs->hash_len,
- SSL_TRANSCRIPT_md(&hs->transcript), in, len, hs->secret,
- hs->hash_len);
+ return HKDF_extract(hs->secret, &hs->hash_len, hs->transcript.Digest(), in,
+ len, hs->secret, hs->hash_len);
}
static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest,
@@ -105,12 +104,11 @@
const uint8_t *label, size_t label_len) {
uint8_t context_hash[EVP_MAX_MD_SIZE];
size_t context_hash_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
- &context_hash_len)) {
+ if (!hs->transcript.GetHash(context_hash, &context_hash_len)) {
return 0;
}
- return hkdf_expand_label(out, SSL_TRANSCRIPT_md(&hs->transcript), hs->secret,
+ return hkdf_expand_label(out, hs->transcript.Digest(), hs->secret,
hs->hash_len, label, label_len, context_hash,
context_hash_len, len);
}
@@ -313,11 +311,9 @@
uint8_t context_hash[EVP_MAX_MD_SIZE];
size_t context_hash_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
- &context_hash_len) ||
- !tls13_verify_data(SSL_TRANSCRIPT_md(&hs->transcript), out, out_len,
- traffic_secret, hs->hash_len, context_hash,
- context_hash_len)) {
+ if (!hs->transcript.GetHash(context_hash, &context_hash_len) ||
+ !tls13_verify_data(hs->transcript.Digest(), out, out_len, traffic_secret,
+ hs->hash_len, context_hash, context_hash_len)) {
return 0;
}
return 1;
@@ -387,8 +383,8 @@
uint8_t context[EVP_MAX_MD_SIZE];
unsigned context_len;
if (!EVP_DigestInit_ex(ctx.get(), digest, NULL) ||
- !EVP_DigestUpdate(ctx.get(), hs->transcript.buffer->data,
- hs->transcript.buffer->length) ||
+ !EVP_DigestUpdate(ctx.get(), hs->transcript.buffer_data(),
+ hs->transcript.buffer_len()) ||
!EVP_DigestUpdate(ctx.get(), msg, len - hash_len - 3) ||
!EVP_DigestFinal_ex(ctx.get(), context, &context_len)) {
return 0;
@@ -407,7 +403,7 @@
int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
CBS *binders) {
- size_t hash_len = SSL_TRANSCRIPT_digest_len(&hs->transcript);
+ size_t hash_len = hs->transcript.DigestLen();
/* Get the full ClientHello, including message header. It must be large enough
* to exclude the binders. */
@@ -423,14 +419,13 @@
uint8_t context[EVP_MAX_MD_SIZE];
unsigned context_len;
if (!EVP_Digest(CBS_data(&message), CBS_len(&message) - CBS_len(binders) - 2,
- context, &context_len, SSL_TRANSCRIPT_md(&hs->transcript),
- NULL)) {
+ context, &context_len, hs->transcript.Digest(), NULL)) {
return 0;
}
uint8_t verify_data[EVP_MAX_MD_SIZE] = {0};
CBS binder;
- if (!tls13_psk_binder(verify_data, SSL_TRANSCRIPT_md(&hs->transcript),
+ if (!tls13_psk_binder(verify_data, hs->transcript.Digest(),
session->master_key, session->master_key_length,
context, context_len, hash_len) ||
/* We only consider the first PSK, so compare against the first binder. */
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index e455d68..067c427 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -671,12 +671,11 @@
* TODO(davidben): This will need to be updated for DTLS 1.3. */
assert(!SSL_is_dtls(hs->ssl));
assert(hs->hash_len <= 0xff);
- uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0, static_cast<uint8_t>(hs->hash_len)};
- if (!SSL_TRANSCRIPT_update(&hs->transcript, header, sizeof(header)) ||
- !SSL_TRANSCRIPT_update(&hs->transcript, hs->expected_client_finished,
- hs->hash_len) ||
- !tls13_derive_resumption_secret(hs) ||
- !add_new_session_tickets(hs)) {
+ uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0,
+ static_cast<uint8_t>(hs->hash_len)};
+ if (!hs->transcript.Update(header, sizeof(header)) ||
+ !hs->transcript.Update(hs->expected_client_finished, hs->hash_len) ||
+ !tls13_derive_resumption_secret(hs) || !add_new_session_tickets(hs)) {
return ssl_hs_error;
}
}