QUIC: posted generating TLS Key Update next keys.

Since at least f9fbeb4ee0de and certainly after 924882f42dea, which
TLS Key Update support predates, queued data output is deferred to a
posted push handler.  To address timing signals after these changes,
generating next keys is now posted to run after the push handler.
This commit is contained in:
Sergey Kandaurov 2023-08-25 13:51:38 +04:00
parent f42519ff54
commit 24f3cb795e
5 changed files with 37 additions and 14 deletions

View File

@ -283,6 +283,10 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf,
qc->path_validation.data = c; qc->path_validation.data = c;
qc->path_validation.handler = ngx_quic_path_handler; qc->path_validation.handler = ngx_quic_path_handler;
qc->key_update.log = c->log;
qc->key_update.data = c;
qc->key_update.handler = ngx_quic_keys_update;
qc->conf = conf; qc->conf = conf;
if (ngx_quic_init_transport_params(&qc->tp, conf) != NGX_OK) { if (ngx_quic_init_transport_params(&qc->tp, conf) != NGX_OK) {
@ -562,6 +566,10 @@ ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc)
ngx_delete_posted_event(&qc->push); ngx_delete_posted_event(&qc->push);
} }
if (qc->key_update.posted) {
ngx_delete_posted_event(&qc->key_update);
}
if (qc->close.timer_set) { if (qc->close.timer_set) {
return; return;
} }
@ -1055,7 +1063,9 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
return rc; return rc;
} }
return ngx_quic_keys_update(c, qc->keys); ngx_post_event(&qc->key_update, &ngx_posted_events);
return NGX_OK;
} }

View File

@ -230,6 +230,8 @@ struct ngx_quic_connection_s {
ngx_event_t pto; ngx_event_t pto;
ngx_event_t close; ngx_event_t close;
ngx_event_t path_validation; ngx_event_t path_validation;
ngx_event_t key_update;
ngx_msec_t last_cc; ngx_msec_t last_cc;
ngx_msec_t first_rtt; ngx_msec_t first_rtt;

View File

@ -700,23 +700,32 @@ ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys)
} }
ngx_int_t void
ngx_quic_keys_update(ngx_connection_t *c, ngx_quic_keys_t *keys) ngx_quic_keys_update(ngx_event_t *ev)
{ {
ngx_uint_t i; ngx_uint_t i;
ngx_quic_hkdf_t seq[6]; ngx_quic_hkdf_t seq[6];
ngx_quic_ciphers_t ciphers; ngx_quic_keys_t *keys;
ngx_quic_secrets_t *current, *next; ngx_connection_t *c;
ngx_quic_ciphers_t ciphers;
ngx_quic_secrets_t *current, *next;
ngx_quic_connection_t *qc;
c = ev->data;
qc = ngx_quic_get_connection(c);
keys = qc->keys;
current = &keys->secrets[ssl_encryption_application]; current = &keys->secrets[ssl_encryption_application];
next = &keys->next_key; next = &keys->next_key;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic key update"); ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic key update");
c->log->action = "updating keys";
if (ngx_quic_ciphers(keys->cipher, &ciphers, ssl_encryption_application) if (ngx_quic_ciphers(keys->cipher, &ciphers, ssl_encryption_application)
== NGX_ERROR) == NGX_ERROR)
{ {
return NGX_ERROR; goto failed;
} }
next->client.secret.len = current->client.secret.len; next->client.secret.len = current->client.secret.len;
@ -744,11 +753,15 @@ ngx_quic_keys_update(ngx_connection_t *c, ngx_quic_keys_t *keys)
for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) { for (i = 0; i < (sizeof(seq) / sizeof(seq[0])); i++) {
if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, c->log) != NGX_OK) { if (ngx_quic_hkdf_expand(&seq[i], ciphers.d, c->log) != NGX_OK) {
return NGX_ERROR; goto failed;
} }
} }
return NGX_OK; return;
failed:
ngx_quic_close_connection(c, NGX_ERROR);
} }

View File

@ -99,7 +99,7 @@ ngx_uint_t ngx_quic_keys_available(ngx_quic_keys_t *keys,
void ngx_quic_keys_discard(ngx_quic_keys_t *keys, void ngx_quic_keys_discard(ngx_quic_keys_t *keys,
enum ssl_encryption_level_t level); enum ssl_encryption_level_t level);
void ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys); 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); void ngx_quic_keys_update(ngx_event_t *ev);
ngx_int_t ngx_quic_encrypt(ngx_quic_header_t *pkt, ngx_str_t *res); 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); ngx_int_t ngx_quic_decrypt(ngx_quic_header_t *pkt, uint64_t *largest_pn);
void ngx_quic_compute_nonce(u_char *nonce, size_t len, uint64_t pn); void ngx_quic_compute_nonce(u_char *nonce, size_t len, uint64_t pn);

View File

@ -482,9 +482,7 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data)
* Generating next keys before a key update is received. * Generating next keys before a key update is received.
*/ */
if (ngx_quic_keys_update(c, qc->keys) != NGX_OK) { ngx_post_event(&qc->key_update, &ngx_posted_events);
return NGX_ERROR;
}
/* /*
* RFC 9001, 4.9.2. Discarding Handshake Keys * RFC 9001, 4.9.2. Discarding Handshake Keys