summaryrefslogtreecommitdiffstats
path: root/ssl/t1_enc.c
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2015-11-25 18:20:50 +0000
committerDr. Stephen Henson <steve@openssl.org>2015-11-27 19:04:14 +0000
commit28ba2541f9f5e61ddef548d3bead494ff6946db2 (patch)
tree62ce07aee098ea394943f63e20e829a702961ce0 /ssl/t1_enc.c
parent2a9b96548afc0d540ab873a31dc1a72c66cba434 (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.c81
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,