Compute the Channel ID hash after ssl_get_message.

This avoids needing the save the hash on the SSL* (and use some field for two
purposes). Instead, use the new SSL_GET_MESSAGE_DONT_HASH_MESSAGE flag (which
actually was already used here, but at the time, pointlessly). Also fix a minor
bug where the hash would be recomputed in non-blocking mode because init_num
may stay zero for a few state machine iterations.

Change-Id: I3d8331cf3134c5f9a3eda9e988bba5bcebe40933
Reviewed-on: https://boringssl-review.googlesource.com/1631
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
David Benjamin 2014-08-25 22:35:07 -04:00 committed by Adam Langley
parent 590cbe970c
commit 880b14e98c

View File

@ -148,6 +148,7 @@
#define NETSCAPE_HANG_BUG
#include <assert.h>
#include <stdio.h>
#include <string.h>
@ -2880,6 +2881,9 @@ int ssl3_get_channel_id(SSL *s)
{
int ret = -1, ok;
long n;
EVP_MD_CTX md_ctx;
uint8_t channel_id_hash[SHA256_DIGEST_LENGTH];
unsigned int channel_id_hash_len;
const uint8_t *p;
uint16_t extension_type, expected_extension_type;
EC_GROUP* p256 = NULL;
@ -2889,22 +2893,6 @@ int ssl3_get_channel_id(SSL *s)
BIGNUM x, y;
CBS encrypted_extensions, extension;
if (s->state == SSL3_ST_SR_CHANNEL_ID_A && s->init_num == 0)
{
/* The first time that we're called we take the current
* handshake hash and store it. */
EVP_MD_CTX md_ctx;
unsigned int len;
EVP_MD_CTX_init(&md_ctx);
EVP_DigestInit_ex(&md_ctx, EVP_sha256(), NULL);
if (!tls1_channel_id_hash(&md_ctx, s))
return -1;
len = sizeof(s->s3->tlsext_channel_id);
EVP_DigestFinal(&md_ctx, s->s3->tlsext_channel_id, &len);
EVP_MD_CTX_cleanup(&md_ctx);
}
n = s->method->ssl_get_message(s,
SSL3_ST_SR_CHANNEL_ID_A,
SSL3_ST_SR_CHANNEL_ID_B,
@ -2916,7 +2904,21 @@ int ssl3_get_channel_id(SSL *s)
if (!ok)
return((int)n);
ssl3_finish_mac(s, (unsigned char*)s->init_buf->data, s->init_num + 4);
/* Before incorporating the EncryptedExtensions message to the
* handshake hash, compute the hash that should have been signed. */
channel_id_hash_len = sizeof(channel_id_hash);
EVP_MD_CTX_init(&md_ctx);
if (!EVP_DigestInit_ex(&md_ctx, EVP_sha256(), NULL) ||
!tls1_channel_id_hash(&md_ctx, s) ||
!EVP_DigestFinal(&md_ctx, channel_id_hash, &channel_id_hash_len))
{
EVP_MD_CTX_cleanup(&md_ctx);
return -1;
}
EVP_MD_CTX_cleanup(&md_ctx);
assert(channel_id_hash_len == SHA256_DIGEST_LENGTH);
ssl3_hash_current_message(s);
/* s->state doesn't reflect whether ChangeCipherSpec has been received
* in this handshake, but s->s3->change_cipher_spec does (will be reset
@ -2989,7 +2991,7 @@ int ssl3_get_channel_id(SSL *s)
/* We stored the handshake hash in |tlsext_channel_id| the first time
* that we were called. */
if (!ECDSA_do_verify(s->s3->tlsext_channel_id, SHA256_DIGEST_LENGTH, &sig, key))
if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key))
{
OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
s->s3->tlsext_channel_id_valid = 0;