From: Pauli Date: Tue, 1 Aug 2023 23:35:35 +0000 (+1000) Subject: quic: process stateless resets X-Git-Tag: openssl-3.2.0-alpha1~206 X-Git-Url: https://git.openssl.org/?p=openssl.git;a=commitdiff_plain;h=cdd916313a89def99493e00b49958ced894ca209 quic: process stateless resets Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/21649) --- diff --git a/include/internal/quic_demux.h b/include/internal/quic_demux.h index d439fa67be..81077425fe 100644 --- a/include/internal/quic_demux.h +++ b/include/internal/quic_demux.h @@ -178,6 +178,14 @@ typedef struct quic_demux_st QUIC_DEMUX; */ typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg); +/* + * Called when a datagram is received. + * Returns 1 if the datagram ends with a stateless reset token and + * 0 if not. + */ +typedef int (ossl_quic_stateless_reset_cb_fn)(const unsigned char *data, + size_t data_len, void *arg); + /* * Creates a new demuxer. The given BIO is used to receive datagrams from the * network using BIO_recvmmsg. short_conn_id_len is the length of destination @@ -270,6 +278,18 @@ void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, ossl_quic_demux_cb_fn *cb, void *cb_arg); +/* + * Sets a callback for stateless reset processing. + * + * If set, this callback is called for datagrams for which we cannot identify + * a CID. This function should return 1 if there is a stateless reset token + * present and 0 if not. If there is a token present, the connection should + * also be reset. + */ +void ossl_quic_demux_set_stateless_reset_handler( + QUIC_DEMUX *demux, + ossl_quic_stateless_reset_cb_fn *cb, void *cb_arg); + /* * Releases a URXE back to the demuxer. No reference must be made to the URXE or * its buffer after calling this function. The URXE must not be in any queue; @@ -315,6 +335,7 @@ void ossl_quic_demux_reinject_urxe(QUIC_DEMUX *demux, #define QUIC_DEMUX_PUMP_RES_OK 1 #define QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL (-1) #define QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL (-2) +#define QUIC_DEMUX_PUMP_RES_STATELESS_RESET (-3) int ossl_quic_demux_pump(QUIC_DEMUX *demux); diff --git a/include/internal/quic_types.h b/include/internal/quic_types.h index bc7c51c49a..f3509da2fb 100644 --- a/include/internal/quic_types.h +++ b/include/internal/quic_types.h @@ -100,6 +100,10 @@ static ossl_unused ossl_inline int ossl_quic_conn_id_eq(const QUIC_CONN_ID *a, # define QUIC_STATELESS_RESET_TOKEN_LEN 16 +typedef struct { + unsigned char token[QUIC_STATELESS_RESET_TOKEN_LEN]; +} QUIC_STATELESS_RESET_TOKEN; + /* * An encoded preferred_addr transport parameter cannot be shorter or longer * than these lengths in bytes. diff --git a/include/internal/quic_wire.h b/include/internal/quic_wire.h index f9f80fbc44..35fc298ea1 100644 --- a/include/internal/quic_wire.h +++ b/include/internal/quic_wire.h @@ -208,10 +208,10 @@ typedef struct ossl_quic_frame_stop_sending_st { /* QUIC Frame: NEW_CONNECTION_ID */ typedef struct ossl_quic_frame_new_conn_id_st { - uint64_t seq_num; - uint64_t retire_prior_to; - QUIC_CONN_ID conn_id; - unsigned char stateless_reset_token[QUIC_STATELESS_RESET_TOKEN_LEN]; + uint64_t seq_num; + uint64_t retire_prior_to; + QUIC_CONN_ID conn_id; + QUIC_STATELESS_RESET_TOKEN stateless_reset; } OSSL_QUIC_FRAME_NEW_CONN_ID; /* QUIC Frame: CONNECTION_CLOSE */ @@ -770,10 +770,10 @@ int ossl_quic_wire_decode_transport_param_cid(PACKET *pkt, * 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; + uint16_t ipv4_port, ipv6_port; + unsigned char ipv4[4], ipv6[16]; + QUIC_STATELESS_RESET_TOKEN stateless_reset; + QUIC_CONN_ID cid; } QUIC_PREFERRED_ADDR; int ossl_quic_wire_decode_transport_param_preferred_addr(PACKET *pkt, diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index a27e19781b..f174814a8b 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -86,11 +86,13 @@ static int ch_discard_el(QUIC_CHANNEL *ch, static void ch_on_idle_timeout(QUIC_CHANNEL *ch); static void ch_update_idle(QUIC_CHANNEL *ch); static void ch_update_ping_deadline(QUIC_CHANNEL *ch); +static void ch_stateless_reset(QUIC_CHANNEL *ch); static void ch_raise_net_error(QUIC_CHANNEL *ch); static void ch_on_terminating_timeout(QUIC_CHANNEL *ch); static void ch_start_terminating(QUIC_CHANNEL *ch, const QUIC_TERMINATE_CAUSE *tcause, int force_immediate); +static int ch_stateless_reset_token_handler(const unsigned char *data, size_t datalen, void *arg); static void ch_default_packet_handler(QUIC_URXE *e, void *arg); static int ch_server_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, const QUIC_CONN_ID *peer_scid, @@ -98,6 +100,8 @@ static int ch_server_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, static void ch_on_txp_ack_tx(const OSSL_QUIC_FRAME_ACK *ack, uint32_t pn_space, void *arg); +DEFINE_LHASH_OF_EX(QUIC_SRT_ELEM); + static int gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, QUIC_CONN_ID *cid) { if (len > QUIC_MAX_CONN_ID_LEN) @@ -113,6 +117,136 @@ static int gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, QUIC_CONN_ID *cid) return 1; } +static unsigned long chan_reset_token_hash(const QUIC_SRT_ELEM *a) +{ + unsigned long h; + + assert(sizeof(h) <= sizeof(a->token)); + memcpy(&h, &a->token, sizeof(h)); + return h; +} + +static int chan_reset_token_cmp(const QUIC_SRT_ELEM *a, const QUIC_SRT_ELEM *b) +{ + /* RFC 9000 s. 10.3.1: + * When comparing a datagram to stateless reset token values, + * endpoints MUST perform the comparison without leaking + * information about the value of the token. For example, + * performing this comparison in constant time protects the + * value of individual stateless reset tokens from information + * leakage through timing side channels. + * + * TODO(QUIC FUTURE): make this a memcmp when obfuscation is done and update + * comment above. + */ + return CRYPTO_memcmp(&a->token, &b->token, sizeof(a->token)); +} + +static int reset_token_obfuscate(QUIC_SRT_ELEM *out, const unsigned char *in) +{ + /* + * TODO(QUIC FUTURE): update this to AES encrypt the token in ECB mode with a + * random (per channel) key. + */ + memcpy(&out->token, in, sizeof(out->token)); + return 1; +} + +/* + * Add a stateless reset token to the channel + */ +static int chan_add_reset_token(QUIC_CHANNEL *ch, const unsigned char *new, + uint64_t seq_num) +{ + QUIC_SRT_ELEM *srte; + int err; + + /* Add to list by sequence number (always the tail) */ + if ((srte = OPENSSL_malloc(sizeof(*srte))) == NULL) + return 0; + + ossl_list_stateless_reset_tokens_init_elem(srte); + ossl_list_stateless_reset_tokens_insert_tail(&ch->srt_list_seq, srte); + reset_token_obfuscate(srte, new); + srte->seq_num = seq_num; + + lh_QUIC_SRT_ELEM_insert(ch->srt_hash_tok, srte); + err = lh_QUIC_SRT_ELEM_error(ch->srt_hash_tok); + if (err > 0) { + ossl_list_stateless_reset_tokens_remove(&ch->srt_list_seq, srte); + OPENSSL_free(srte); + return 0; + } + return 1; +} + +/* + * Remove a stateless reset token from the channel + * If the token isn't known, we just ignore the remove request which is safe. + */ +static void chan_remove_reset_token(QUIC_CHANNEL *ch, uint64_t seq_num) +{ + QUIC_SRT_ELEM *srte; + + /* + * Because the list is ordered and we only ever remove CIDs in order, + * this loop should never iterate, but safer to provide the option. + */ + for (srte = ossl_list_stateless_reset_tokens_head(&ch->srt_list_seq); + srte != NULL; + srte = ossl_list_stateless_reset_tokens_next(srte)) { + if (srte->seq_num > seq_num) + return; + if (srte->seq_num == seq_num) { + ossl_list_stateless_reset_tokens_remove(&ch->srt_list_seq, srte); + (void)lh_QUIC_SRT_ELEM_delete(ch->srt_hash_tok, srte); + OPENSSL_free(srte); + return; + } + } +} + +/* + * This is called by the demux whenever a new datagram arrives + * + * TODO(QUIC FUTURE): optimise this to only be called for unparsable packets + */ +static int ch_stateless_reset_token_handler(const unsigned char *data, + size_t datalen, void *arg) +{ + QUIC_SRT_ELEM srte; + QUIC_CHANNEL *ch = (QUIC_CHANNEL *)arg; + + /* + * Perform some fast and cheap checks for a packet not being a stateless + * reset token. RFC 9000 s. 10.3 specifies this layout for stateless + * reset packets: + * + * Stateless Reset { + * Fixed Bits (2) = 1, + * Unpredictable Bits (38..), + * Stateless Reset Token (128), + * } + * + * It also specifies: + * However, endpoints MUST treat any packet ending in a valid + * stateless reset token as a Stateless Reset, as other QUIC + * versions might allow the use of a long header. + * + * We can rapidly check for the minimum length and that the first pair + * of bits in the first byte are 01 or 11. + * + * The function returns 1 if it is a stateless reset packet, 0 if it isn't + * and -1 if an error was encountered. + */ + if (datalen < QUIC_STATELESS_RESET_TOKEN_LEN + 5 || (0100 & *data) != 0100) + return 0; + memset(&srte, 0, sizeof(srte)); + if (!reset_token_obfuscate(&srte, data + datalen - sizeof(srte.token))) + return -1; + return lh_QUIC_SRT_ELEM_retrieve(ch->srt_hash_tok, &srte) != NULL; +} + /* * QUIC Channel Initialization and Teardown * ======================================== @@ -134,6 +268,12 @@ static int ch_init(QUIC_CHANNEL *ch) uint32_t pn_space; size_t rx_short_cid_len = ch->is_server ? INIT_DCID_LEN : 0; + ossl_list_stateless_reset_tokens_init(&ch->srt_list_seq); + ch->srt_hash_tok = lh_QUIC_SRT_ELEM_new(&chan_reset_token_hash, + &chan_reset_token_cmp); + if (ch->srt_hash_tok == NULL) + goto err; + /* For clients, generate our initial DCID. */ if (!ch->is_server && !gen_rand_conn_id(ch->libctx, INIT_DCID_LEN, &ch->init_dcid)) @@ -248,6 +388,13 @@ static int ch_init(QUIC_CHANNEL *ch) get_time, ch)) == NULL) goto err; + /* + * Setup a handler to detect stateless reset tokens. + */ + ossl_quic_demux_set_stateless_reset_handler(ch->demux, + &ch_stateless_reset_token_handler, + ch); + /* * If we are a server, setup our handler for packets not corresponding to * any known DCID on our end. This is for handling clients establishing new @@ -338,6 +485,7 @@ err: static void ch_cleanup(QUIC_CHANNEL *ch) { + QUIC_SRT_ELEM *srte, *srte_next; uint32_t pn_space; if (ch->ackm != NULL) @@ -373,6 +521,17 @@ static void ch_cleanup(QUIC_CHANNEL *ch) OPENSSL_free(ch->local_transport_params); OPENSSL_free((char *)ch->terminate_cause.reason); OSSL_ERR_STATE_free(ch->err_state); + + /* Free the stateless reset tokens */ + for (srte = ossl_list_stateless_reset_tokens_head(&ch->srt_list_seq); + srte != NULL; + srte = srte_next) { + srte_next = ossl_list_stateless_reset_tokens_next(srte); + ossl_list_stateless_reset_tokens_remove(&ch->srt_list_seq, srte); + (void)lh_QUIC_SRT_ELEM_delete(ch->srt_hash_tok, srte); + OPENSSL_free(srte); + } + lh_QUIC_SRT_ELEM_free(ch->srt_hash_tok); } QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args) @@ -1047,6 +1206,8 @@ static int ch_on_handshake_alert(void *arg, unsigned char alert_code) x " sent when not performing a retry" #define TP_REASON_REQUIRED(x) \ x " was not sent but is required" +#define TP_REASON_INTERNAL_ERROR(x) \ + x " encountered internal error" static void txfc_bump_cwm_bidi(QUIC_STREAM *s, void *arg) { @@ -1392,10 +1553,11 @@ static int ch_on_transport_params(const unsigned char *params, break; case QUIC_TPARAM_STATELESS_RESET_TOKEN: - /* TODO(QUIC): Handle stateless reset tokens. */ /* - * We ignore these for now, but we must ensure a client doesn't - * send them. + * We must ensure a client doesn't send them because we don't have + * processing for them. + * + * TODO(QUIC SERVER): remove this restriction */ if (ch->is_server) { reason = TP_REASON_SERVER_ONLY("STATELESS_RESET_TOKEN"); @@ -1407,6 +1569,10 @@ static int ch_on_transport_params(const unsigned char *params, reason = TP_REASON_MALFORMED("STATELESS_RESET_TOKEN"); goto malformed; } + if (!chan_add_reset_token(ch, body, ch->cur_remote_seq_num)) { + reason = TP_REASON_INTERNAL_ERROR("STATELESS_RESET_TOKEN"); + goto malformed; + } break; @@ -1793,7 +1959,9 @@ static void ch_rx_pre(QUIC_CHANNEL *ch) * to the appropriate QRX instance. */ ret = ossl_quic_demux_pump(ch->demux); - if (ret == QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL) + if (ret == QUIC_DEMUX_PUMP_RES_STATELESS_RESET) + ch_stateless_reset(ch); + else if (ret == QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL) /* * We don't care about transient failure, but permanent failure means we * should tear down the connection as though a protocol violation @@ -2798,6 +2966,8 @@ static int ch_enqueue_retire_conn_id(QUIC_CHANNEL *ch, uint64_t seq_num) WPACKET wpkt; size_t l; + chan_remove_reset_token(ch, seq_num); + if ((buf_mem = BUF_MEM_new()) == NULL) return 0; @@ -2900,6 +3070,16 @@ void ossl_quic_channel_on_new_conn_id(QUIC_CHANNEL *ch, } if (new_remote_seq_num > ch->cur_remote_seq_num) { + /* Add new stateless reset token */ + if (!chan_add_reset_token(ch, f->stateless_reset.token, + new_remote_seq_num)) { + ossl_quic_channel_raise_protocol_error( + ch, QUIC_ERR_CONNECTION_ID_LIMIT_ERROR, + OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, + "unable to store stateless reset token"); + + return; + } ch->cur_remote_seq_num = new_remote_seq_num; ch->cur_remote_dcid = f->conn_id; ossl_quic_tx_packetiser_set_cur_dcid(ch->txp, &ch->cur_remote_dcid); @@ -2943,6 +3123,14 @@ static void ch_save_err_state(QUIC_CHANNEL *ch) OSSL_ERR_STATE_save(ch->err_state); } +static void ch_stateless_reset(QUIC_CHANNEL *ch) +{ + QUIC_TERMINATE_CAUSE tcause = {0}; + + tcause.error_code = QUIC_ERR_NO_ERROR; + ch_start_terminating(ch, &tcause, 1); +} + static void ch_raise_net_error(QUIC_CHANNEL *ch) { QUIC_TERMINATE_CAUSE tcause = {0}; diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index dd86f390be..ff861f18c7 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -5,6 +5,20 @@ # ifndef OPENSSL_NO_QUIC +# include +# include "internal/list.h" + + +typedef struct quic_srt_elem_st QUIC_SRT_ELEM; + +struct quic_srt_elem_st { + OSSL_LIST_MEMBER(stateless_reset_tokens, QUIC_SRT_ELEM); + QUIC_STATELESS_RESET_TOKEN token; + uint64_t seq_num; +}; + +DEFINE_LIST_OF(stateless_reset_tokens, QUIC_SRT_ELEM); + /* * QUIC Channel Structure * ====================== @@ -127,13 +141,30 @@ struct quic_channel_st { */ QUIC_CONN_ID retry_scid; - /* The DCID we currently use to talk to the peer and its sequence num. */ + /* + * The DCID we currently use to talk to the peer and its sequence num. + * + * TODO(QUIC FUTURE) consider removing the second two, both are contained in + * srt_list_seq (defined below). + * + * cur_remote_seq_num is same as the sequence number in the last element. + * cur_retire_prior_to corresponds to the sequence number in first element. + * + * Leaving them here avoids null checking etc + */ QUIC_CONN_ID cur_remote_dcid; uint64_t cur_remote_seq_num; uint64_t cur_retire_prior_to; + /* Server only: The DCID we currently expect the peer to use to talk to us. */ QUIC_CONN_ID cur_local_cid; + /* Hash of stateless reset tokens keyed on the token */ + LHASH_OF(QUIC_SRT_ELEM) *srt_hash_tok; + + /* List of the stateless reset tokens ordered by sequence number */ + OSSL_LIST(stateless_reset_tokens) srt_list_seq; + /* Transport parameter values we send to our peer. */ uint64_t tx_init_max_stream_data_bidi_local; uint64_t tx_init_max_stream_data_bidi_remote; diff --git a/ssl/quic/quic_demux.c b/ssl/quic/quic_demux.c index 160bf28168..bc2cde726b 100644 --- a/ssl/quic/quic_demux.c +++ b/ssl/quic/quic_demux.c @@ -80,6 +80,10 @@ struct quic_demux_st { ossl_quic_demux_cb_fn *default_cb; void *default_cb_arg; + /* The stateless reset token checker handler, if any. */ + ossl_quic_stateless_reset_cb_fn *reset_token_cb; + void *reset_token_cb_arg; + /* * List of URXEs which are not currently in use (i.e., not filled with * unconsumed data). These are moved to the pending list as they are filled. @@ -297,6 +301,14 @@ void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, demux->default_cb_arg = cb_arg; } +void ossl_quic_demux_set_stateless_reset_handler( + QUIC_DEMUX *demux, + ossl_quic_stateless_reset_cb_fn *cb, void *cb_arg) +{ + demux->reset_token_cb = cb; + demux->reset_token_cb_arg = cb_arg; +} + static QUIC_URXE *demux_alloc_urxe(size_t alloc_len) { QUIC_URXE *e; @@ -483,10 +495,14 @@ static QUIC_DEMUX_CONN *demux_identify_conn(QUIC_DEMUX *demux, QUIC_URXE *e) return demux_get_by_conn_id(demux, &dst_conn_id); } -/* Process a single pending URXE. */ +/* + * Process a single pending URXE. + * Returning 1 on success, 0 on failure and -1 on stateless reset. + */ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) { QUIC_DEMUX_CONN *conn; + int r; /* The next URXE we process should be at the head of the pending list. */ if (!ossl_assert(e == ossl_list_urxe_head(&demux->urx_pending))) @@ -494,6 +510,29 @@ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) assert(e->demux_state == URXE_DEMUX_STATE_PENDING); + /* + * Check if the packet ends with a stateless reset token and if it does + * skip it after dropping the connection. + * + * RFC 9000 s. 10.3.1 Detecting a Stateless Reset + * If the last 16 bytes of the datagram are identical in value to + * a stateless reset token, the endpoint MUST enter the draining + * period and not send any further packets on this connection. + * + * Returning a failure here causes the connection to enter the terminating + * state which achieves the desired outcome. + * + * TODO(QUIC FUTURE): only try to match unparsable packets + */ + if (demux->reset_token_cb != NULL) { + r = demux->reset_token_cb(ossl_quic_urxe_data(e), e->data_len, + demux->reset_token_cb_arg); + if (r > 0) /* Received a stateless reset */ + return -1; + if (r < 0) /* Error during stateless reset detection */ + return 0; + } + conn = demux_identify_conn(demux, e); if (conn == NULL) { /* @@ -528,10 +567,11 @@ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) static int demux_process_pending_urxl(QUIC_DEMUX *demux) { QUIC_URXE *e; + int ret; while ((e = ossl_list_urxe_head(&demux->urx_pending)) != NULL) - if (!demux_process_pending_urxe(demux, e)) - return 0; + if ((ret = demux_process_pending_urxe(demux, e)) <= 0) + return ret; return 1; } @@ -559,8 +599,9 @@ int ossl_quic_demux_pump(QUIC_DEMUX *demux) assert(ossl_list_urxe_head(&demux->urx_pending) != NULL); } - if (!demux_process_pending_urxl(demux)) - return QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL; + if ((ret = demux_process_pending_urxl(demux)) <= 0) + return ret == 0 ? QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL + : QUIC_DEMUX_PUMP_RES_STATELESS_RESET; return QUIC_DEMUX_PUMP_RES_OK; } @@ -608,7 +649,7 @@ int ossl_quic_demux_inject(QUIC_DEMUX *demux, ossl_list_urxe_insert_tail(&demux->urx_pending, urxe); urxe->demux_state = URXE_DEMUX_STATE_PENDING; - return demux_process_pending_urxl(demux); + return demux_process_pending_urxl(demux) > 0; } /* Called by our user to return a URXE to the free list. */ diff --git a/ssl/quic/quic_trace.c b/ssl/quic/quic_trace.c index d881140294..51ce7910cd 100644 --- a/ssl/quic/quic_trace.c +++ b/ssl/quic/quic_trace.c @@ -330,7 +330,8 @@ static int frame_new_conn_id(BIO *bio, PACKET *pkt) BIO_puts(bio, " Connection id: "); put_conn_id(bio, &frame_data.conn_id); BIO_puts(bio, "\n Stateless Reset Token: "); - put_data(bio, frame_data.stateless_reset_token, 16); + put_data(bio, frame_data.stateless_reset.token, + sizeof(frame_data.stateless_reset.token)); BIO_puts(bio, "\n"); return 1; diff --git a/ssl/quic/quic_wire.c b/ssl/quic/quic_wire.c index 748596d506..0a2130a2d1 100644 --- a/ssl/quic/quic_wire.c +++ b/ssl/quic/quic_wire.c @@ -328,8 +328,8 @@ int ossl_quic_wire_encode_frame_new_conn_id(WPACKET *pkt, || !WPACKET_quic_write_vlint(pkt, f->retire_prior_to) || !WPACKET_put_bytes_u8(pkt, f->conn_id.id_len) || !WPACKET_memcpy(pkt, f->conn_id.id, f->conn_id.id_len) - || !WPACKET_memcpy(pkt, f->stateless_reset_token, - sizeof(f->stateless_reset_token))) + || !WPACKET_memcpy(pkt, f->stateless_reset.token, + sizeof(f->stateless_reset.token))) return 0; return 1; @@ -804,8 +804,8 @@ int ossl_quic_wire_decode_frame_new_conn_id(PACKET *pkt, if (len < QUIC_MAX_CONN_ID_LEN) memset(f->conn_id.id + len, 0, QUIC_MAX_CONN_ID_LEN - len); - if (!PACKET_copy_bytes(pkt, f->stateless_reset_token, - sizeof(f->stateless_reset_token))) + if (!PACKET_copy_bytes(pkt, f->stateless_reset.token, + sizeof(f->stateless_reset.token))) return 0; return 1; @@ -983,8 +983,8 @@ int ossl_quic_wire_decode_transport_param_preferred_addr(PACKET *pkt, || !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))) + || !PACKET_copy_bytes(&pkt2, p->stateless_reset.token, + sizeof(p->stateless_reset.token))) return 0; p->ipv4_port = (uint16_t)ipv4_port; diff --git a/test/quic_txp_test.c b/test/quic_txp_test.c index fd9e56816e..e6acd5af80 100644 --- a/test/quic_txp_test.c +++ b/test/quic_txp_test.c @@ -403,7 +403,7 @@ static int schedule_cfq_new_conn_id(struct helper *h) ncid.seq_num = 2345; ncid.retire_prior_to = 1234; ncid.conn_id = cid_1; - memcpy(ncid.stateless_reset_token, reset_token_1, sizeof(reset_token_1)); + memcpy(ncid.stateless_reset.token, reset_token_1, sizeof(reset_token_1)); if (!TEST_ptr(buf_mem = BUF_MEM_new())) goto err; @@ -442,7 +442,7 @@ static int check_cfq_new_conn_id(struct helper *h) || !TEST_uint64_t_eq(h->frame.new_conn_id.retire_prior_to, 1234) || !TEST_mem_eq(&h->frame.new_conn_id.conn_id, sizeof(cid_1), &cid_1, sizeof(cid_1)) - || !TEST_mem_eq(&h->frame.new_conn_id.stateless_reset_token, + || !TEST_mem_eq(&h->frame.new_conn_id.stateless_reset.token, sizeof(reset_token_1), reset_token_1, sizeof(reset_token_1))) diff --git a/test/quic_wire_test.c b/test/quic_wire_test.c index f9c6688d99..5691be7dd5 100644 --- a/test/quic_wire_test.c +++ b/test/quic_wire_test.c @@ -746,8 +746,10 @@ static const OSSL_QUIC_FRAME_NEW_CONN_ID encode_case_16_f = { {0x33, 0x44, 0x55, 0x66} }, { - 0xde, 0x06, 0xcb, 0x76, 0x5d, 0xb1, 0xa7, 0x71, - 0x78, 0x09, 0xbb, 0xe8, 0x50, 0x19, 0x12, 0x9a + { + 0xde, 0x06, 0xcb, 0x76, 0x5d, 0xb1, 0xa7, 0x71, + 0x78, 0x09, 0xbb, 0xe8, 0x50, 0x19, 0x12, 0x9a + } } }; @@ -783,10 +785,10 @@ static int encode_case_16_dec(PACKET *pkt, ossl_ssize_t fail) encode_case_16_conn_id, sizeof(encode_case_16_conn_id))) return 0; - if (!TEST_mem_eq(f.stateless_reset_token, - sizeof(f.stateless_reset_token), - encode_case_16_f.stateless_reset_token, - sizeof(encode_case_16_f.stateless_reset_token))) + if (!TEST_mem_eq(f.stateless_reset.token, + sizeof(f.stateless_reset.token), + encode_case_16_f.stateless_reset.token, + sizeof(encode_case_16_f.stateless_reset.token))) return 0; return 1; @@ -811,8 +813,10 @@ static const OSSL_QUIC_FRAME_NEW_CONN_ID encode_case_16b_f = { {0x33, 0x44, 0x55, 0x66} }, { - 0xde, 0x06, 0xcb, 0x76, 0x5d, 0xb1, 0xa7, 0x71, - 0x78, 0x09, 0xbb, 0xe8, 0x50, 0x19, 0x12, 0x9a + { + 0xde, 0x06, 0xcb, 0x76, 0x5d, 0xb1, 0xa7, 0x71, + 0x78, 0x09, 0xbb, 0xe8, 0x50, 0x19, 0x12, 0x9a + } } };