# HG changeset patch # User Vladimir Homutov # Date 1585740325 -10800 # Node ID 058a5af7ddfc1371d70fea59cac2ecbc341688be # Parent e35f824f644d8be4a4167a28e2d3ee637b28e48c Refactored QUIC secrets storage. The quic->keys[4] array now contains secrets related to the corresponding encryption level. All protection-level functions get proper keys and do not need to switch manually between levels. diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c --- a/src/event/ngx_event_quic.c +++ b/src/event/ngx_event_quic.c @@ -42,7 +42,9 @@ struct ngx_quic_connection_s { ngx_uint_t handshake_pn; ngx_uint_t appdata_pn; - ngx_quic_secrets_t secrets; + ngx_quic_secrets_t keys[NGX_QUIC_ENCRYPTION_LAST]; + uint64_t crypto_offset[NGX_QUIC_ENCRYPTION_LAST]; + ngx_ssl_t *ssl; ngx_quic_frame_t *frames; ngx_quic_frame_t *free_frames; @@ -56,9 +58,6 @@ struct ngx_quic_connection_s { unsigned send_timer_set:1; unsigned closing:1; - -#define SSL_ECRYPTION_LAST ((ssl_encryption_application) + 1) - uint64_t crypto_offset[SSL_ECRYPTION_LAST]; }; @@ -156,20 +155,23 @@ ngx_quic_set_read_secret(ngx_ssl_conn_t enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, const uint8_t *rsecret, size_t secret_len) { - ngx_connection_t *c; + ngx_connection_t *c; + ngx_quic_secrets_t *keys; c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); ngx_quic_hexdump(c->log, "level:%d read secret", rsecret, secret_len, level); + keys = &c->quic->keys[level]; + if (level == ssl_encryption_early_data) { c->quic->state = NGX_QUIC_ST_EARLY_DATA; } return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, rsecret, secret_len, - &c->quic->secrets.client); + &keys->client); } @@ -178,16 +180,19 @@ ngx_quic_set_write_secret(ngx_ssl_conn_t enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, const uint8_t *wsecret, size_t secret_len) { - ngx_connection_t *c; + ngx_connection_t *c; + ngx_quic_secrets_t *keys; c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); ngx_quic_hexdump(c->log, "level:%d write secret", wsecret, secret_len, level); + keys = &c->quic->keys[level]; + return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, wsecret, secret_len, - &c->quic->secrets.server); + &keys->server); } #else @@ -197,16 +202,19 @@ ngx_quic_set_encryption_secrets(ngx_ssl_ enum ssl_encryption_level_t level, const uint8_t *rsecret, const uint8_t *wsecret, size_t secret_len) { - ngx_int_t rc; - ngx_connection_t *c; + ngx_int_t rc; + ngx_connection_t *c; + ngx_quic_secrets_t *keys; c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); ngx_quic_hexdump(c->log, "level:%d read", rsecret, secret_len, level); + keys = &c->quic->secrets[level]; + rc = ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, rsecret, secret_len, - &c->quic->secrets.client); + &keys->client); if (rc != 1) { return rc; } @@ -220,7 +228,7 @@ ngx_quic_set_encryption_secrets(ngx_ssl_ return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, wsecret, secret_len, - &c->quic->secrets.server); + &keys->server); } #endif @@ -380,6 +388,7 @@ ngx_quic_new_connection(ngx_connection_t ngx_quic_header_t *pkt, ngx_connection_handler_pt handler) { ngx_quic_tp_t *ctp; + ngx_quic_secrets_t *keys; ngx_quic_connection_t *qc; static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; @@ -445,14 +454,16 @@ ngx_quic_new_connection(ngx_connection_t } ngx_memcpy(qc->token.data, pkt->token.data, qc->token.len); + keys = &c->quic->keys[ssl_encryption_initial]; - if (ngx_quic_set_initial_secret(c->pool, &qc->secrets, &qc->dcid) + if (ngx_quic_set_initial_secret(c->pool, &keys->client, &keys->server, + &qc->dcid) != NGX_OK) { return NGX_ERROR; } - pkt->secret = &qc->secrets.client.in; + pkt->secret = &keys->client; pkt->level = ssl_encryption_initial; pkt->plaintext = buf; @@ -743,13 +754,12 @@ ngx_quic_input(ngx_connection_t *c, ngx_ static ngx_int_t ngx_quic_initial_input(ngx_connection_t *c, ngx_quic_header_t *pkt) { - ngx_ssl_conn_t *ssl_conn; - ngx_quic_connection_t *qc; - static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; + ngx_ssl_conn_t *ssl_conn; + ngx_quic_secrets_t *keys; + static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; c->log->action = "processing initial quic packet"; - qc = c->quic; ssl_conn = c->ssl->connection; if (ngx_quic_parse_long_header(pkt) != NGX_OK) { @@ -760,7 +770,9 @@ ngx_quic_initial_input(ngx_connection_t return NGX_ERROR; } - pkt->secret = &qc->secrets.client.in; + keys = &c->quic->keys[ssl_encryption_initial]; + + pkt->secret = &keys->client; pkt->level = ssl_encryption_initial; pkt->plaintext = buf; @@ -775,6 +787,7 @@ ngx_quic_initial_input(ngx_connection_t static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt) { + ngx_quic_secrets_t *keys; ngx_quic_connection_t *qc; static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; @@ -817,7 +830,9 @@ ngx_quic_handshake_input(ngx_connection_ return NGX_ERROR; } - pkt->secret = &qc->secrets.client.hs; + keys = &c->quic->keys[ssl_encryption_handshake]; + + pkt->secret = &keys->client; pkt->level = ssl_encryption_handshake; pkt->plaintext = buf; @@ -832,6 +847,7 @@ ngx_quic_handshake_input(ngx_connection_ static ngx_int_t ngx_quic_early_input(ngx_connection_t *c, ngx_quic_header_t *pkt) { + ngx_quic_secrets_t *keys; ngx_quic_connection_t *qc; static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; @@ -879,7 +895,9 @@ ngx_quic_early_input(ngx_connection_t *c return NGX_OK; } - pkt->secret = &qc->secrets.client.ed; + keys = &c->quic->keys[ssl_encryption_early_data]; + + pkt->secret = &keys->client; pkt->level = ssl_encryption_early_data; pkt->plaintext = buf; @@ -894,6 +912,7 @@ ngx_quic_early_input(ngx_connection_t *c static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, ngx_quic_header_t *pkt) { + ngx_quic_secrets_t *keys; ngx_quic_connection_t *qc; static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; @@ -901,7 +920,9 @@ ngx_quic_app_input(ngx_connection_t *c, qc = c->quic; - if (qc->secrets.client.ad.key.len == 0) { + keys = &c->quic->keys[ssl_encryption_application]; + + if (keys->client.key.len == 0) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "no read keys yet, packet ignored"); return NGX_DECLINED; @@ -911,7 +932,7 @@ ngx_quic_app_input(ngx_connection_t *c, return NGX_ERROR; } - pkt->secret = &qc->secrets.client.ad; + pkt->secret = &keys->client; pkt->level = ssl_encryption_application; pkt->plaintext = buf; @@ -1085,9 +1106,7 @@ ngx_quic_payload_handler(ngx_connection_ return NGX_ERROR; } - ack_frame->level = (pkt->level == ssl_encryption_early_data) - ? ssl_encryption_application - : pkt->level; + ack_frame->level = pkt->level; ack_frame->type = NGX_QUIC_FT_ACK; ack_frame->u.ack.pn = pkt->pn; @@ -1434,6 +1453,7 @@ ngx_quic_frames_send(ngx_connection_t *c ngx_str_t out, res; ngx_quic_frame_t *f; ngx_quic_header_t pkt; + ngx_quic_secrets_t *keys; ngx_quic_connection_t *qc; static ngx_str_t initial_token = ngx_null_string; static u_char src[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; @@ -1472,20 +1492,21 @@ ngx_quic_frames_send(ngx_connection_t *c qc = c->quic; + keys = &c->quic->keys[start->level]; + + pkt.secret = &keys->server; + if (start->level == ssl_encryption_initial) { pkt.number = &qc->initial_pn; pkt.flags = NGX_QUIC_PKT_INITIAL; - pkt.secret = &qc->secrets.server.in; pkt.token = initial_token; } else if (start->level == ssl_encryption_handshake) { pkt.number = &qc->handshake_pn; pkt.flags = NGX_QUIC_PKT_HANDSHAKE; - pkt.secret = &qc->secrets.server.hs; } else { pkt.number = &qc->appdata_pn; - pkt.secret = &qc->secrets.server.ad; } pkt.log = c->log; diff --git a/src/event/ngx_event_quic_protection.c b/src/event/ngx_event_quic_protection.c --- a/src/event/ngx_event_quic_protection.c +++ b/src/event/ngx_event_quic_protection.c @@ -118,8 +118,8 @@ ngx_quic_ciphers(ngx_ssl_conn_t *ssl_con ngx_int_t -ngx_quic_set_initial_secret(ngx_pool_t *pool, ngx_quic_secrets_t *qsec, - ngx_str_t *secret) +ngx_quic_set_initial_secret(ngx_pool_t *pool, ngx_quic_secret_t *client, + ngx_quic_secret_t *server, ngx_str_t *secret) { size_t is_len; uint8_t is[SHA256_DIGEST_LENGTH]; @@ -152,17 +152,17 @@ ngx_quic_set_initial_secret(ngx_pool_t * ngx_quic_hexdump0(pool->log, "initial secret", is, is_len); /* draft-ietf-quic-tls-23#section-5.2 */ - qsec->client.in.secret.len = SHA256_DIGEST_LENGTH; - qsec->server.in.secret.len = SHA256_DIGEST_LENGTH; + client->secret.len = SHA256_DIGEST_LENGTH; + server->secret.len = SHA256_DIGEST_LENGTH; - qsec->client.in.key.len = EVP_CIPHER_key_length(cipher); - qsec->server.in.key.len = EVP_CIPHER_key_length(cipher); + client->key.len = EVP_CIPHER_key_length(cipher); + server->key.len = EVP_CIPHER_key_length(cipher); - qsec->client.in.hp.len = EVP_CIPHER_key_length(cipher); - qsec->server.in.hp.len = EVP_CIPHER_key_length(cipher); + client->hp.len = EVP_CIPHER_key_length(cipher); + server->hp.len = EVP_CIPHER_key_length(cipher); - qsec->client.in.iv.len = EVP_CIPHER_iv_length(cipher); - qsec->server.in.iv.len = EVP_CIPHER_iv_length(cipher); + client->iv.len = EVP_CIPHER_iv_length(cipher); + server->iv.len = EVP_CIPHER_iv_length(cipher); struct { ngx_str_t label; @@ -171,40 +171,40 @@ ngx_quic_set_initial_secret(ngx_pool_t * } seq[] = { /* draft-ietf-quic-tls-23#section-5.2 */ - { ngx_string("tls13 client in"), &qsec->client.in.secret, &iss }, + { ngx_string("tls13 client in"), &client->secret, &iss }, { ngx_string("tls13 quic key"), - &qsec->client.in.key, - &qsec->client.in.secret, + &client->key, + &client->secret, }, { ngx_string("tls13 quic iv"), - &qsec->client.in.iv, - &qsec->client.in.secret, + &client->iv, + &client->secret, }, { /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.4.1 */ ngx_string("tls13 quic hp"), - &qsec->client.in.hp, - &qsec->client.in.secret, + &client->hp, + &client->secret, }, - { ngx_string("tls13 server in"), &qsec->server.in.secret, &iss }, + { ngx_string("tls13 server in"), &server->secret, &iss }, { /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.3 */ ngx_string("tls13 quic key"), - &qsec->server.in.key, - &qsec->server.in.secret, + &server->key, + &server->secret, }, { ngx_string("tls13 quic iv"), - &qsec->server.in.iv, - &qsec->server.in.secret, + &server->iv, + &server->secret, }, { /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.4.1 */ ngx_string("tls13 quic hp"), - &qsec->server.in.hp, - &qsec->server.in.secret, + &server->hp, + &server->secret, }, }; @@ -604,12 +604,11 @@ failed: int ngx_quic_set_encryption_secret(ngx_pool_t *pool, ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level, const uint8_t *secret, - size_t secret_len, ngx_quic_peer_secrets_t *qsec) + size_t secret_len, ngx_quic_secret_t *peer_secret) { - ngx_int_t key_len; - ngx_uint_t i; - ngx_quic_secret_t *peer_secret; - ngx_quic_ciphers_t ciphers; + ngx_int_t key_len; + ngx_uint_t i; + ngx_quic_ciphers_t ciphers; key_len = ngx_quic_ciphers(ssl_conn, &ciphers, level); @@ -618,21 +617,7 @@ ngx_quic_set_encryption_secret(ngx_pool_ return 0; } - switch (level) { - - case ssl_encryption_early_data: - peer_secret = &qsec->ed; - break; - - case ssl_encryption_handshake: - peer_secret = &qsec->hs; - break; - - case ssl_encryption_application: - peer_secret = &qsec->ad; - break; - - default: + if (level == ssl_encryption_initial) { return 0; } diff --git a/src/event/ngx_event_quic_protection.h b/src/event/ngx_event_quic_protection.h --- a/src/event/ngx_event_quic_protection.h +++ b/src/event/ngx_event_quic_protection.h @@ -8,6 +8,9 @@ #define _NGX_EVENT_QUIC_PROTECTION_H_INCLUDED_ +#define NGX_QUIC_ENCRYPTION_LAST ((ssl_encryption_application) + 1) + + typedef struct ngx_quic_secret_s { ngx_str_t secret; ngx_str_t key; @@ -17,25 +20,18 @@ typedef struct ngx_quic_secret_s { typedef struct { - ngx_quic_secret_t in; - ngx_quic_secret_t ed; - ngx_quic_secret_t hs; - ngx_quic_secret_t ad; -} ngx_quic_peer_secrets_t; - - -typedef struct { - ngx_quic_peer_secrets_t client; - ngx_quic_peer_secrets_t server; + ngx_quic_secret_t client; + ngx_quic_secret_t server; } ngx_quic_secrets_t; ngx_int_t ngx_quic_set_initial_secret(ngx_pool_t *pool, - ngx_quic_secrets_t *secrets, ngx_str_t *secret); + ngx_quic_secret_t *client, ngx_quic_secret_t *server, + ngx_str_t *secret); int ngx_quic_set_encryption_secret(ngx_pool_t *pool, ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level, const uint8_t *secret, size_t secret_len, - ngx_quic_peer_secrets_t *qsec); + ngx_quic_secret_t *peer_secret); ssize_t ngx_quic_encrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, ngx_str_t *res);