From 28ba2541f9f5e61ddef548d3bead494ff6946db2 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 25 Nov 2015 18:20:50 +0000 Subject: [PATCH] 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 --- ssl/s3_enc.c | 144 ++++++++++++------------------------------------- ssl/ssl_algs.c | 3 ++ ssl/ssl_ciph.c | 48 +++++++---------- ssl/ssl_lib.c | 26 +++------ ssl/ssl_locl.h | 67 +++++++++++++---------- ssl/t1_enc.c | 81 ++++++++++++---------------- 6 files changed, 138 insertions(+), 231 deletions(-) diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index b801d0541b..bb900e9ca8 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -140,26 +140,6 @@ #include #include -static const unsigned char ssl3_pad_1[48] = { - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 -}; - -static const unsigned char ssl3_pad_2[48] = { - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c -}; - -static int ssl3_handshake_mac(SSL *s, int md_nid, - const char *sender, int len, unsigned char *p); static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num) { EVP_MD_CTX m5; @@ -488,69 +468,48 @@ void ssl3_init_finished_mac(SSL *s) void ssl3_free_digest_list(SSL *s) { - int i; BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; - if (!s->s3->handshake_dgst) - return; - for (i = 0; i < SSL_MAX_DIGEST; i++) { - if (s->s3->handshake_dgst[i]) - EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]); - } - OPENSSL_free(s->s3->handshake_dgst); + EVP_MD_CTX_destroy(s->s3->handshake_dgst); s->s3->handshake_dgst = NULL; } void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len) { - if (s->s3->handshake_dgst == NULL) { + if (s->s3->handshake_dgst == NULL) BIO_write(s->s3->handshake_buffer, (void *)buf, len); - } else { - int i; - for (i = 0; i < SSL_MAX_DIGEST; i++) { - if (s->s3->handshake_dgst[i] != NULL) - EVP_DigestUpdate(s->s3->handshake_dgst[i], buf, len); - } - } + else + EVP_DigestUpdate(s->s3->handshake_dgst, buf, len); } int ssl3_digest_cached_records(SSL *s, int keep) { - int i; - long mask; const EVP_MD *md; long hdatalen; void *hdata; if (s->s3->handshake_dgst == NULL) { - /* Allocate handshake_dgst array */ - s->s3->handshake_dgst = - OPENSSL_malloc(sizeof(*s->s3->handshake_dgst) * SSL_MAX_DIGEST); - if (s->s3->handshake_dgst == NULL) { - SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE); - return 0; - } hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); if (hdatalen <= 0) { SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH); return 0; } - /* Loop through bits of algorithm2 field and create MD_CTX-es */ - for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) { - if ((mask & ssl_get_algorithm2(s)) && md) { - s->s3->handshake_dgst[i] = EVP_MD_CTX_create(); - if (EVP_MD_nid(md) == NID_md5) { - EVP_MD_CTX_set_flags(s->s3->handshake_dgst[i], - EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - } - EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL); - EVP_DigestUpdate(s->s3->handshake_dgst[i], hdata, hdatalen); - } else { - s->s3->handshake_dgst[i] = NULL; - } + s->s3->handshake_dgst = EVP_MD_CTX_create(); + if (s->s3->handshake_dgst == NULL) { + SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE); + return 0; } + md = ssl_handshake_md(s); + if (md == NULL) { + SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_INTERNAL_ERROR); + return 0; + } + + EVP_DigestInit_ex(s->s3->handshake_dgst, md, NULL); + EVP_DigestUpdate(s->s3->handshake_dgst, hdata, hdatalen); + } if (keep == 0) { BIO_free(s->s3->handshake_buffer); @@ -560,77 +519,40 @@ int ssl3_digest_cached_records(SSL *s, int keep) return 1; } -int ssl3_final_finish_mac(SSL *s, - const char *sender, int len, unsigned char *p) +int ssl3_final_finish_mac(SSL *s, const char *sender, int len, unsigned char *p) { - int ret, sha1len; - ret = ssl3_handshake_mac(s, NID_md5, sender, len, p); - if (ret == 0) - return 0; - - p += ret; - - sha1len = ssl3_handshake_mac(s, NID_sha1, sender, len, p); - if (sha1len == 0) - return 0; - - ret += sha1len; - return (ret); -} - -static int ssl3_handshake_mac(SSL *s, int md_nid, - const char *sender, int len, unsigned char *p) -{ - unsigned int ret; - int npad, n; - unsigned int i; - unsigned char md_buf[EVP_MAX_MD_SIZE]; - EVP_MD_CTX ctx, *d = NULL; + int ret; + EVP_MD_CTX ctx; if (!ssl3_digest_cached_records(s, 0)) return 0; - /* - * Search for digest of specified type in the handshake_dgst array - */ - for (i = 0; i < SSL_MAX_DIGEST; i++) { - if (s->s3->handshake_dgst[i] - && EVP_MD_CTX_type(s->s3->handshake_dgst[i]) == md_nid) { - d = s->s3->handshake_dgst[i]; - break; - } - } - if (!d) { + if (EVP_MD_CTX_type(s->s3->handshake_dgst) != NID_md5_sha1) { SSLerr(SSL_F_SSL3_HANDSHAKE_MAC, SSL_R_NO_REQUIRED_DIGEST); return 0; } + EVP_MD_CTX_init(&ctx); - EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - EVP_MD_CTX_copy_ex(&ctx, d); - n = EVP_MD_CTX_size(&ctx); - if (n < 0) + EVP_MD_CTX_copy_ex(&ctx, s->s3->handshake_dgst); + + ret = EVP_MD_CTX_size(&ctx); + if (ret < 0) { + EVP_MD_CTX_cleanup(&ctx); return 0; + } - npad = (48 / n) * n; if ((sender != NULL && EVP_DigestUpdate(&ctx, sender, len) <= 0) - || EVP_DigestUpdate(&ctx, s->session->master_key, - s->session->master_key_length) <= 0 - || EVP_DigestUpdate(&ctx, ssl3_pad_1, npad) <= 0 - || EVP_DigestFinal_ex(&ctx, md_buf, &i) <= 0 - - || EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL) <= 0 - || EVP_DigestUpdate(&ctx, s->session->master_key, - s->session->master_key_length) <= 0 - || EVP_DigestUpdate(&ctx, ssl3_pad_2, npad) <= 0 - || EVP_DigestUpdate(&ctx, md_buf, i) <= 0 - || EVP_DigestFinal_ex(&ctx, p, &ret) <= 0) { + || EVP_MD_CTX_ctrl(&ctx, EVP_CTRL_SSL3_MASTER_SECRET, + s->session->master_key_length, + s->session->master_key) <= 0 + || EVP_DigestFinal_ex(&ctx, p, NULL) <= 0) { SSLerr(SSL_F_SSL3_HANDSHAKE_MAC, ERR_R_INTERNAL_ERROR); ret = 0; } EVP_MD_CTX_cleanup(&ctx); - return ((int)ret); + return ret; } int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c index f4827fd787..9c12e19e17 100644 --- a/ssl/ssl_algs.c +++ b/ssl/ssl_algs.c @@ -110,6 +110,9 @@ int SSL_library_init(void) #ifndef OPENSSL_NO_MD5 EVP_add_digest(EVP_md5()); EVP_add_digest_alias(SN_md5, "ssl3-md5"); +# ifndef OPENSSL_NO_SHA + EVP_add_digest(EVP_md5_sha1()); +# endif #endif EVP_add_digest(EVP_sha1()); /* RSA with sha1 */ EVP_add_digest_alias(SN_sha1, "ssl3-sha1"); diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 47f5e0f130..4e3c1e505f 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -212,15 +212,6 @@ static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX] = { static STACK_OF(SSL_COMP) *ssl_comp_methods = NULL; -#define SSL_MD_MD5_IDX 0 -#define SSL_MD_SHA1_IDX 1 -#define SSL_MD_GOST94_IDX 2 -#define SSL_MD_GOST89MAC_IDX 3 -#define SSL_MD_SHA256_IDX 4 -#define SSL_MD_SHA384_IDX 5 -#define SSL_MD_GOST12_256_IDX 6 -#define SSL_MD_GOST89MAC12_IDX 7 -#define SSL_MD_GOST12_512_IDX 8 /* * Constant SSL_MAX_DIGEST equal to size of digests array should be defined * in the ssl_locl.h @@ -238,11 +229,12 @@ static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = { {SSL_SHA384, NID_sha384}, /* SSL_MD_SHA384_IDX 5 */ {SSL_GOST12_256, NID_id_GostR3411_2012_256}, /* SSL_MD_GOST12_256_IDX 6 */ {SSL_GOST89MAC12, NID_gost_mac_12}, /* SSL_MD_GOST89MAC12_IDX 7 */ - {SSL_GOST12_512, NID_id_GostR3411_2012_512} /* SSL_MD_GOST12_512_IDX 8 */ + {SSL_GOST12_512, NID_id_GostR3411_2012_512}, /* SSL_MD_GOST12_512_IDX 8 */ + {0, NID_md5_sha1} /* SSL_MD_MD5_SHA1_IDX 9 */ }; static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* Utility function for table lookup */ @@ -275,14 +267,7 @@ static int ssl_mac_pkey_id[SSL_MD_NUM_IDX] = { }; static int ssl_mac_secret_size[SSL_MD_NUM_IDX] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const int ssl_handshake_digest_flag[SSL_MD_NUM_IDX] = { - SSL_HANDSHAKE_MAC_MD5, SSL_HANDSHAKE_MAC_SHA, - SSL_HANDSHAKE_MAC_GOST94, 0, SSL_HANDSHAKE_MAC_SHA256, - SSL_HANDSHAKE_MAC_SHA384, SSL_HANDSHAKE_MAC_GOST12_256, 0, - SSL_HANDSHAKE_MAC_GOST12_512, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #define CIPHER_ADD 1 @@ -727,17 +712,22 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, return (0); } -int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md) +static const EVP_MD *ssl_cipher_table_idx(int idx) { - if (idx < 0 || idx >= SSL_MD_NUM_IDX) { - return 0; - } - *mask = ssl_handshake_digest_flag[idx]; - if (*mask) - *md = ssl_digest_methods[idx]; - else - *md = NULL; - return 1; + idx &= SSL_HANDSHAKE_MAC_MASK; + if (idx < 0 || idx >= SSL_MD_NUM_IDX) + return NULL; + return ssl_digest_methods[idx]; +} + +const EVP_MD *ssl_handshake_md(SSL *s) +{ + return ssl_cipher_table_idx(ssl_get_algorithm2(s)); +} + +const EVP_MD *ssl_prf_md(SSL *s) +{ + return ssl_cipher_table_idx(ssl_get_algorithm2(s) >> TLS1_PRF_DGST_SHIFT); } #define ITEM_SEP(a) \ diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index a9370dcb87..12ae35cf8c 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -3335,27 +3335,17 @@ void ssl_clear_hash_ctx(EVP_MD_CTX **hash) /* Retrieve handshake hashes */ int ssl_handshake_hash(SSL *s, unsigned char *out, int outlen) { - unsigned char *p = out; - int idx, ret = 0; - long mask; EVP_MD_CTX ctx; - const EVP_MD *md; + EVP_MD_CTX *hdgst = s->s3->handshake_dgst; + int ret = EVP_MD_CTX_size(hdgst); EVP_MD_CTX_init(&ctx); - for (idx = 0; ssl_get_handshake_digest(idx, &mask, &md); idx++) { - if (mask & ssl_get_algorithm2(s)) { - int hashsize = EVP_MD_size(md); - EVP_MD_CTX *hdgst = s->s3->handshake_dgst[idx]; - if (!hdgst || hashsize < 0 || hashsize > outlen) - goto err; - if (!EVP_MD_CTX_copy_ex(&ctx, hdgst)) - goto err; - if (!EVP_DigestFinal_ex(&ctx, p, NULL)) - goto err; - p += hashsize; - outlen -= hashsize; - } + if (ret < 0 || ret > outlen) { + ret = 0; + goto err; } - ret = p - out; + if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) + || EVP_DigestFinal_ex(&ctx, out, NULL) <= 0) + ret = 0; err: EVP_MD_CTX_cleanup(&ctx); return ret; diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 70689bc324..0cbb3cc57f 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -391,38 +391,50 @@ # define SSL_TLSV1 0x00000004U # define SSL_TLSV1_2 0x00000008U -/* Bits for algorithm2 (handshake digests and other extra flags) */ - -# define SSL_HANDSHAKE_MAC_MD5 0x10 -# define SSL_HANDSHAKE_MAC_SHA 0x20 -# define SSL_HANDSHAKE_MAC_GOST94 0x40 -# define SSL_HANDSHAKE_MAC_SHA256 0x80 -# define SSL_HANDSHAKE_MAC_SHA384 0x100 -# define SSL_HANDSHAKE_MAC_GOST12_256 0x200 -# define SSL_HANDSHAKE_MAC_GOST12_512 0x400 -# define SSL_HANDSHAKE_MAC_DEFAULT (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA) - /* * When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make * sure to update this constant too */ -# define SSL_MAX_DIGEST 9 - -# define TLS1_PRF_DGST_SHIFT 10 -# define TLS1_PRF_MD5 (SSL_HANDSHAKE_MAC_MD5 << TLS1_PRF_DGST_SHIFT) -# define TLS1_PRF_SHA1 (SSL_HANDSHAKE_MAC_SHA << TLS1_PRF_DGST_SHIFT) -# define TLS1_PRF_SHA256 (SSL_HANDSHAKE_MAC_SHA256 << TLS1_PRF_DGST_SHIFT) -# define TLS1_PRF_SHA384 (SSL_HANDSHAKE_MAC_SHA384 << TLS1_PRF_DGST_SHIFT) -# define TLS1_PRF_GOST94 (SSL_HANDSHAKE_MAC_GOST94 << TLS1_PRF_DGST_SHIFT) -# define TLS1_PRF_GOST12_256 (SSL_HANDSHAKE_MAC_GOST12_256 << TLS1_PRF_DGST_SHIFT) -# define TLS1_PRF_GOST12_512 (SSL_HANDSHAKE_MAC_GOST12_512 << TLS1_PRF_DGST_SHIFT) -# define TLS1_PRF (TLS1_PRF_MD5 | TLS1_PRF_SHA1) + +# define SSL_MD_MD5_IDX 0 +# define SSL_MD_SHA1_IDX 1 +# define SSL_MD_GOST94_IDX 2 +# define SSL_MD_GOST89MAC_IDX 3 +# define SSL_MD_SHA256_IDX 4 +# define SSL_MD_SHA384_IDX 5 +# define SSL_MD_GOST12_256_IDX 6 +# define SSL_MD_GOST89MAC12_IDX 7 +# define SSL_MD_GOST12_512_IDX 8 +# define SSL_MD_MD5_SHA1_IDX 9 +# define SSL_MAX_DIGEST 10 + +/* Bits for algorithm2 (handshake digests and other extra flags) */ + +/* Bits 0-7 are handshake MAC */ +# define SSL_HANDSHAKE_MAC_MASK 0xFF +# define SSL_HANDSHAKE_MAC_MD5_SHA1 SSL_MD_MD5_SHA1_IDX +# define SSL_HANDSHAKE_MAC_SHA256 SSL_MD_SHA256_IDX +# define SSL_HANDSHAKE_MAC_SHA384 SSL_MD_SHA384_IDX +# define SSL_HANDSHAKE_MAC_GOST94 SSL_MD_GOST94_IDX +# define SSL_HANDSHAKE_MAC_GOST12_256 SSL_MD_GOST12_256_IDX +# define SSL_HANDSHAKE_MAC_GOST12_512 SSL_MD_GOST12_512_IDX +# define SSL_HANDSHAKE_MAC_DEFAULT SSL_HANDSHAKE_MAC_MD5_SHA1 + +/* Bits 8-15 bits are PRF */ +# define TLS1_PRF_DGST_SHIFT 8 +# define TLS1_PRF_SHA1_MD5 (SSL_MD_MD5_SHA1_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_SHA256 (SSL_MD_SHA256_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_SHA384 (SSL_MD_SHA384_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_GOST94 (SSL_MD_GOST94_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_GOST12_256 (SSL_MD_GOST12_256_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF_GOST12_512 (SSL_MD_GOST12_512_IDX << TLS1_PRF_DGST_SHIFT) +# define TLS1_PRF (SSL_MD_MD5_SHA1_IDX << TLS1_PRF_DGST_SHIFT) /* * Stream MAC for GOST ciphersuites from cryptopro draft (currently this also * goes into algorithm2) */ -# define TLS1_STREAM_MAC 0x04 +# define TLS1_STREAM_MAC 0x10000 /* * Export and cipher strength information. For each cipher we have to decide @@ -1239,10 +1251,10 @@ typedef struct ssl3_state_st { /* used during startup, digest all incoming/outgoing packets */ BIO *handshake_buffer; /* - * When set of handshake digests is determined, buffer is hashed and - * freed and MD_CTX-es for all required digests are stored in this array + * When handshake digest is determined, buffer is hashed and + * freed and MD_CTX for the required digest is stored here. */ - EVP_MD_CTX **handshake_dgst; + EVP_MD_CTX *handshake_dgst; /* * Set whenever an expected ChangeCipherSpec message is processed. * Unset when the peer's Finished message is received. @@ -1890,7 +1902,6 @@ void ssl_update_cache(SSL *s, int mode); __owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size, SSL_COMP **comp, int use_etm); -__owur int ssl_get_handshake_digest(int i, long *mask, const EVP_MD **md); __owur int ssl_cipher_get_cert_index(const SSL_CIPHER *c); __owur const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl, const unsigned char *ptr); __owur int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain); @@ -2128,6 +2139,8 @@ __owur int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, __owur int ssl_parse_serverhello_use_srtp_ext(SSL *s, PACKET *pkt, int *al); __owur int ssl_handshake_hash(SSL *s, unsigned char *out, int outlen); +__owur const EVP_MD *ssl_handshake_md(SSL *s); +__owur const EVP_MD *ssl_prf_md(SSL *s); /* s3_cbc.c */ __owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); 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, -- 2.34.1