unsigned char handshake_secret[EVP_MAX_MD_SIZE];
unsigned char client_finished_secret[EVP_MAX_MD_SIZE];
unsigned char server_finished_secret[EVP_MAX_MD_SIZE];
+ unsigned char server_finished_hash[EVP_MAX_MD_SIZE];
EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
unsigned char read_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static read IV */
EVP_MD_CTX *read_hash; /* used for mac generation */
__owur size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
unsigned char *p);
__owur int tls13_change_cipher_state(SSL *s, int which);
-__owur int tls13_derive_secret(SSL *s, const unsigned char *insecret,
- const unsigned char *label, size_t labellen,
- unsigned char *secret);
+__owur int tls13_hkdf_expand(SSL *s, const unsigned char *secret,
+ const unsigned char *label, size_t labellen,
+ const unsigned char *hash,
+ unsigned char *out, size_t outlen);
__owur int tls13_derive_key(SSL *s, const unsigned char *secret,
unsigned char *key, size_t keylen);
__owur int tls13_derive_iv(SSL *s, const unsigned char *secret,
* the location pointed to be |out|. The |hash| value may be NULL. Returns 1 on
* success 0 on failure.
*/
-static int tls13_hkdf_expand(SSL *s, const unsigned char *secret,
+int tls13_hkdf_expand(SSL *s, const unsigned char *secret,
const unsigned char *label, size_t labellen,
const unsigned char *hash,
unsigned char *out, size_t outlen)
return ret == 0;
}
-/*
- * Given a input secret |insecret| and a |label| of length |labellen|, derive a
- * new |secret|. This will be the length of the current hash output size and
- * will be based on the current state of the handshake hashes. Returns 1 on
- * success 0 on failure.
- */
-int tls13_derive_secret(SSL *s, const unsigned char *insecret,
- const unsigned char *label, size_t labellen,
- unsigned char *secret)
-{
- unsigned char hash[EVP_MAX_MD_SIZE];
- size_t hashlen;
-
- if (!ssl3_digest_cached_records(s, 1))
- return 0;
-
- if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen))
- return 0;
-
- return tls13_hkdf_expand(s, insecret, label, labellen, hash, secret,
- hashlen);
-}
-
/*
* Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on
* success 0 on failure.
unsigned char key[EVP_MAX_KEY_LENGTH];
unsigned char *iv;
unsigned char secret[EVP_MAX_MD_SIZE];
+ unsigned char hashval[EVP_MAX_MD_SIZE];
+ unsigned char *hash = hashval;
unsigned char *insecret;
unsigned char *finsecret = NULL;
EVP_CIPHER_CTX *ciph_ctx;
const EVP_CIPHER *ciph = s->s3->tmp.new_sym_enc;
size_t ivlen, keylen, finsecretlen = 0;
const unsigned char *label;
- size_t labellen;
+ size_t labellen, hashlen = 0;
int ret = 0;
if (which & SSL3_CC_READ) {
label = client_handshake_traffic;
labellen = sizeof(client_handshake_traffic) - 1;
} else {
+ int hashleni;
+
insecret = s->session->master_key;
label = client_application_traffic;
labellen = sizeof(client_application_traffic) - 1;
+ /*
+ * For this we only use the handshake hashes up until the server
+ * Finished hash. We do not include the client's Finished, which is
+ * what ssl_handshake_hash() would give us. Instead we use the
+ * previously saved value.
+ */
+ hash = s->server_finished_hash;
+ hashleni = EVP_MD_CTX_size(s->s3->handshake_dgst);
+ if (hashleni < 0) {
+ SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ hashlen = (size_t)hashleni;
}
} else {
if (which & SSL3_CC_HANDSHAKE) {
}
}
- if (!tls13_derive_secret(s, insecret, label, labellen, secret)) {
+ if (label != client_application_traffic) {
+ if (!ssl3_digest_cached_records(s, 1)
+ || !ssl_handshake_hash(s, hash, sizeof(hashval), &hashlen)) {
+ SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * Save the hash of handshakes up to now for use when we calculate the
+ * client application traffic secret
+ */
+ if (label == server_application_traffic)
+ memcpy(s->server_finished_hash, hash, hashlen);
+ }
+
+ if (!tls13_hkdf_expand(s, insecret, label, labellen, hash, secret,
+ hashlen)) {
SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
goto err;
}
const unsigned char *ref_secret,
const unsigned char *ref_key, const unsigned char *ref_iv)
{
- size_t hashsize = EVP_MD_size(ssl_handshake_md(s));
+ size_t hashsize;
unsigned char gensecret[EVP_MAX_MD_SIZE];
+ unsigned char hash[EVP_MAX_MD_SIZE];
unsigned char key[KEYLEN];
unsigned char iv[IVLEN];
- if (!tls13_derive_secret(s, prk, label, labellen, gensecret)) {
+ if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashsize)) {
+ fprintf(stderr, "Failed to get hash\n");
+ return 0;
+ }
+
+ if (!tls13_hkdf_expand(s, prk, label, labellen, hash, gensecret,
+ hashsize)) {
fprintf(stderr, "Secret generation failed\n");
return 0;
}