Add the PRF to SSL3_ENC_METHOD. This lets us fold away the SSLv3-specific generate_master_secret. Once SSLv3 uses AEADs, others will fold away as well. Change-Id: I27c1b75741823bc6db920d35f5dd5ce71b6fdbb3 Reviewed-on: https://boringssl-review.googlesource.com/2697 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 456481b..1404be0 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h
@@ -2269,7 +2269,7 @@ #define SSL_F_ssl3_connect 128 #define SSL_F_dtls1_connect 129 #define SSL_F_SSL_use_RSAPrivateKey 130 -#define SSL_F_tls1_PRF 131 +#define SSL_F_tls1_prf 131 #define SSL_F_ssl_bytes_to_cipher_list 132 #define SSL_F_ssl3_do_change_cipher_spec 133 #define SSL_F_SSL_SESSION_set1_id_context 134 @@ -2435,7 +2435,7 @@ #define SSL_F_ssl3_get_v2_client_hello 295 #define SSL_F_ssl3_get_initial_bytes 296 #define SSL_F_tls1_enc 297 -#define SSL_F_ssl3_PRF 298 +#define SSL_F_ssl3_prf 298 #define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 100 #define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 101 #define SSL_R_INVALID_NULL_CMD_NAME 102
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index 5869cdf..7e76905 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c
@@ -79,6 +79,7 @@ const SSL3_ENC_METHOD DTLSv1_enc_data = { tls1_enc, tls1_mac, + tls1_prf, tls1_setup_key_block, tls1_generate_master_secret, tls1_change_cipher_state, @@ -98,6 +99,7 @@ const SSL3_ENC_METHOD DTLSv1_2_enc_data = { tls1_enc, tls1_mac, + tls1_prf, tls1_setup_key_block, tls1_generate_master_secret, tls1_change_cipher_state,
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 68684b3..9e3f5f2 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c
@@ -162,10 +162,10 @@ static int ssl3_handshake_mac(SSL *s, int md_nid, const char *sender, int len, uint8_t *p); -static int ssl3_PRF(uint8_t *out, size_t out_len, - const uint8_t *secret, size_t secret_len, - const uint8_t *seed1, size_t seed1_len, - const uint8_t *seed2, size_t seed2_len) { +int ssl3_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret, + size_t secret_len, const char *label, size_t label_len, + const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len) { EVP_MD_CTX md5; EVP_MD_CTX sha1; uint8_t buf[16], smd[SHA_DIGEST_LENGTH]; @@ -179,7 +179,7 @@ k++; if (k > sizeof(buf)) { /* bug: 'buf' is too small for this ciphersuite */ - OPENSSL_PUT_ERROR(SSL, ssl3_PRF, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_prf, ERR_R_INTERNAL_ERROR); return 0; } @@ -188,11 +188,12 @@ } c++; if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) { - OPENSSL_PUT_ERROR(SSL, ssl3_PRF, ERR_LIB_EVP); + OPENSSL_PUT_ERROR(SSL, ssl3_prf, ERR_LIB_EVP); return 0; } EVP_DigestUpdate(&sha1, buf, k); EVP_DigestUpdate(&sha1, secret, secret_len); + /* |label| is ignored for SSLv3. */ if (seed1_len) { EVP_DigestUpdate(&sha1, seed1, seed1_len); } @@ -202,7 +203,7 @@ EVP_DigestFinal_ex(&sha1, smd, NULL); if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) { - OPENSSL_PUT_ERROR(SSL, ssl3_PRF, ERR_LIB_EVP); + OPENSSL_PUT_ERROR(SSL, ssl3_prf, ERR_LIB_EVP); return 0; } EVP_DigestUpdate(&md5, secret, secret_len); @@ -225,9 +226,13 @@ } static int ssl3_generate_key_block(SSL *s, uint8_t *out, size_t out_len) { - return ssl3_PRF(out, out_len, s->session->master_key, - s->session->master_key_length, s->s3->server_random, - SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE); + return s->enc_method->prf(s, out, out_len, s->session->master_key, + s->session->master_key_length, + 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); } int ssl3_change_cipher_state(SSL *s, int which) { @@ -750,17 +755,6 @@ } } -int ssl3_generate_master_secret(SSL *s, uint8_t *out, const uint8_t *premaster, - size_t premaster_len) { - if (!ssl3_PRF(out, SSL3_MASTER_SECRET_SIZE, premaster, premaster_len, - s->s3->client_random, SSL3_RANDOM_SIZE, s->s3->server_random, - SSL3_RANDOM_SIZE)) { - return 0; - } - - return SSL3_MASTER_SECRET_SIZE; -} - int ssl3_alert_code(int code) { switch (code) { case SSL_AD_CLOSE_NOTIFY:
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 913f84b..29ba11f 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c
@@ -559,8 +559,9 @@ const SSL3_ENC_METHOD SSLv3_enc_data = { ssl3_enc, n_ssl3_mac, + ssl3_prf, ssl3_setup_key_block, - ssl3_generate_master_secret, + tls1_generate_master_secret, ssl3_change_cipher_state, ssl3_final_finish_mac, MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
diff --git a/ssl/ssl_error.c b/ssl/ssl_error.c index 691a30e..b756e1c 100644 --- a/ssl/ssl_error.c +++ b/ssl/ssl_error.c
@@ -105,7 +105,6 @@ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_peek, 0), "ssl23_peek"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_read, 0), "ssl23_read"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_write, 0), "ssl23_write"}, - {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_PRF, 0), "ssl3_PRF"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_accept, 0), "ssl3_accept"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_callback_ctrl, 0), "ssl3_callback_ctrl"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_cert_verify_hash, 0), "ssl3_cert_verify_hash"}, @@ -138,6 +137,7 @@ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_key_exchange, 0), "ssl3_get_server_key_exchange"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_v2_client_hello, 0), "ssl3_get_v2_client_hello"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_handshake_mac, 0), "ssl3_handshake_mac"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_prf, 0), "ssl3_prf"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_read_bytes, 0), "ssl3_read_bytes"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_read_n, 0), "ssl3_read_n"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_cert_verify, 0), "ssl3_send_cert_verify"}, @@ -201,7 +201,6 @@ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_undefined_void_function, 0), "ssl_undefined_void_function"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_verify_cert_chain, 0), "ssl_verify_cert_chain"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_tls12_check_peer_sigalg, 0), "tls12_check_peer_sigalg"}, - {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_PRF, 0), "tls1_PRF"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_aead_ctx_init, 0), "tls1_aead_ctx_init"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_cert_verify_mac, 0), "tls1_cert_verify_mac"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_change_cipher_state, 0), "tls1_change_cipher_state"}, @@ -212,6 +211,7 @@ {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_export_keying_material, 0), "tls1_export_keying_material"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_get_server_supplemental_data, 0), "tls1_get_server_supplemental_data"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_heartbeat, 0), "tls1_heartbeat"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_prf, 0), "tls1_prf"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_send_server_supplemental_data, 0), "tls1_send_server_supplemental_data"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_setup_key_block, 0), "tls1_setup_key_block"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_APP_DATA_IN_HANDSHAKE), "APP_DATA_IN_HANDSHAKE"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 0264a87..6333a0c 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h
@@ -578,6 +578,8 @@ struct ssl3_enc_method { int (*enc)(SSL *, int); int (*mac)(SSL *, uint8_t *, int); + int (*prf)(SSL *, uint8_t *, size_t, const uint8_t *, size_t, const char *, + size_t, const uint8_t *, size_t, const uint8_t *, size_t); int (*setup_key_block)(SSL *); int (*generate_master_secret)(SSL *, uint8_t *, const uint8_t *, size_t); int (*change_cipher_state)(SSL *, int); @@ -737,12 +739,14 @@ int ssl3_get_finished(SSL *s, int state_a, int state_b); int ssl3_setup_key_block(SSL *s); int ssl3_send_change_cipher_spec(SSL *s, int state_a, int state_b); +int ssl3_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret, + size_t secret_len, const char *label, size_t label_len, + const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len); int ssl3_change_cipher_state(SSL *s, int which); void ssl3_cleanup_key_block(SSL *s); int ssl3_do_write(SSL *s, int type); int ssl3_send_alert(SSL *s, int level, int desc); -int ssl3_generate_master_secret(SSL *s, uint8_t *out, - const uint8_t *premaster, size_t premaster_len); int ssl3_get_req_cert_type(SSL *s, uint8_t *p); long ssl3_get_message(SSL *s, int header_state, int body_state, int msg_type, long max, int hash_message, int *ok); @@ -894,6 +898,16 @@ int ssl_init_wbio_buffer(SSL *s, int push); void ssl_free_wbio_buffer(SSL *s); +/* tls1_prf computes the TLS PRF function for |s| as described in RFC 5246, + * section 5 and RFC 2246 section 5. 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 success and zero + * on failure. */ +int tls1_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret, + size_t secret_len, const char *label, size_t label_len, + const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len); + int tls1_change_cipher_state(SSL *s, int which); int tls1_setup_key_block(SSL *s); int tls1_enc(SSL *s, int snd);
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 7385e7f..6cf8fb6 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c
@@ -219,16 +219,10 @@ return ret; } -/* tls1_PRF computes the TLS PRF function as described in RFC 5246, section 5 - * and RFC 2246 section 5. It writes |out_len| bytes to |out|, using - * |digest_mask| to select the hash functions, |secret| as the secret, and - * |label| as the label. |seed1| and |seed2| are concatenated to form the seed - * parameter. It returns one on success and zero on failure. */ -static int tls1_PRF(uint8_t *out, size_t out_len, long digest_mask, - const uint8_t *secret, size_t secret_len, - const char *label, size_t label_len, - const uint8_t *seed1, size_t seed1_len, - const uint8_t *seed2, size_t seed2_len) { +int tls1_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret, + size_t secret_len, const char *label, size_t label_len, + const uint8_t *seed1, size_t seed1_len, + const uint8_t *seed2, size_t seed2_len) { size_t idx, len, count, i; const uint8_t *S1; long m; @@ -243,14 +237,14 @@ /* Allocate a temporary buffer. */ tmp = OPENSSL_malloc(out_len); if (tmp == NULL) { - OPENSSL_PUT_ERROR(SSL, tls1_PRF, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, tls1_prf, ERR_R_MALLOC_FAILURE); return 0; } /* Count number of digests and partition |secret| evenly. */ count = 0; for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) { - if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask) { + if ((m << TLS1_PRF_DGST_SHIFT) & ssl_get_algorithm2(s)) { count++; } } @@ -265,7 +259,7 @@ S1 = secret; memset(out, 0, out_len); for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) { - if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask) { + if ((m << TLS1_PRF_DGST_SHIFT) & ssl_get_algorithm2(s)) { /* If |count| is 2 and |secret_len| is odd, |secret| is partitioned into * two halves with an overlapping byte. */ if (!tls1_P_hash(tmp, out_len, md, S1, len + (secret_len & 1), @@ -288,11 +282,13 @@ } static int tls1_generate_key_block(SSL *s, uint8_t *out, size_t out_len) { - return tls1_PRF(out, out_len, ssl_get_algorithm2(s), - s->session->master_key, s->session->master_key_length, - 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); + return s->enc_method->prf(s, out, out_len, s->session->master_key, + s->session->master_key_length, + 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); } /* tls1_aead_ctx_init allocates |*aead_ctx|, if needed and returns 1. It @@ -1046,9 +1042,9 @@ digests_len = 0; } - if (!tls1_PRF(out, 12, ssl_get_algorithm2(s), s->session->master_key, - s->session->master_key_length, str, slen, buf, digests_len, - NULL, 0)) { + if (!s->enc_method->prf(s, out, 12, s->session->master_key, + s->session->master_key_length, str, slen, buf, + digests_len, NULL, 0)) { err = 1; } @@ -1165,18 +1161,18 @@ return 0; } - if (!tls1_PRF(out, SSL3_MASTER_SECRET_SIZE, ssl_get_algorithm2(s), - premaster, premaster_len, TLS_MD_EXTENDED_MASTER_SECRET_CONST, - TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests, - digests_len, NULL, 0)) { + if (!s->enc_method->prf(s, 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; } } else { - if (!tls1_PRF(out, SSL3_MASTER_SECRET_SIZE, ssl_get_algorithm2(s), - premaster, premaster_len, TLS_MD_MASTER_SECRET_CONST, - TLS_MD_MASTER_SECRET_CONST_SIZE, s->s3->client_random, - SSL3_RANDOM_SIZE, s->s3->server_random, - SSL3_RANDOM_SIZE)) { + if (!s->enc_method->prf(s, out, SSL3_MASTER_SECRET_SIZE, premaster, + premaster_len, TLS_MD_MASTER_SECRET_CONST, + TLS_MD_MASTER_SECRET_CONST_SIZE, + s->s3->client_random, SSL3_RANDOM_SIZE, + s->s3->server_random, SSL3_RANDOM_SIZE)) { return 0; } } @@ -1237,9 +1233,12 @@ goto err1; } - ret = tls1_PRF(out, olen, ssl_get_algorithm2(s), s->session->master_key, - s->session->master_key_length, (const char *)val, vallen, NULL, - 0, NULL, 0); + /* SSL_export_keying_material is not implemented for SSLv3, so passing + * everything through the label parameter works. */ + assert(s->version != SSL3_VERSION); + ret = s->enc_method->prf(s, out, olen, s->session->master_key, + s->session->master_key_length, (const char *)val, + vallen, NULL, 0, NULL, 0); goto out; err1:
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 5975f70..9b212a5 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c
@@ -129,6 +129,7 @@ const SSL3_ENC_METHOD TLSv1_enc_data = { tls1_enc, tls1_mac, + tls1_prf, tls1_setup_key_block, tls1_generate_master_secret, tls1_change_cipher_state, @@ -148,6 +149,7 @@ const SSL3_ENC_METHOD TLSv1_1_enc_data = { tls1_enc, tls1_mac, + tls1_prf, tls1_setup_key_block, tls1_generate_master_secret, tls1_change_cipher_state, @@ -167,6 +169,7 @@ const SSL3_ENC_METHOD TLSv1_2_enc_data = { tls1_enc, tls1_mac, + tls1_prf, tls1_setup_key_block, tls1_generate_master_secret, tls1_change_cipher_state,