Mercurial > hg > nginx
diff src/event/ngx_event_quic.c @ 8319:29354c6fc5f2 quic
TLS Key Update in QUIC.
Old keys retention is yet to be implemented.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Mon, 06 Apr 2020 14:54:08 +0300 |
parents | 0dc0552335bd |
children | 6e1213ef469a |
line wrap: on
line diff
--- a/src/event/ngx_event_quic.c +++ b/src/event/ngx_event_quic.c @@ -68,6 +68,7 @@ struct ngx_quic_connection_s { ngx_quic_namespace_t ns[NGX_QUIC_NAMESPACE_LAST]; ngx_quic_secrets_t keys[NGX_QUIC_ENCRYPTION_LAST]; + ngx_quic_secrets_t next_key; uint64_t crypto_offset[NGX_QUIC_ENCRYPTION_LAST]; ngx_ssl_t *ssl; @@ -88,6 +89,7 @@ struct ngx_quic_connection_s { unsigned send_timer_set:1; unsigned closing:1; + unsigned key_phase:1; }; @@ -979,7 +981,8 @@ 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_int_t rc; + ngx_quic_secrets_t *keys, *next, tmp; ngx_quic_connection_t *qc; static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; @@ -988,6 +991,7 @@ ngx_quic_app_input(ngx_connection_t *c, qc = c->quic; keys = &c->quic->keys[ssl_encryption_application]; + next = &c->quic->next_key; if (keys->client.key.len == 0) { ngx_log_error(NGX_LOG_INFO, c->log, 0, @@ -1000,6 +1004,8 @@ ngx_quic_app_input(ngx_connection_t *c, } pkt->secret = &keys->client; + pkt->next = &next->client; + pkt->key_phase = c->quic->key_phase; pkt->level = ssl_encryption_application; pkt->plaintext = buf; @@ -1007,7 +1013,31 @@ ngx_quic_app_input(ngx_connection_t *c, return NGX_ERROR; } - return ngx_quic_payload_handler(c, pkt); + /* switch keys on Key Phase change */ + + if (pkt->key_update) { + c->quic->key_phase ^= 1; + + tmp = *keys; + *keys = *next; + *next = tmp; + } + + rc = ngx_quic_payload_handler(c, pkt); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + /* generate next keys */ + + if (pkt->key_update) { + if (ngx_quic_key_update(c, keys, next) != NGX_OK) { + return NGX_ERROR; + } + } + + return rc; } @@ -1330,6 +1360,18 @@ ngx_quic_handle_crypto_frame(ngx_connect ngx_quic_queue_frame(c->quic, frame); } #endif + + /* + * Generating next keys before a key update is received. + * 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) + { + return NGX_ERROR; + } } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, @@ -1756,7 +1798,8 @@ ngx_quic_send_frames(ngx_connection_t *c pkt.flags = NGX_QUIC_PKT_HANDSHAKE; } else { - pkt.flags = 0x40; // TODO: macro, set FIXED bit + // TODO: macro, set FIXED bit + pkt.flags = 0x40 | (c->quic->key_phase ? NGX_QUIC_PKT_KPHASE : 0); } ngx_quic_set_packet_number(&pkt, ns);