/* * Generates the mac for the Finished message. Returns the length of the MAC or * 0 on error. */ size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen, unsigned char *out) { const EVP_MD *md = ssl_handshake_md(s); unsigned char hash[EVP_MAX_MD_SIZE]; size_t hashlen, ret = 0; EVP_PKEY *key = NULL; EVP_MD_CTX *ctx = EVP_MD_CTX_new(); if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) { /* SSLfatal() already called */ goto err; } if (str == s->method->ssl3_enc->server_finished_label) { key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, s->server_finished_secret, hashlen); } else if (SSL_IS_FIRST_HANDSHAKE(s)) { key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, s->client_finished_secret, hashlen); } else { unsigned char finsecret[EVP_MAX_MD_SIZE]; if (!tls13_derive_finishedkey(s, ssl_handshake_md(s), s->client_app_traffic_secret, finsecret, hashlen)) goto err; key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret, hashlen); OPENSSL_cleanse(finsecret, sizeof(finsecret)); } if (key == NULL || ctx == NULL || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0 || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0 || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR); goto err; } ret = hashlen; err: EVP_PKEY_free(key); EVP_MD_CTX_free(ctx); return ret; }
int tls13_change_cipher_state(SSL *s, int which) { static const unsigned char client_early_traffic[] = "c e traffic"; static const unsigned char client_handshake_traffic[] = "c hs traffic"; static const unsigned char client_application_traffic[] = "c ap traffic"; static const unsigned char server_handshake_traffic[] = "s hs traffic"; static const unsigned char server_application_traffic[] = "s ap traffic"; static const unsigned char exporter_master_secret[] = "exp master"; static const unsigned char resumption_master_secret[] = "res master"; static const unsigned char early_exporter_master_secret[] = "e exp master"; 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; const char *log_label = NULL; EVP_CIPHER_CTX *ciph_ctx; size_t finsecretlen = 0; const unsigned char *label; size_t labellen, hashlen = 0; int ret = 0; const EVP_MD *md = NULL; const EVP_CIPHER *cipher = NULL; if (which & SSL3_CC_READ) { if (s->enc_read_ctx != NULL) { EVP_CIPHER_CTX_reset(s->enc_read_ctx); } else { s->enc_read_ctx = EVP_CIPHER_CTX_new(); if (s->enc_read_ctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } } ciph_ctx = s->enc_read_ctx; iv = s->read_iv; RECORD_LAYER_reset_read_sequence(&s->rlayer); } else { s->statem.enc_write_state = ENC_WRITE_STATE_INVALID; if (s->enc_write_ctx != NULL) { EVP_CIPHER_CTX_reset(s->enc_write_ctx); } else { s->enc_write_ctx = EVP_CIPHER_CTX_new(); if (s->enc_write_ctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } } ciph_ctx = s->enc_write_ctx; iv = s->write_iv; RECORD_LAYER_reset_write_sequence(&s->rlayer); } if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE)) || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) { if (which & SSL3_CC_EARLY) { EVP_MD_CTX *mdctx = NULL; long handlen; void *hdata; unsigned int hashlenui; const SSL_CIPHER *sslcipher = SSL_SESSION_get0_cipher(s->session); insecret = s->early_secret; label = client_early_traffic; labellen = sizeof(client_early_traffic) - 1; log_label = CLIENT_EARLY_LABEL; handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); if (handlen <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_HANDSHAKE_LENGTH); goto err; } if (s->early_data_state == SSL_EARLY_DATA_CONNECTING && s->max_early_data > 0 && s->session->ext.max_early_data == 0) { /* * If we are attempting to send early data, and we've decided to * actually do it but max_early_data in s->session is 0 then we * must be using an external PSK. */ if (!ossl_assert(s->psksession != NULL && s->max_early_data == s->psksession->ext.max_early_data)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); goto err; } sslcipher = SSL_SESSION_get0_cipher(s->psksession); } if (sslcipher == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_PSK); goto err; } /* * We need to calculate the handshake digest using the digest from * the session. We haven't yet selected our ciphersuite so we can't * use ssl_handshake_md(). */ mdctx = EVP_MD_CTX_new(); if (mdctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher)); md = ssl_md(sslcipher->algorithm2); if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL) || !EVP_DigestUpdate(mdctx, hdata, handlen) || !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); EVP_MD_CTX_free(mdctx); goto err; } hashlen = hashlenui; EVP_MD_CTX_free(mdctx); if (!tls13_hkdf_expand(s, md, insecret, early_exporter_master_secret, sizeof(early_exporter_master_secret) - 1, hashval, hashlen, s->early_exporter_master_secret, hashlen, 1)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); goto err; } if (!ssl_log_secret(s, EARLY_EXPORTER_SECRET_LABEL, s->early_exporter_master_secret, hashlen)) { /* SSLfatal() already called */ goto err; } } else if (which & SSL3_CC_HANDSHAKE) { insecret = s->handshake_secret; finsecret = s->client_finished_secret; finsecretlen = EVP_MD_size(ssl_handshake_md(s)); label = client_handshake_traffic; labellen = sizeof(client_handshake_traffic) - 1; log_label = CLIENT_HANDSHAKE_LABEL; /* * The handshake hash used for the server read/client write handshake * traffic secret is the same as the hash for the server * write/client read handshake traffic secret. However, if we * processed early data then we delay changing the server * read/client write cipher state until later, and the handshake * hashes have moved on. Therefore we use the value saved earlier * when we did the server write/client read change cipher state. */ hash = s->handshake_traffic_hash; } else { insecret = s->master_secret; label = client_application_traffic; labellen = sizeof(client_application_traffic) - 1; log_label = CLIENT_APPLICATION_LABEL; /* * 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; } } else { /* Early data never applies to client-read/server-write */ if (which & SSL3_CC_HANDSHAKE) { insecret = s->handshake_secret; finsecret = s->server_finished_secret; finsecretlen = EVP_MD_size(ssl_handshake_md(s)); label = server_handshake_traffic; labellen = sizeof(server_handshake_traffic) - 1; log_label = SERVER_HANDSHAKE_LABEL; } else { insecret = s->master_secret; label = server_application_traffic; labellen = sizeof(server_application_traffic) - 1; log_label = SERVER_APPLICATION_LABEL; } } if (!(which & SSL3_CC_EARLY)) { md = ssl_handshake_md(s); cipher = s->s3->tmp.new_sym_enc; if (!ssl3_digest_cached_records(s, 1) || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) { /* SSLfatal() already called */; 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, hashval, hashlen); if (label == server_handshake_traffic) memcpy(s->handshake_traffic_hash, hashval, hashlen); if (label == client_application_traffic) { /* * We also create the resumption master secret, but this time use the * hash for the whole handshake including the Client Finished */ if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, resumption_master_secret, sizeof(resumption_master_secret) - 1, hashval, hashlen, s->resumption_master_secret, hashlen, 1)) { /* SSLfatal() already called */ goto err; } } if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher, insecret, hash, label, labellen, secret, iv, ciph_ctx)) { /* SSLfatal() already called */ goto err; } if (label == server_application_traffic) { memcpy(s->server_app_traffic_secret, secret, hashlen); /* Now we create the exporter master secret */ if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, exporter_master_secret, sizeof(exporter_master_secret) - 1, hash, hashlen, s->exporter_master_secret, hashlen, 1)) { /* SSLfatal() already called */ goto err; } if (!ssl_log_secret(s, EXPORTER_SECRET_LABEL, s->exporter_master_secret, hashlen)) { /* SSLfatal() already called */ goto err; } } else if (label == client_application_traffic) memcpy(s->client_app_traffic_secret, secret, hashlen); if (!ssl_log_secret(s, log_label, secret, hashlen)) { /* SSLfatal() already called */ goto err; } if (finsecret != NULL && !tls13_derive_finishedkey(s, ssl_handshake_md(s), secret, finsecret, finsecretlen)) { /* SSLfatal() already called */ goto err; } if (!s->server && label == client_early_traffic) s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS; else s->statem.enc_write_state = ENC_WRITE_STATE_VALID; ret = 1; err: OPENSSL_cleanse(secret, sizeof(secret)); return ret; }
int tls13_change_cipher_state(SSL *s, int which) { static const unsigned char client_handshake_traffic[] = "client handshake traffic secret"; static const unsigned char client_application_traffic[] = "client application traffic secret"; static const unsigned char server_handshake_traffic[] = "server handshake traffic secret"; 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 secret[EVP_MAX_MD_SIZE]; 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; int ret = 0; if (which & SSL3_CC_READ) { if (s->enc_read_ctx != NULL) { EVP_CIPHER_CTX_reset(s->enc_read_ctx); } else { s->enc_read_ctx = EVP_CIPHER_CTX_new(); if (s->enc_read_ctx == NULL) { SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } } ciph_ctx = s->enc_read_ctx; RECORD_LAYER_reset_read_sequence(&s->rlayer); } else { if (s->enc_write_ctx != NULL) { EVP_CIPHER_CTX_reset(s->enc_write_ctx); } else { s->enc_write_ctx = EVP_CIPHER_CTX_new(); if (s->enc_write_ctx == NULL) { SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } } ciph_ctx = s->enc_write_ctx; RECORD_LAYER_reset_write_sequence(&s->rlayer); } if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE)) || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) { if (which & SSL3_CC_HANDSHAKE) { insecret = s->handshake_secret; finsecret = s->client_finished_secret; finsecretlen = sizeof(s->client_finished_secret); label = client_handshake_traffic; labellen = sizeof(client_handshake_traffic) - 1; } else { insecret = s->session->master_key; label = client_application_traffic; labellen = sizeof(client_application_traffic) - 1; } } else { if (which & SSL3_CC_HANDSHAKE) { insecret = s->handshake_secret; finsecret = s->server_finished_secret; finsecretlen = sizeof(s->server_finished_secret); label = server_handshake_traffic; labellen = sizeof(server_handshake_traffic) - 1; } else { insecret = s->session->master_key; label = server_application_traffic; labellen = sizeof(server_application_traffic) - 1; } } if (!tls13_derive_secret(s, insecret, label, labellen, secret)) { 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); if (!tls13_derive_key(s, secret, key, keylen) || !tls13_derive_iv(s, secret, iv, ivlen) || (finsecret != NULL && !tls13_derive_finishedkey(s, secret, finsecret, finsecretlen))) { SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); 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; } } #ifdef OPENSSL_SSL_TRACE_CRYPTO if (s->msg_callback) { int wh = which & SSL3_CC_WRITE ? TLS1_RT_CRYPTO_WRITE : 0; 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); } } #endif ret = 1; err: OPENSSL_cleanse(secret, sizeof(secret)); OPENSSL_cleanse(key, sizeof(key)); OPENSSL_cleanse(iv, sizeof(iv)); return ret; }
int tls13_change_cipher_state(SSL *s, int which) { static const unsigned char client_handshake_traffic[] = "client handshake traffic secret"; static const unsigned char client_application_traffic[] = "client application traffic secret"; static const unsigned char server_handshake_traffic[] = "server handshake traffic secret"; static const unsigned char server_application_traffic[] = "server application traffic secret"; static const unsigned char resumption_master_secret[] = "resumption master secret"; 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; const char *log_label = 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, hashlen = 0; int ret = 0; if (which & SSL3_CC_READ) { if (s->enc_read_ctx != NULL) { EVP_CIPHER_CTX_reset(s->enc_read_ctx); } else { s->enc_read_ctx = EVP_CIPHER_CTX_new(); if (s->enc_read_ctx == NULL) { SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } } ciph_ctx = s->enc_read_ctx; iv = s->read_iv; RECORD_LAYER_reset_read_sequence(&s->rlayer); } else { if (s->enc_write_ctx != NULL) { EVP_CIPHER_CTX_reset(s->enc_write_ctx); } else { s->enc_write_ctx = EVP_CIPHER_CTX_new(); if (s->enc_write_ctx == NULL) { SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); goto err; } } ciph_ctx = s->enc_write_ctx; iv = s->write_iv; RECORD_LAYER_reset_write_sequence(&s->rlayer); } if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE)) || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) { if (which & SSL3_CC_HANDSHAKE) { insecret = s->handshake_secret; finsecret = s->client_finished_secret; finsecretlen = EVP_MD_size(ssl_handshake_md(s)); label = client_handshake_traffic; labellen = sizeof(client_handshake_traffic) - 1; log_label = CLIENT_HANDSHAKE_LABEL; } else { insecret = s->master_secret; label = client_application_traffic; labellen = sizeof(client_application_traffic) - 1; log_label = CLIENT_APPLICATION_LABEL; /* * 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; } } else { if (which & SSL3_CC_HANDSHAKE) { insecret = s->handshake_secret; finsecret = s->server_finished_secret; finsecretlen = EVP_MD_size(ssl_handshake_md(s)); label = server_handshake_traffic; labellen = sizeof(server_handshake_traffic) - 1; log_label = SERVER_HANDSHAKE_LABEL; } else { insecret = s->master_secret; label = server_application_traffic; labellen = sizeof(server_application_traffic) - 1; log_label = SERVER_APPLICATION_LABEL; } } if (!ssl3_digest_cached_records(s, 1) || !ssl_handshake_hash(s, hashval, 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, hashval, hashlen); if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, label, labellen, hash, secret, hashlen)) { SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); goto err; } if (label == client_application_traffic) { /* * We also create the resumption master secret, but this time use the * hash for the whole handshake including the Client Finished */ if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret, resumption_master_secret, sizeof(resumption_master_secret) - 1, hashval, s->session->master_key, hashlen)) { SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); goto err; } s->session->master_key_length = hashlen; } /* TODO(size_t): convert me */ keylen = EVP_CIPHER_key_length(ciph); ivlen = EVP_CIPHER_iv_length(ciph); if (!ssl_log_secret(s, log_label, secret, hashlen)) { SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); goto err; } if (!tls13_derive_key(s, secret, key, keylen) || !tls13_derive_iv(s, secret, iv, ivlen) || (finsecret != NULL && !tls13_derive_finishedkey(s, ssl_handshake_md(s), secret, finsecret, finsecretlen))) { SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); 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 (s->msg_callback) { int wh = which & SSL3_CC_WRITE ? TLS1_RT_CRYPTO_WRITE : 0; if (ciph->key_len) s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY, key, ciph->key_len, 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)); return ret; }