aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/openssl/ssl/tls13_enc.c
diff options
context:
space:
mode:
authorxiwra <xiwra@yandex-team.com>2024-10-11 04:10:50 +0300
committerxiwra <xiwra@yandex-team.com>2024-10-11 04:23:51 +0300
commite7ae2d617562e731cd6770c5f903adc9a60a7386 (patch)
treee0393dab34202280c2bf820d769dc4e637c7def7 /contrib/libs/openssl/ssl/tls13_enc.c
parentadf06dbfe67e7c178f9d19dbf7ce1a3d59af3423 (diff)
downloadydb-e7ae2d617562e731cd6770c5f903adc9a60a7386.tar.gz
OpenSSL+quictls
applied patch from ms: <https://github.com/quictls/openssl/releases/tag/OpenSSL_1_1_1w-quic1> needed to bring QUIC to smart devices PoC with this patch checked here: <HIDDEN_URL> commit_hash:a1710ceeba972d163108e8a86bba74b090c8f4c8
Diffstat (limited to 'contrib/libs/openssl/ssl/tls13_enc.c')
-rw-r--r--contrib/libs/openssl/ssl/tls13_enc.c218
1 files changed, 216 insertions, 2 deletions
diff --git a/contrib/libs/openssl/ssl/tls13_enc.c b/contrib/libs/openssl/ssl/tls13_enc.c
index ff85df4483..af48d83718 100644
--- a/contrib/libs/openssl/ssl/tls13_enc.c
+++ b/contrib/libs/openssl/ssl/tls13_enc.c
@@ -435,8 +435,6 @@ static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
return 0;
}
-int tls13_change_cipher_state(SSL *s, int which)
-{
#ifdef CHARSET_EBCDIC
static const unsigned char client_early_traffic[] = {0x63, 0x20, 0x65, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
static const unsigned char client_handshake_traffic[] = {0x63, 0x20, 0x68, 0x73, 0x20, /*traffic*/0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x00};
@@ -456,6 +454,217 @@ int tls13_change_cipher_state(SSL *s, int which)
static const unsigned char resumption_master_secret[] = "res master";
static const unsigned char early_exporter_master_secret[] = "e exp master";
#endif
+
+#ifndef OPENSSL_NO_QUIC
+static int quic_change_cipher_state(SSL *s, int which)
+{
+ unsigned char hash[EVP_MAX_MD_SIZE];
+ size_t hashlen = 0;
+ int hashleni;
+ int ret = 0;
+ const EVP_MD *md = NULL;
+ OSSL_ENCRYPTION_LEVEL level;
+ int is_handshake = ((which & SSL3_CC_HANDSHAKE) == SSL3_CC_HANDSHAKE);
+ int is_client_read = ((which & SSL3_CHANGE_CIPHER_CLIENT_READ) == SSL3_CHANGE_CIPHER_CLIENT_READ);
+ int is_server_write = ((which & SSL3_CHANGE_CIPHER_SERVER_WRITE) == SSL3_CHANGE_CIPHER_SERVER_WRITE);
+ int is_early = (which & SSL3_CC_EARLY);
+
+ if (is_early) {
+ EVP_MD_CTX *mdctx = NULL;
+ long handlen;
+ void *hdata;
+ unsigned int hashlenui;
+ const SSL_CIPHER *sslcipher = SSL_SESSION_get0_cipher(s->session);
+
+ handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (handlen <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_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_QUIC_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_QUIC_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_QUIC_CHANGE_CIPHER_STATE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ md = ssl_md(sslcipher->algorithm2);
+ if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
+ || !EVP_DigestUpdate(mdctx, hdata, handlen)
+ || !EVP_DigestFinal_ex(mdctx, hash, &hashlenui)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_CHANGE_CIPHER_STATE,
+ ERR_R_INTERNAL_ERROR);
+ EVP_MD_CTX_free(mdctx);
+ goto err;
+ }
+ hashlen = hashlenui;
+ EVP_MD_CTX_free(mdctx);
+ } else {
+ md = ssl_handshake_md(s);
+ if (!ssl3_digest_cached_records(s, 1)
+ || !ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
+ /* SSLfatal() already called */;
+ goto err;
+ }
+
+ /* Ensure cast to size_t is safe */
+ hashleni = EVP_MD_size(md);
+ if (!ossl_assert(hashleni >= 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_QUIC_CHANGE_CIPHER_STATE,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ hashlen = (size_t)hashleni;
+ }
+
+ if (is_client_read || is_server_write) {
+ if (is_handshake) {
+ /*
+ * This looks a bit weird, since the condition is basically "the
+ * server is writing" but we set both the server *and* client
+ * handshake traffic keys here. That's because there's only a fixed
+ * number of change-cipher-state events in the TLS 1.3 handshake,
+ * and in particular there's not an event in between when the server
+ * writes encrypted handshake messages and when the client writes
+ * encrypted handshake messages, so we generate both here.
+ */
+ level = ssl_encryption_handshake;
+
+ if (!tls13_hkdf_expand(s, md, s->handshake_secret,
+ client_handshake_traffic,
+ sizeof(client_handshake_traffic)-1, hash,
+ hashlen, s->client_hand_traffic_secret,
+ hashlen, 1)
+ || !ssl_log_secret(s, CLIENT_HANDSHAKE_LABEL,
+ s->client_hand_traffic_secret, hashlen)
+ || !tls13_derive_finishedkey(s, md,
+ s->client_hand_traffic_secret,
+ s->client_finished_secret, hashlen)
+ || !tls13_hkdf_expand(s, md, s->handshake_secret,
+ server_handshake_traffic,
+ sizeof(server_handshake_traffic)-1, hash,
+ hashlen, s->server_hand_traffic_secret,
+ hashlen, 1)
+ || !ssl_log_secret(s, SERVER_HANDSHAKE_LABEL,
+ s->server_hand_traffic_secret, hashlen)
+ || !tls13_derive_finishedkey(s, md,
+ s->server_hand_traffic_secret,
+ s->server_finished_secret,
+ hashlen)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else {
+ /*
+ * As above, we generate both sets of application traffic keys at
+ * the same time.
+ */
+ level = ssl_encryption_application;
+
+ if (!tls13_hkdf_expand(s, md, s->master_secret,
+ client_application_traffic,
+ sizeof(client_application_traffic)-1, hash,
+ hashlen, s->client_app_traffic_secret,
+ hashlen, 1)
+ || !ssl_log_secret(s, CLIENT_APPLICATION_LABEL,
+ s->client_app_traffic_secret, hashlen)
+ || !tls13_hkdf_expand(s, md, s->master_secret,
+ server_application_traffic,
+ sizeof(server_application_traffic)-1,
+ hash, hashlen,
+ s->server_app_traffic_secret, hashlen, 1)
+ || !ssl_log_secret(s, SERVER_APPLICATION_LABEL,
+ s->server_app_traffic_secret, hashlen)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ }
+ if (!quic_set_encryption_secrets(s, level)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ if (s->server)
+ s->quic_write_level = level;
+ else
+ s->quic_read_level = level;
+ } else {
+ /* is_client_write || is_server_read */
+
+ if (is_early) {
+ level = ssl_encryption_early_data;
+
+ if (!tls13_hkdf_expand(s, md, s->early_secret, client_early_traffic,
+ sizeof(client_early_traffic)-1, hash,
+ hashlen, s->client_early_traffic_secret,
+ hashlen, 1)
+ || !ssl_log_secret(s, CLIENT_EARLY_LABEL,
+ s->client_early_traffic_secret, hashlen)
+ || !quic_set_encryption_secrets(s, level)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (is_handshake) {
+ level = ssl_encryption_handshake;
+ } else {
+ level = ssl_encryption_application;
+ /*
+ * 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, md, s->master_secret,
+ resumption_master_secret,
+ sizeof(resumption_master_secret)-1, hash,
+ hashlen, s->resumption_master_secret,
+ hashlen, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ }
+
+ if (level != ssl_encryption_early_data) {
+ if (s->server)
+ s->quic_read_level = level;
+ else
+ s->quic_write_level = level;
+ }
+ }
+
+ ret = 1;
+ err:
+ return ret;
+}
+#endif /* OPENSSL_NO_QUIC */
+
+int tls13_change_cipher_state(SSL *s, int which)
+{
unsigned char *iv;
unsigned char secret[EVP_MAX_MD_SIZE];
unsigned char hashval[EVP_MAX_MD_SIZE];
@@ -471,6 +680,11 @@ int tls13_change_cipher_state(SSL *s, int which)
const EVP_MD *md = NULL;
const EVP_CIPHER *cipher = NULL;
+#ifndef OPENSSL_NO_QUIC
+ if (SSL_IS_QUIC(s))
+ return quic_change_cipher_state(s, which);
+#endif
+
if (which & SSL3_CC_READ) {
if (s->enc_read_ctx != NULL) {
EVP_CIPHER_CTX_reset(s->enc_read_ctx);