* 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.
static const unsigned char server_application_traffic[] =
"server application traffic secret";
unsigned char key[EVP_MAX_KEY_LENGTH];
- unsigned char iv[EVP_MAX_IV_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) {
}
}
ciph_ctx = s->enc_read_ctx;
+ iv = s->read_iv;
RECORD_LAYER_reset_read_sequence(&s->rlayer);
} else {
}
}
ciph_ctx = s->enc_write_ctx;
+ iv = s->write_iv;
RECORD_LAYER_reset_write_sequence(&s->rlayer);
}
if (which & SSL3_CC_HANDSHAKE) {
insecret = s->handshake_secret;
finsecret = s->client_finished_secret;
- finsecretlen = sizeof(s->client_finished_secret);
+ finsecretlen = EVP_MD_size(ssl_handshake_md(s));
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) {
insecret = s->handshake_secret;
finsecret = s->server_finished_secret;
- finsecretlen = sizeof(s->server_finished_secret);
+ finsecretlen = EVP_MD_size(ssl_handshake_md(s));
label = server_handshake_traffic;
labellen = sizeof(server_handshake_traffic) - 1;
} else {
}
}
- 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;
}
/* TODO(size_t): convert me */
keylen = EVP_CIPHER_key_length(ciph);
-
- if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE)
- ivlen = EVP_GCM_TLS_FIXED_IV_LEN;
- else if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE)
- ivlen = EVP_CCM_TLS_FIXED_IV_LEN;
- else
- ivlen = EVP_CIPHER_iv_length(ciph);
+ ivlen = EVP_CIPHER_iv_length(ciph);
if (!tls13_derive_key(s, secret, key, keylen)
|| !tls13_derive_iv(s, secret, iv, ivlen)
goto err;
}
- if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE) {
- if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, key, NULL,
- (which & SSL3_CC_WRITE))
- || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_GCM_SET_IV_FIXED,
- (int)ivlen, iv)) {
- SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB);
- goto err;
- }
- } else if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) {
- int taglen;
-
- if (s->s3->tmp.new_cipher->algorithm_enc
- & (SSL_AES128CCM8 | SSL_AES256CCM8))
- taglen = 8;
- else
- taglen = 16;
- if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL,
- (which & SSL3_CC_WRITE))
- || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, 12,
- NULL)
- || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen,
- NULL)
- || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_CCM_SET_IV_FIXED,
- (int)ivlen, iv)
- || !EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1)) {
- SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB);
- goto err;
- }
- } else {
- if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, key, iv,
- (which & SSL3_CC_WRITE))) {
- SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB);
- goto err;
- }
+ if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, key, NULL,
+ (which & SSL3_CC_WRITE)) <= 0) {
+ SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB);
+ goto err;
}
#ifdef OPENSSL_SSL_TRACE_CRYPTO
if (ciph->key_len)
s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY,
key, ciph->key_len, s, s->msg_callback_arg);
- if (ivlen) {
- if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE)
- wh |= TLS1_RT_CRYPTO_FIXED_IV;
- else
- wh |= TLS1_RT_CRYPTO_IV;
- s->msg_callback(2, s->version, wh, iv, ivlen, s,
- s->msg_callback_arg);
- }
+
+ wh |= TLS1_RT_CRYPTO_IV;
+ s->msg_callback(2, s->version, wh, iv, ivlen, s,
+ s->msg_callback_arg);
}
#endif
ret = 1;
-
err:
OPENSSL_cleanse(secret, sizeof(secret));
OPENSSL_cleanse(key, sizeof(key));
- OPENSSL_cleanse(iv, sizeof(iv));
return ret;
}
+
+int tls13_alert_code(int code)
+{
+ if (code == SSL_AD_MISSING_EXTENSION)
+ return code;
+
+ return tls1_alert_code(code);
+}