From d7eeb2e30b4e90739d5784dd5369834fc7d390f6 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Wed, 1 Apr 2020 14:31:08 +0300 Subject: [PATCH] Introduced packet namespace in QUIC connection. The structure contains all data that is related to the namespace: packet number and output queue (next patch). --- src/event/ngx_event_quic.c | 45 +++++++++++++++++++-------- src/event/ngx_event_quic_protection.c | 4 +-- src/event/ngx_event_quic_transport.c | 4 +-- src/event/ngx_event_quic_transport.h | 2 +- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c index fc9499666..f3d46a590 100644 --- a/src/event/ngx_event_quic.c +++ b/src/event/ngx_event_quic.c @@ -9,6 +9,20 @@ #include +/* 0-RTT and 1-RTT data exist in the same packet number space, + * so we have 3 packet number spaces: + * + * 0 - Initial + * 1 - Handshake + * 2 - 0-RTT and 1-RTT + */ +#define ngx_quic_ns(level) \ + ((level) == ssl_encryption_initial) ? 0 \ + : (((level) == ssl_encryption_handshake) ? 1 : 2) + +#define NGX_QUIC_NAMESPACE_LAST (NGX_QUIC_ENCRYPTION_LAST - 1) + + typedef enum { NGX_QUIC_ST_INITIAL, /* connection just created */ NGX_QUIC_ST_HANDSHAKE, /* handshake started */ @@ -26,6 +40,14 @@ typedef struct { } ngx_quic_streams_t; +typedef struct { + ngx_quic_secret_t client_secret; + ngx_quic_secret_t server_secret; + + ngx_uint_t pnum; +} ngx_quic_namespace_t; + + struct ngx_quic_connection_s { ngx_str_t scid; ngx_str_t dcid; @@ -37,11 +59,7 @@ struct ngx_quic_connection_s { ngx_quic_state_t state; - /* current packet numbers for each namespace */ - ngx_uint_t initial_pn; - ngx_uint_t handshake_pn; - ngx_uint_t appdata_pn; - + ngx_quic_namespace_t ns[NGX_QUIC_NAMESPACE_LAST]; ngx_quic_secrets_t keys[NGX_QUIC_ENCRYPTION_LAST]; uint64_t crypto_offset[NGX_QUIC_ENCRYPTION_LAST]; @@ -1106,11 +1124,14 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) return NGX_ERROR; } - ack_frame->level = pkt->level; + ack_frame->level = (pkt->level == ssl_encryption_early_data) + ? ssl_encryption_application + : pkt->level; + ack_frame->type = NGX_QUIC_FT_ACK; ack_frame->u.ack.pn = pkt->pn; - ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, pkt->level); + ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, ack_frame->level); ngx_quic_queue_frame(qc, ack_frame); return ngx_quic_output(c); @@ -1454,6 +1475,7 @@ ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start, ngx_quic_frame_t *f; ngx_quic_header_t pkt; ngx_quic_secrets_t *keys; + ngx_quic_namespace_t *ns; ngx_quic_connection_t *qc; static ngx_str_t initial_token = ngx_null_string; static u_char src[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; @@ -1493,20 +1515,17 @@ ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start, qc = c->quic; keys = &c->quic->keys[start->level]; + ns = &c->quic->ns[ngx_quic_ns(start->level)]; pkt.secret = &keys->server; + pkt.number = ns->pnum; if (start->level == ssl_encryption_initial) { - pkt.number = &qc->initial_pn; pkt.flags = NGX_QUIC_PKT_INITIAL; pkt.token = initial_token; } else if (start->level == ssl_encryption_handshake) { - pkt.number = &qc->handshake_pn; pkt.flags = NGX_QUIC_PKT_HANDSHAKE; - - } else { - pkt.number = &qc->appdata_pn; } pkt.log = c->log; @@ -1525,7 +1544,7 @@ ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start, c->send(c, res.data, res.len); // TODO: err handling - (*pkt.number)++; + ns->pnum++; return NGX_OK; } diff --git a/src/event/ngx_event_quic_protection.c b/src/event/ngx_event_quic_protection.c index 34289d856..bf831109d 100644 --- a/src/event/ngx_event_quic_protection.c +++ b/src/event/ngx_event_quic_protection.c @@ -673,7 +673,7 @@ ngx_quic_create_long_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, } ngx_memcpy(nonce, pkt->secret->iv.data, pkt->secret->iv.len); - pn = *pkt->number; + pn = pkt->number; nonce[11] ^= pn; ngx_quic_hexdump0(pkt->log, "server_iv", pkt->secret->iv.data, 12); @@ -731,7 +731,7 @@ ngx_quic_create_short_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn, if (pkt->level == ssl_encryption_handshake || pkt->level == ssl_encryption_application) { - nonce[11] ^= *pkt->number; + nonce[11] ^= pkt->number; } ngx_quic_hexdump0(pkt->log, "server_iv", pkt->secret->iv.data, 12); diff --git a/src/event/ngx_event_quic_transport.c b/src/event/ngx_event_quic_transport.c index 467a41157..bfa3867ea 100644 --- a/src/event/ngx_event_quic_transport.c +++ b/src/event/ngx_event_quic_transport.c @@ -366,7 +366,7 @@ ngx_quic_create_long_header(ngx_quic_header_t *pkt, u_char *out, *pnp = p; - *p++ = (uint64_t) (*pkt->number); + *p++ = pkt->number; // XXX: uint64 return p - start; } @@ -386,7 +386,7 @@ ngx_quic_create_short_header(ngx_quic_header_t *pkt, u_char *out, *pnp = p; - *p++ = (*pkt->number); + *p++ = pkt->number; // XXX: uint64 return p - start; } diff --git a/src/event/ngx_event_quic_transport.h b/src/event/ngx_event_quic_transport.h index c12f6c66a..8268d0410 100644 --- a/src/event/ngx_event_quic_transport.h +++ b/src/event/ngx_event_quic_transport.h @@ -232,7 +232,7 @@ typedef struct { ngx_log_t *log; struct ngx_quic_secret_s *secret; - ngx_uint_t *number; + uint64_t number; uint8_t flags; uint32_t version; ngx_str_t token;