return NGX_ERROR;
}
- if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
- return NGX_ERROR;
+ rc = ngx_quic_parse_long_header(pkt);
+ if (rc != NGX_OK) {
+ return rc;
}
if (!ngx_quic_pkt_in(pkt->flags)) {
ctx = ngx_quic_get_send_ctx(qc, pkt->level);
if (ngx_quic_decrypt(pkt, NULL, &ctx->largest_pn) != NGX_OK) {
+ qc->error = pkt->error;
return NGX_ERROR;
}
static ngx_int_t
ngx_quic_retry_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
{
+ ngx_int_t rc;
ngx_quic_secrets_t *keys;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
return NGX_OK;
}
- if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
- return NGX_ERROR;
+ rc = ngx_quic_parse_long_header(pkt);
+ if (rc != NGX_OK) {
+ return rc;
}
if (ngx_quic_pkt_zrtt(pkt->flags)) {
ctx = ngx_quic_get_send_ctx(qc, pkt->level);
if (ngx_quic_decrypt(pkt, NULL, &ctx->largest_pn) != NGX_OK) {
+ qc->error = pkt->error;
return NGX_ERROR;
}
static ngx_int_t
ngx_quic_initial_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
{
+ ngx_int_t rc;
ngx_ssl_conn_t *ssl_conn;
ngx_quic_secrets_t *keys;
ngx_quic_send_ctx_t *ctx;
ssl_conn = c->ssl->connection;
- if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
- return NGX_ERROR;
+ rc = ngx_quic_parse_long_header(pkt);
+ if (rc != NGX_OK) {
+ return rc;
}
if (ngx_quic_parse_initial_header(pkt) != NGX_OK) {
ctx = ngx_quic_get_send_ctx(c->quic, pkt->level);
if (ngx_quic_decrypt(pkt, ssl_conn, &ctx->largest_pn) != NGX_OK) {
+ c->quic->error = pkt->error;
return NGX_ERROR;
}
static ngx_int_t
ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
{
+ ngx_int_t rc;
ngx_quic_secrets_t *keys;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
}
/* extract cleartext data into pkt */
- if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
- return NGX_ERROR;
+ rc = ngx_quic_parse_long_header(pkt);
+ if (rc != NGX_OK) {
+ return rc;
}
if (ngx_quic_check_peer(qc, pkt) != NGX_OK) {
ctx = ngx_quic_get_send_ctx(qc, pkt->level);
if (ngx_quic_decrypt(pkt, c->ssl->connection, &ctx->largest_pn) != NGX_OK) {
+ qc->error = pkt->error;
return NGX_ERROR;
}
static ngx_int_t
ngx_quic_early_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
{
+ ngx_int_t rc;
ngx_quic_secrets_t *keys;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
qc = c->quic;
/* extract cleartext data into pkt */
- if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
- return NGX_ERROR;
+ rc = ngx_quic_parse_long_header(pkt);
+ if (rc != NGX_OK) {
+ return rc;
}
if (ngx_quic_check_peer(qc, pkt) != NGX_OK) {
ctx = ngx_quic_get_send_ctx(qc, pkt->level);
if (ngx_quic_decrypt(pkt, c->ssl->connection, &ctx->largest_pn) != NGX_OK) {
+ qc->error = pkt->error;
return NGX_ERROR;
}
return NGX_DECLINED;
}
- if (ngx_quic_parse_short_header(pkt, &qc->dcid) != NGX_OK) {
- return NGX_ERROR;
+ rc = ngx_quic_parse_short_header(pkt, &qc->dcid);
+ if (rc != NGX_OK) {
+ return rc;
}
pkt->secret = &keys->client;
ctx = ngx_quic_get_send_ctx(qc, pkt->level);
if (ngx_quic_decrypt(pkt, c->ssl->connection, &ctx->largest_pn) != NGX_OK) {
+ qc->error = pkt->error;
return NGX_ERROR;
}
uint64_t *largest_pn)
{
u_char clearflags, *p, *sample;
+ uint8_t badflags;
uint64_t pn;
ngx_int_t pnl, rc, key_phase;
ngx_str_t in, ad;
if (ngx_quic_tls_hp(pkt->log, ciphers.hp, secret, mask, sample)
!= NGX_OK)
{
+ pkt->error = NGX_QUIC_ERR_CRYPTO_ERROR;
return NGX_ERROR;
}
if (ngx_quic_long_pkt(pkt->flags)) {
in.len = pkt->len - pnl;
+ badflags = clearflags & NGX_QUIC_PKT_LONG_RESERVED_BIT;
} else {
in.len = pkt->data + pkt->len - p;
+ badflags = clearflags & NGX_QUIC_PKT_SHORT_RESERVED_BIT;
}
ad.len = p - pkt->data;
pkt->payload.data, pkt->payload.len);
#endif
- return rc;
+ if (rc != NGX_OK) {
+ pkt->error = NGX_QUIC_ERR_CRYPTO_ERROR;
+ return rc;
+ }
+
+ if (badflags) {
+ /*
+ * An endpoint MUST treat receipt of a packet that has
+ * a non-zero value for these bits, after removing both
+ * packet and header protection, as a connection error
+ * of type PROTOCOL_VIOLATION.
+ */
+ ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
+ "quic reserved bit set in packet");
+ pkt->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
}
"quic long packet flags:%xi version:%xD",
pkt->flags, pkt->version);
+ if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) {
+ ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set");
+ return NGX_DECLINED;
+ }
+
if (pkt->version != NGX_QUIC_VERSION) {
ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
"quic unsupported version: 0x%xi", pkt->version);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
"quic short packet flags:%xi", pkt->flags);
+ if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) {
+ ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set");
+ return NGX_DECLINED;
+ }
+
if (ngx_memcmp(p, dcid->data, dcid->len) != 0) {
ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "unexpected quic dcid");
return NGX_ERROR;