# HG changeset patch # User Sergey Kandaurov # Date 1604330494 -10800 # Node ID 9c3be23ddbe71fde1d18ee707d8ad260f3a1f4a1 # Parent d10118e3894307073e4c9ab3ec305e9d4fb1242b QUIC: refactored key handling. All key handling functionality is moved into ngx_quic_protection.c. Public structures from ngx_quic_protection.h are now private and new methods are available to manipulate keys. A negotiated cipher is cached in QUIC connection from the set secret callback to avoid calling SSL_get_current_cipher() on each encrypt/decrypt operation. This also reduces the number of unwanted c->ssl->connection occurrences. 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 @@ -94,9 +94,6 @@ typedef struct { * are also Initial packets. */ typedef struct { - ngx_quic_secret_t client_secret; - ngx_quic_secret_t server_secret; - enum ssl_encryption_level_t level; uint64_t pnum; /* to be sent */ @@ -134,10 +131,11 @@ struct ngx_quic_connection_s { ngx_quic_tp_t ctp; ngx_quic_send_ctx_t send_ctx[NGX_QUIC_SEND_CTX_LAST]; - ngx_quic_secrets_t keys[NGX_QUIC_ENCRYPTION_LAST]; - ngx_quic_secrets_t next_key; + ngx_quic_frames_stream_t crypto[NGX_QUIC_ENCRYPTION_LAST]; + ngx_quic_keys_t *keys; + ngx_quic_conf_t *conf; ngx_event_t push; @@ -643,8 +641,7 @@ 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_quic_secrets_t *keys; + ngx_connection_t *c; c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); @@ -654,11 +651,8 @@ ngx_quic_set_read_secret(ngx_ssl_conn_t ngx_quic_hexdump(c->log, "quic read secret", rsecret, secret_len); #endif - keys = &c->quic->keys[level]; - - return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, - rsecret, secret_len, - &keys->client); + return ngx_quic_keys_set_encryption_secret(c->pool, 0, c->quic->keys, level, + cipher, rsecret, secret_len); } @@ -667,8 +661,7 @@ 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_quic_secrets_t *keys; + ngx_connection_t *c; c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); @@ -678,11 +671,8 @@ ngx_quic_set_write_secret(ngx_ssl_conn_t ngx_quic_hexdump(c->log, "quic write secret", wsecret, secret_len); #endif - keys = &c->quic->keys[level]; - - return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, - wsecret, secret_len, - &keys->server); + return ngx_quic_keys_set_encryption_secret(c->pool, 1, c->quic->keys, level, + cipher, wsecret, secret_len); } #else @@ -692,25 +682,24 @@ 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_quic_secrets_t *keys; + ngx_connection_t *c; + const SSL_CIPHER *cipher; c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic ngx_quic_set_encryption_secrets() level:%d", level); #ifdef NGX_QUIC_DEBUG_CRYPTO - ngx_quic_hexdump(c->log, "quic read", rsecret, secret_len); + ngx_quic_hexdump(c->log, "quic read secret", rsecret, secret_len); #endif - keys = &c->quic->keys[level]; - - rc = ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, - rsecret, secret_len, - &keys->client); - if (rc != 1) { - return rc; + cipher = SSL_get_current_cipher(ssl_conn); + + if (ngx_quic_keys_set_encryption_secret(c->pool, 0, c->quic->keys, level, + cipher, rsecret, secret_len) + != 1) + { + return 0; } if (level == ssl_encryption_early_data) { @@ -718,12 +707,11 @@ ngx_quic_set_encryption_secrets(ngx_ssl_ } #ifdef NGX_QUIC_DEBUG_CRYPTO - ngx_quic_hexdump(c->log, "quic write", wsecret, secret_len); + ngx_quic_hexdump(c->log, "quic write secret", wsecret, secret_len); #endif - return ngx_quic_set_encryption_secret(c->pool, ssl_conn, level, - wsecret, secret_len, - &keys->server); + return ngx_quic_keys_set_encryption_secret(c->pool, 1, c->quic->keys, level, + cipher, wsecret, secret_len); } #endif @@ -965,6 +953,11 @@ ngx_quic_new_connection(ngx_connection_t return NULL; } + qc->keys = ngx_quic_keys_new(c->pool); + if (qc->keys == NULL) { + return NULL; + } + ngx_rbtree_init(&qc->streams.tree, &qc->streams.sentinel, ngx_quic_rbtree_insert_stream); @@ -1239,7 +1232,7 @@ ngx_quic_send_retry(ngx_connection_t *c) res.data = buf; - if (ngx_quic_encrypt(&pkt, NULL, &res) != NGX_OK) { + if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) { return NGX_ERROR; } @@ -1990,8 +1983,6 @@ ngx_quic_process_packet(ngx_connection_t ngx_quic_header_t *pkt) { ngx_int_t rc; - ngx_ssl_conn_t *ssl_conn; - ngx_quic_secrets_t *keys, *next, tmp; ngx_quic_send_ctx_t *ctx; ngx_quic_connection_t *qc; @@ -2135,26 +2126,19 @@ ngx_quic_process_packet(ngx_connection_t c->log->action = "decrypting packet"; - keys = &qc->keys[pkt->level]; - - if (keys->client.key.len == 0) { + if (!ngx_quic_keys_available(qc->keys, pkt->level)) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic no level %d keys yet, ignoring packet", pkt->level); return NGX_DECLINED; } - next = &qc->next_key; - - pkt->secret = &keys->client; - pkt->next = &next->client; + pkt->keys = qc->keys; pkt->key_phase = qc->key_phase; pkt->plaintext = buf; ctx = ngx_quic_get_send_ctx(qc, pkt->level); - ssl_conn = c->ssl ? c->ssl->connection : NULL; - - rc = ngx_quic_decrypt(pkt, ssl_conn, &ctx->largest_pn); + rc = ngx_quic_decrypt(pkt, &ctx->largest_pn); if (rc != NGX_OK) { qc->error = pkt->error; qc->error_reason = "failed to decrypt packet"; @@ -2190,44 +2174,32 @@ ngx_quic_process_packet(ngx_connection_t return ngx_quic_payload_handler(c, pkt); } - /* switch keys on Key Phase change */ - - if (pkt->key_update) { - qc->key_phase ^= 1; - - tmp = *keys; - *keys = *next; - *next = tmp; - } + if (!pkt->key_update) { + return ngx_quic_payload_handler(c, pkt); + } + + /* switch keys and generate next on Key Phase change */ + + qc->key_phase ^= 1; + ngx_quic_keys_switch(c, qc->keys); rc = ngx_quic_payload_handler(c, pkt); if (rc != NGX_OK) { return rc; } - /* generate next keys */ - - if (pkt->key_update) { - if (ngx_quic_key_update(c, keys, next) != NGX_OK) { - return NGX_ERROR; - } - } - - return NGX_OK; + return ngx_quic_keys_update(c, qc->keys); } static ngx_int_t ngx_quic_init_secrets(ngx_connection_t *c) { - ngx_quic_secrets_t *keys; ngx_quic_connection_t *qc; - qc =c->quic; - keys = &qc->keys[ssl_encryption_initial]; - - if (ngx_quic_set_initial_secret(c->pool, &keys->client, &keys->server, - &qc->odcid) + qc = c->quic; + + if (ngx_quic_keys_set_initial_secret(c->pool, qc->keys, &qc->odcid) != NGX_OK) { return NGX_ERROR; @@ -2249,11 +2221,12 @@ ngx_quic_discard_ctx(ngx_connection_t *c qc = c->quic; - if (qc->keys[level].client.key.len == 0) { + if (!ngx_quic_keys_available(qc->keys, level)) { return; } - qc->keys[level].client.key.len = 0; + ngx_quic_keys_discard(qc->keys, level); + qc->pto_count = 0; ctx = ngx_quic_get_send_ctx(qc, level); @@ -3634,10 +3607,7 @@ ngx_quic_crypto_input(ngx_connection_t * * See quic-tls 9.4 Header Protection Timing Side-Channels. */ - if (ngx_quic_key_update(c, &c->quic->keys[ssl_encryption_application], - &c->quic->next_key) - != NGX_OK) - { + if (ngx_quic_keys_update(c, c->quic->keys) != NGX_OK) { return NGX_ERROR; } @@ -4503,10 +4473,8 @@ ngx_quic_send_frames(ngx_connection_t *c ngx_str_t out, res; ngx_msec_t now; ngx_queue_t *q; - ngx_ssl_conn_t *ssl_conn; ngx_quic_frame_t *f, *start; ngx_quic_header_t pkt; - ngx_quic_secrets_t *keys; ngx_quic_connection_t *qc; static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; @@ -4514,8 +4482,6 @@ ngx_quic_send_frames(ngx_connection_t *c ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic ngx_quic_send_frames"); - ssl_conn = c->ssl ? c->ssl->connection : NULL; - q = ngx_queue_head(frames); start = ngx_queue_data(q, ngx_quic_frame_t, queue); @@ -4554,9 +4520,7 @@ ngx_quic_send_frames(ngx_connection_t *c qc = c->quic; - keys = &c->quic->keys[start->level]; - - pkt.secret = &keys->server; + pkt.keys = qc->keys; pkt.flags = NGX_QUIC_PKT_FIXED_BIT; @@ -4603,7 +4567,7 @@ ngx_quic_send_frames(ngx_connection_t *c ngx_quic_level_name(start->level), out.len, pkt.need_ack, pkt.number, pkt.num_len, pkt.trunc); - if (ngx_quic_encrypt(&pkt, ssl_conn, &res) != NGX_OK) { + if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) { ngx_quic_free_frames(c, frames); return NGX_ERROR; } diff --git a/src/event/ngx_event_quic.h b/src/event/ngx_event_quic.h --- a/src/event/ngx_event_quic.h +++ b/src/event/ngx_event_quic.h @@ -116,6 +116,9 @@ struct ngx_quic_stream_s { }; +typedef struct ngx_quic_keys_s ngx_quic_keys_t; + + void ngx_quic_run(ngx_connection_t *c, ngx_quic_conf_t *conf); ngx_connection_t *ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi); void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err, 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 @@ -24,6 +24,7 @@ #define ngx_quic_cipher_t EVP_CIPHER #endif + typedef struct { const ngx_quic_cipher_t *c; const EVP_CIPHER *hp; @@ -31,6 +32,27 @@ typedef struct { } ngx_quic_ciphers_t; +typedef struct ngx_quic_secret_s { + ngx_str_t secret; + ngx_str_t key; + ngx_str_t iv; + ngx_str_t hp; +} ngx_quic_secret_t; + + +typedef struct { + ngx_quic_secret_t client; + ngx_quic_secret_t server; +} ngx_quic_secrets_t; + + +struct ngx_quic_keys_s { + ngx_quic_secrets_t secrets[NGX_QUIC_ENCRYPTION_LAST]; + ngx_quic_secrets_t next_key; + ngx_uint_t cipher; +}; + + static ngx_int_t ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest, const u_char *prk, size_t prk_len, const u_char *info, size_t info_len); @@ -41,7 +63,7 @@ static ngx_int_t ngx_hkdf_extract(u_char static uint64_t ngx_quic_parse_pn(u_char **pos, ngx_int_t len, u_char *mask, uint64_t *largest_pn); static void ngx_quic_compute_nonce(u_char *nonce, size_t len, uint64_t pn); -static ngx_int_t ngx_quic_ciphers(ngx_ssl_conn_t *ssl_conn, +static ngx_int_t ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers, enum ssl_encryption_level_t level); static ngx_int_t ngx_quic_tls_open(const ngx_quic_cipher_t *cipher, @@ -56,30 +78,21 @@ static ngx_int_t ngx_quic_hkdf_expand(ng ngx_str_t *out, ngx_str_t *label, const uint8_t *prk, size_t prk_len); static ngx_int_t ngx_quic_create_long_packet(ngx_quic_header_t *pkt, - ngx_ssl_conn_t *ssl_conn, ngx_str_t *res); + ngx_str_t *res); static ngx_int_t ngx_quic_create_short_packet(ngx_quic_header_t *pkt, - ngx_ssl_conn_t *ssl_conn, ngx_str_t *res); + ngx_str_t *res); static ngx_int_t ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res); static ngx_int_t -ngx_quic_ciphers(ngx_ssl_conn_t *ssl_conn, ngx_quic_ciphers_t *ciphers, +ngx_quic_ciphers(ngx_uint_t id, ngx_quic_ciphers_t *ciphers, enum ssl_encryption_level_t level) { - ngx_int_t id, len; - const SSL_CIPHER *cipher; + ngx_int_t len; if (level == ssl_encryption_initial) { id = NGX_AES_128_GCM_SHA256; - - } else { - cipher = SSL_get_current_cipher(ssl_conn); - if (cipher == NULL) { - return NGX_ERROR; - } - - id = SSL_CIPHER_get_id(cipher) & 0xffff; } switch (id) { @@ -130,14 +143,15 @@ ngx_quic_ciphers(ngx_ssl_conn_t *ssl_con ngx_int_t -ngx_quic_set_initial_secret(ngx_pool_t *pool, ngx_quic_secret_t *client, - ngx_quic_secret_t *server, ngx_str_t *secret) +ngx_quic_keys_set_initial_secret(ngx_pool_t *pool, ngx_quic_keys_t *keys, + ngx_str_t *secret) { - size_t is_len; - uint8_t is[SHA256_DIGEST_LENGTH]; - ngx_uint_t i; - const EVP_MD *digest; - const EVP_CIPHER *cipher; + size_t is_len; + uint8_t is[SHA256_DIGEST_LENGTH]; + ngx_uint_t i; + const EVP_MD *digest; + const EVP_CIPHER *cipher; + ngx_quic_secret_t *client, *server; static const uint8_t salt[20] = #if (NGX_QUIC_DRAFT_VERSION >= 29) @@ -148,6 +162,9 @@ ngx_quic_set_initial_secret(ngx_pool_t * "\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02"; #endif + client = &keys->secrets[ssl_encryption_initial].client; + server = &keys->secrets[ssl_encryption_initial].server; + /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.3 */ cipher = EVP_aes_128_gcm(); @@ -626,16 +643,25 @@ 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_secret_t *peer_secret) +int ngx_quic_keys_set_encryption_secret(ngx_pool_t *pool, ngx_uint_t is_write, + ngx_quic_keys_t *keys, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len) { - ngx_int_t key_len; - ngx_uint_t i; - ngx_quic_ciphers_t ciphers; + ngx_int_t key_len; + ngx_uint_t i; + ngx_quic_secret_t *peer_secret; + ngx_quic_ciphers_t ciphers; + + peer_secret = is_write ? &keys->secrets[level].server + : &keys->secrets[level].client; - key_len = ngx_quic_ciphers(ssl_conn, &ciphers, level); + /* + * SSL_CIPHER_get_protocol_id() is not universally available, + * casting to uint16_t works for both OpenSSL and BoringSSL + */ + keys->cipher = (uint16_t) SSL_CIPHER_get_id(cipher); + + key_len = ngx_quic_ciphers(keys->cipher, &ciphers, level); if (key_len == NGX_ERROR) { ngx_ssl_error(NGX_LOG_INFO, pool->log, 0, "unexpected cipher"); @@ -682,17 +708,56 @@ ngx_quic_set_encryption_secret(ngx_pool_ } +ngx_quic_keys_t * +ngx_quic_keys_new(ngx_pool_t *pool) +{ + return ngx_pcalloc(pool, sizeof(ngx_quic_keys_t)); +} + + +ngx_uint_t +ngx_quic_keys_available(ngx_quic_keys_t *keys, + enum ssl_encryption_level_t level) +{ + return keys->secrets[level].client.key.len != 0; +} + + +void +ngx_quic_keys_discard(ngx_quic_keys_t *keys, + enum ssl_encryption_level_t level) +{ + keys->secrets[level].client.key.len = 0; +} + + +void +ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys) +{ + ngx_quic_secrets_t *current, *next, tmp; + + current = &keys->secrets[ssl_encryption_application]; + next = &keys->next_key; + + tmp = *current; + *current = *next; + *next = tmp; +} + + ngx_int_t -ngx_quic_key_update(ngx_connection_t *c, ngx_quic_secrets_t *current, - ngx_quic_secrets_t *next) +ngx_quic_keys_update(ngx_connection_t *c, ngx_quic_keys_t *keys) { - ngx_uint_t i; - ngx_quic_ciphers_t ciphers; + ngx_uint_t i; + ngx_quic_ciphers_t ciphers; + ngx_quic_secrets_t *current, *next; + + current = &keys->secrets[ssl_encryption_application]; + next = &keys->next_key; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic key update"); - if (ngx_quic_ciphers(c->ssl->connection, &ciphers, - ssl_encryption_application) + if (ngx_quic_ciphers(keys->cipher, &ciphers, ssl_encryption_application) == NGX_ERROR) { return NGX_ERROR; @@ -760,12 +825,12 @@ ngx_quic_key_update(ngx_connection_t *c, static ngx_int_t -ngx_quic_create_long_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, - ngx_str_t *res) +ngx_quic_create_long_packet(ngx_quic_header_t *pkt, ngx_str_t *res) { u_char *pnp, *sample; ngx_str_t ad, out; ngx_uint_t i; + ngx_quic_secret_t *secret; ngx_quic_ciphers_t ciphers; u_char nonce[12], mask[16]; @@ -780,14 +845,17 @@ ngx_quic_create_long_packet(ngx_quic_hea ngx_quic_hexdump(pkt->log, "quic ad", ad.data, ad.len); #endif - if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) { + if (ngx_quic_ciphers(pkt->keys->cipher, &ciphers, pkt->level) == NGX_ERROR) + { return NGX_ERROR; } - ngx_memcpy(nonce, pkt->secret->iv.data, pkt->secret->iv.len); + secret = &pkt->keys->secrets[pkt->level].server; + + ngx_memcpy(nonce, secret->iv.data, secret->iv.len); ngx_quic_compute_nonce(nonce, sizeof(nonce), pkt->number); - if (ngx_quic_tls_seal(ciphers.c, pkt->secret, &out, + if (ngx_quic_tls_seal(ciphers.c, secret, &out, nonce, &pkt->payload, &ad, pkt->log) != NGX_OK) { @@ -795,7 +863,7 @@ ngx_quic_create_long_packet(ngx_quic_hea } sample = &out.data[4 - pkt->num_len]; - if (ngx_quic_tls_hp(pkt->log, ciphers.hp, pkt->secret, mask, sample) + if (ngx_quic_tls_hp(pkt->log, ciphers.hp, secret, mask, sample) != NGX_OK) { return NGX_ERROR; @@ -815,12 +883,12 @@ ngx_quic_create_long_packet(ngx_quic_hea static ngx_int_t -ngx_quic_create_short_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, - ngx_str_t *res) +ngx_quic_create_short_packet(ngx_quic_header_t *pkt, ngx_str_t *res) { u_char *pnp, *sample; ngx_str_t ad, out; ngx_uint_t i; + ngx_quic_secret_t *secret; ngx_quic_ciphers_t ciphers; u_char nonce[12], mask[16]; @@ -835,14 +903,17 @@ ngx_quic_create_short_packet(ngx_quic_he ngx_quic_hexdump(pkt->log, "quic ad", ad.data, ad.len); #endif - if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) { + if (ngx_quic_ciphers(pkt->keys->cipher, &ciphers, pkt->level) == NGX_ERROR) + { return NGX_ERROR; } - ngx_memcpy(nonce, pkt->secret->iv.data, pkt->secret->iv.len); + secret = &pkt->keys->secrets[pkt->level].server; + + ngx_memcpy(nonce, secret->iv.data, secret->iv.len); ngx_quic_compute_nonce(nonce, sizeof(nonce), pkt->number); - if (ngx_quic_tls_seal(ciphers.c, pkt->secret, &out, + if (ngx_quic_tls_seal(ciphers.c, secret, &out, nonce, &pkt->payload, &ad, pkt->log) != NGX_OK) { @@ -850,7 +921,7 @@ ngx_quic_create_short_packet(ngx_quic_he } sample = &out.data[4 - pkt->num_len]; - if (ngx_quic_tls_hp(pkt->log, ciphers.hp, pkt->secret, mask, sample) + if (ngx_quic_tls_hp(pkt->log, ciphers.hp, secret, mask, sample) != NGX_OK) { return NGX_ERROR; @@ -902,7 +973,7 @@ ngx_quic_create_retry_packet(ngx_quic_he ngx_quic_hexdump(pkt->log, "quic retry itag", ad.data, ad.len); #endif - if (ngx_quic_ciphers(NULL, &ciphers, pkt->level) == NGX_ERROR) { + if (ngx_quic_ciphers(0, &ciphers, pkt->level) == NGX_ERROR) { return NGX_ERROR; } @@ -1033,24 +1104,22 @@ ngx_quic_compute_nonce(u_char *nonce, si ngx_int_t -ngx_quic_encrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, - ngx_str_t *res) +ngx_quic_encrypt(ngx_quic_header_t *pkt, ngx_str_t *res) { if (ngx_quic_short_pkt(pkt->flags)) { - return ngx_quic_create_short_packet(pkt, ssl_conn, res); + return ngx_quic_create_short_packet(pkt, res); } if (ngx_quic_pkt_retry(pkt->flags)) { return ngx_quic_create_retry_packet(pkt, res); } - return ngx_quic_create_long_packet(pkt, ssl_conn, res); + return ngx_quic_create_long_packet(pkt, res); } ngx_int_t -ngx_quic_decrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, - uint64_t *largest_pn) +ngx_quic_decrypt(ngx_quic_header_t *pkt, uint64_t *largest_pn) { u_char clearflags, *p, *sample; size_t len; @@ -1062,11 +1131,12 @@ ngx_quic_decrypt(ngx_quic_header_t *pkt, ngx_quic_ciphers_t ciphers; uint8_t mask[16], nonce[12]; - if (ngx_quic_ciphers(ssl_conn, &ciphers, pkt->level) == NGX_ERROR) { + if (ngx_quic_ciphers(pkt->keys->cipher, &ciphers, pkt->level) == NGX_ERROR) + { return NGX_ERROR; } - secret = pkt->secret; + secret = &pkt->keys->secrets[pkt->level].client; p = pkt->raw->pos; len = pkt->data + pkt->len - p; @@ -1099,7 +1169,7 @@ ngx_quic_decrypt(ngx_quic_header_t *pkt, key_phase = (clearflags & NGX_QUIC_PKT_KPHASE) != 0; if (key_phase != pkt->key_phase) { - secret = pkt->next; + secret = &pkt->keys->next_key.client; pkt->key_update = 1; } } 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 @@ -15,37 +15,24 @@ #define NGX_QUIC_ENCRYPTION_LAST ((ssl_encryption_application) + 1) -typedef struct ngx_quic_secret_s { - ngx_str_t secret; - ngx_str_t key; - ngx_str_t iv; - ngx_str_t hp; -} ngx_quic_secret_t; - +ngx_quic_keys_t *ngx_quic_keys_new(ngx_pool_t *pool); +ngx_int_t ngx_quic_keys_set_initial_secret(ngx_pool_t *pool, + ngx_quic_keys_t *keys, ngx_str_t *secret); +int ngx_quic_keys_set_encryption_secret(ngx_pool_t *pool, ngx_uint_t is_write, + ngx_quic_keys_t *keys, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len); +ngx_uint_t ngx_quic_keys_available(ngx_quic_keys_t *keys, + enum ssl_encryption_level_t level); +void ngx_quic_keys_discard(ngx_quic_keys_t *keys, + enum ssl_encryption_level_t level); +void ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys); +ngx_int_t ngx_quic_keys_update(ngx_connection_t *c, ngx_quic_keys_t *keys); -typedef struct { - 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_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_secret_t *peer_secret); - -ngx_int_t ngx_quic_key_update(ngx_connection_t *c, - ngx_quic_secrets_t *current, ngx_quic_secrets_t *next); ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, ngx_str_t *key, u_char *token); -ngx_int_t ngx_quic_encrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, - ngx_str_t *res); -ngx_int_t ngx_quic_decrypt(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, - uint64_t *largest_pn); +ngx_int_t ngx_quic_encrypt(ngx_quic_header_t *pkt, ngx_str_t *res); +ngx_int_t ngx_quic_decrypt(ngx_quic_header_t *pkt, uint64_t *largest_pn); #endif /* _NGX_EVENT_QUIC_PROTECTION_H_INCLUDED_ */ diff --git a/src/event/ngx_event_quic_transport.h b/src/event/ngx_event_quic_transport.h --- a/src/event/ngx_event_quic_transport.h +++ b/src/event/ngx_event_quic_transport.h @@ -290,8 +290,8 @@ struct ngx_quic_frame_s { typedef struct { ngx_log_t *log; - struct ngx_quic_secret_s *secret; - struct ngx_quic_secret_s *next; + ngx_quic_keys_t *keys; + ngx_msec_t received; uint64_t number; uint8_t num_len;