Skip to content

Commit

Permalink
QUIC CONFORMANCE: Validate preferred_addr transport parameter
Browse files Browse the repository at this point in the history
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from #21135)
  • Loading branch information
hlandau authored and paulidale committed Jul 16, 2023
1 parent f37befa commit 54bd1f2
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 12 deletions.
7 changes: 7 additions & 0 deletions include/internal/quic_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ static ossl_unused ossl_inline int ossl_quic_conn_id_eq(const QUIC_CONN_ID *a,

# define QUIC_STATELESS_RESET_TOKEN_LEN 16

/*
* An encoded preferred_addr transport parameter cannot be longer than this
* number of bytes.
*/
# define QUIC_MIN_ENCODED_PREFERRED_ADDR_LEN 41
# define QUIC_MAX_ENCODED_PREFERRED_ADDR_LEN 61

# endif

#endif
13 changes: 13 additions & 0 deletions include/internal/quic_wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,19 @@ int ossl_quic_wire_decode_transport_param_cid(PACKET *pkt,
uint64_t *id,
QUIC_CONN_ID *cid);

/*
* Decodes a QUIC transport parameter TLV containing a preferred_address.
*/
typedef struct quic_preferred_addr_st {
uint16_t ipv4_port, ipv6_port;
unsigned char ipv4[4], ipv6[16];
unsigned char stateless_reset_token[QUIC_STATELESS_RESET_TOKEN_LEN];
QUIC_CONN_ID cid;
} QUIC_PREFERRED_ADDR;

int ossl_quic_wire_decode_transport_param_preferred_addr(PACKET *pkt,
QUIC_PREFERRED_ADDR *p);

# endif

#endif
44 changes: 32 additions & 12 deletions ssl/quic/quic_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -1344,18 +1344,38 @@ static int ch_on_transport_params(const unsigned char *params,
break;

case QUIC_TPARAM_PREFERRED_ADDR:
/* TODO(QUIC): Handle preferred address. */
if (ch->is_server) {
reason = TP_REASON_SERVER_ONLY("PREFERRED_ADDR");
goto malformed;
{
/* TODO(QUIC): Handle preferred address. */
QUIC_PREFERRED_ADDR pfa;

/*
* RFC 9000 s. 18.2: "A server that chooses a zero-length
* connection ID MUST NOT provide a preferred address.
* Similarly, a server MUST NOT include a zero-length connection
* ID in this transport parameter. A client MUST treat a
* violation of these requirements as a connection error of type
* TRANSPORT_PARAMETER_ERROR."
*/
if (ch->is_server) {
reason = TP_REASON_SERVER_ONLY("PREFERRED_ADDR");
goto malformed;
}

if (ch->cur_remote_dcid.id_len == 0) {
reason = "PREFERRED_ADDR provided for zero-length CID";
goto malformed;
}

if (!ossl_quic_wire_decode_transport_param_preferred_addr(&pkt, &pfa)) {
reason = TP_REASON_MALFORMED("PREFERRED_ADDR");
goto malformed;
}

if (pfa.cid.id_len == 0) {
reason = "zero-length CID in PREFERRED_ADDR";
goto malformed;
}
}

body = ossl_quic_wire_decode_transport_param_bytes(&pkt, &id, &len);
if (body == NULL) {
reason = TP_REASON_MALFORMED("PREFERRED_ADDR");
goto malformed;
}

break;

case QUIC_TPARAM_DISABLE_ACTIVE_MIGRATION:
Expand Down Expand Up @@ -1488,7 +1508,7 @@ static int ch_generate_transport_params(QUIC_CHANNEL *ch)
goto err;

if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_ACTIVE_CONN_ID_LIMIT,
2))
QUIC_MIN_ACTIVE_CONN_ID_LIMIT))
goto err;

if (!ossl_quic_wire_encode_transport_param_int(&wpkt, QUIC_TPARAM_INITIAL_MAX_DATA,
Expand Down
36 changes: 36 additions & 0 deletions ssl/quic/quic_wire.c
Original file line number Diff line number Diff line change
Expand Up @@ -937,3 +937,39 @@ int ossl_quic_wire_decode_transport_param_cid(PACKET *pkt,
memcpy(cid->id, body, cid->id_len);
return 1;
}

int ossl_quic_wire_decode_transport_param_preferred_addr(PACKET *pkt,
QUIC_PREFERRED_ADDR *p)
{
const unsigned char *body;
uint64_t id;
size_t len = 0;
PACKET pkt2;
unsigned int ipv4_port, ipv6_port, cidl;

body = ossl_quic_wire_decode_transport_param_bytes(pkt, &id, &len);
if (body == NULL
|| len < QUIC_MIN_ENCODED_PREFERRED_ADDR_LEN
|| len > QUIC_MAX_ENCODED_PREFERRED_ADDR_LEN
|| id != QUIC_TPARAM_PREFERRED_ADDR)
return 0;

if (!PACKET_buf_init(&pkt2, body, len))
return 0;

if (!PACKET_copy_bytes(&pkt2, p->ipv4, sizeof(p->ipv4))
|| !PACKET_get_net_2(&pkt2, &ipv4_port)
|| !PACKET_copy_bytes(&pkt2, p->ipv6, sizeof(p->ipv6))
|| !PACKET_get_net_2(&pkt2, &ipv6_port)
|| !PACKET_get_1(&pkt2, &cidl)
|| cidl > QUIC_MAX_CONN_ID_LEN
|| !PACKET_copy_bytes(&pkt2, p->cid.id, cidl)
|| !PACKET_copy_bytes(&pkt2, p->stateless_reset_token,
sizeof(p->stateless_reset_token)))
return 0;

p->ipv4_port = (uint16_t)ipv4_port;
p->ipv6_port = (uint16_t)ipv6_port;
p->cid.id_len = (unsigned char)cidl;
return 1;
}

0 comments on commit 54bd1f2

Please sign in to comment.