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,