diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2015-11-25 18:20:50 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2015-11-27 19:04:14 +0000 |
commit | 28ba2541f9f5e61ddef548d3bead494ff6946db2 (patch) | |
tree | 62ce07aee098ea394943f63e20e829a702961ce0 /ssl/t1_enc.c | |
parent | 2a9b96548afc0d540ab873a31dc1a72c66cba434 (diff) |
PRF and handshake hash revision.
Change handshake hash array into a single digest context simplifying the
handhake hash code. Use EVP_md5_sha1() if needed for handshake hashes in
TLS 1.1 and earlier.
Simplify PRF code to also use a single digest and treat EVP_md5_sha1()
as a special case.
Modify algorithm2 field of ciphers to use a single index value for handshake
hash and PRF instead of a bitmap.
Reviewed-by: Matt Caswell <matt@openssl.org>
Diffstat (limited to 'ssl/t1_enc.c')
-rw-r--r-- | ssl/t1_enc.c | 81 |
1 files changed, 35 insertions, 46 deletions
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 906029c8fc..ae1d36c71e 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -236,7 +236,7 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, } /* seed1 through seed5 are virtually concatenated */ -static int tls1_PRF(long digest_mask, +static int tls1_PRF(SSL *s, const void *seed1, int seed1_len, const void *seed2, int seed2_len, const void *seed3, int seed3_len, @@ -245,55 +245,44 @@ static int tls1_PRF(long digest_mask, const unsigned char *sec, int slen, unsigned char *out1, unsigned char *out2, int olen) { - int len, i, idx, count; - const unsigned char *S1; - long m; - const EVP_MD *md; - int ret = 0; + const EVP_MD *md = ssl_prf_md(s); - /* Count number of digests and partition sec evenly */ - count = 0; - for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) { - if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask) - count++; - } - if (!count) { + if (md == NULL) { /* Should never happen */ SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR); - goto err; + return 0; } - len = slen / count; - if (count == 1) - slen = 0; - S1 = sec; - memset(out1, 0, olen); - for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) { - if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask) { - if (!md) { - SSLerr(SSL_F_TLS1_PRF, SSL_R_UNSUPPORTED_DIGEST_TYPE); - goto err; - } - if (!tls1_P_hash(md, S1, len + (slen & 1), - seed1, seed1_len, seed2, seed2_len, seed3, - seed3_len, seed4, seed4_len, seed5, seed5_len, - out2, olen)) - goto err; - S1 += len; - for (i = 0; i < olen; i++) { - out1[i] ^= out2[i]; - } - } + if (EVP_MD_type(md) == NID_md5_sha1) { + int i; + if (!tls1_P_hash(EVP_md5(), sec, slen/2 + (slen & 1), + seed1, seed1_len, seed2, seed2_len, seed3, + seed3_len, seed4, seed4_len, seed5, seed5_len, + out1, olen)) + return 0; + if (!tls1_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1), + seed1, seed1_len, seed2, seed2_len, seed3, + seed3_len, seed4, seed4_len, seed5, seed5_len, + out2, olen)) + return 0; + for (i = 0; i < olen; i++) + out1[i] ^= out2[i]; + return 1; } - ret = 1; - err: - return ret; + memset(out2, 0, olen); + if (!tls1_P_hash(md, sec, slen, + seed1, seed1_len, seed2, seed2_len, seed3, + seed3_len, seed4, seed4_len, seed5, seed5_len, + out1, olen)) + return 0; + + return 1; } static int tls1_generate_key_block(SSL *s, unsigned char *km, unsigned char *tmp, int num) { int ret; - ret = tls1_PRF(ssl_get_algorithm2(s), + ret = tls1_PRF(s, TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE, @@ -489,7 +478,7 @@ int tls1_change_cipher_state(SSL *s, int which) * In here I set both the read and write key/iv to the same value * since only the correct one will be used :-). */ - if (!tls1_PRF(ssl_get_algorithm2(s), + if (!tls1_PRF(s, exp_label, exp_label_len, s->s3->client_random, SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE, @@ -499,7 +488,7 @@ int tls1_change_cipher_state(SSL *s, int which) key = tmp1; if (k > 0) { - if (!tls1_PRF(ssl_get_algorithm2(s), + if (!tls1_PRF(s, TLS_MD_IV_BLOCK_CONST, TLS_MD_IV_BLOCK_CONST_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE, @@ -702,7 +691,7 @@ int tls1_final_finish_mac(SSL *s, const char *str, int slen, unsigned char *out) { int hashlen; - unsigned char hash[2 * EVP_MAX_MD_SIZE]; + unsigned char hash[EVP_MAX_MD_SIZE]; unsigned char buf2[12]; if (!ssl3_digest_cached_records(s, 0)) @@ -713,7 +702,7 @@ int tls1_final_finish_mac(SSL *s, const char *str, int slen, if (hashlen == 0) return 0; - if (!tls1_PRF(ssl_get_algorithm2(s), + if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0, s->session->master_key, s->session->master_key_length, out, buf2, sizeof buf2)) @@ -743,7 +732,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, fprintf(stderr, "Handshake hashes:\n"); BIO_dump_fp(stderr, (char *)hash, hashlen); #endif - tls1_PRF(ssl_get_algorithm2(s), + tls1_PRF(s, TLS_MD_EXTENDED_MASTER_SECRET_CONST, TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, hash, hashlen, @@ -752,7 +741,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, NULL, 0, p, len, s->session->master_key, buff, sizeof buff); OPENSSL_cleanse(hash, hashlen); } else { - tls1_PRF(ssl_get_algorithm2(s), + tls1_PRF(s, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE, @@ -858,7 +847,7 @@ int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen, TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) goto err1; - rv = tls1_PRF(ssl_get_algorithm2(s), + rv = tls1_PRF(s, val, vallen, NULL, 0, NULL, 0, |