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,