X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ftls13_enc.c;h=449e6f9f36baff6cf8d01c7b8a3ade24fded0e2f;hp=b5306eb78cd2a361aceb6a938ca22e8b61030057;hb=049043127209a4a1846a1c0fcc56eff601c41be2;hpb=902d036c149c4d723b501bf09b327b2b4e2182af diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c index b5306eb78c..449e6f9f36 100644 --- a/ssl/tls13_enc.c +++ b/ssl/tls13_enc.c @@ -23,7 +23,7 @@ static const unsigned char default_zeros[EVP_MAX_MD_SIZE]; * 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) @@ -74,29 +74,6 @@ static int tls13_hkdf_expand(SSL *s, const unsigned char *secret, 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. @@ -284,15 +261,17 @@ int tls13_change_cipher_state(SSL *s, int which) 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; + 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) { @@ -306,6 +285,7 @@ int tls13_change_cipher_state(SSL *s, int which) } } ciph_ctx = s->enc_read_ctx; + iv = s->read_iv; RECORD_LAYER_reset_read_sequence(&s->rlayer); } else { @@ -319,6 +299,7 @@ int tls13_change_cipher_state(SSL *s, int which) } } ciph_ctx = s->enc_write_ctx; + iv = s->write_iv; RECORD_LAYER_reset_write_sequence(&s->rlayer); } @@ -328,19 +309,34 @@ int tls13_change_cipher_state(SSL *s, int which) 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 { @@ -350,20 +346,30 @@ int tls13_change_cipher_state(SSL *s, int which) } } - 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) @@ -374,40 +380,10 @@ int tls13_change_cipher_state(SSL *s, int which) 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 @@ -417,22 +393,24 @@ int tls13_change_cipher_state(SSL *s, int which) 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); +}