xref: /freebsd/crypto/openssl/ssl/quic/quic_rx_depack.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery  *
4*e7be843bSPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e7be843bSPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*e7be843bSPierre Pronchery  * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery  * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery  */
9*e7be843bSPierre Pronchery 
10*e7be843bSPierre Pronchery #include "internal/packet_quic.h"
11*e7be843bSPierre Pronchery #include "internal/nelem.h"
12*e7be843bSPierre Pronchery #include "internal/quic_wire.h"
13*e7be843bSPierre Pronchery #include "internal/quic_record_rx.h"
14*e7be843bSPierre Pronchery #include "internal/quic_ackm.h"
15*e7be843bSPierre Pronchery #include "internal/quic_rx_depack.h"
16*e7be843bSPierre Pronchery #include "internal/quic_error.h"
17*e7be843bSPierre Pronchery #include "internal/quic_fc.h"
18*e7be843bSPierre Pronchery #include "internal/quic_channel.h"
19*e7be843bSPierre Pronchery #include "internal/sockets.h"
20*e7be843bSPierre Pronchery 
21*e7be843bSPierre Pronchery #include "quic_local.h"
22*e7be843bSPierre Pronchery #include "quic_channel_local.h"
23*e7be843bSPierre Pronchery #include "../ssl_local.h"
24*e7be843bSPierre Pronchery 
25*e7be843bSPierre Pronchery /*
26*e7be843bSPierre Pronchery  * Helper functions to process different frame types.
27*e7be843bSPierre Pronchery  *
28*e7be843bSPierre Pronchery  * Typically, those that are ACK eliciting will take an OSSL_ACKM_RX_PKT
29*e7be843bSPierre Pronchery  * pointer argument, the few that aren't ACK eliciting will not.  This makes
30*e7be843bSPierre Pronchery  * them a verifiable pattern against tables where this is specified.
31*e7be843bSPierre Pronchery  */
32*e7be843bSPierre Pronchery static int depack_do_implicit_stream_create(QUIC_CHANNEL *ch,
33*e7be843bSPierre Pronchery                                             uint64_t stream_id,
34*e7be843bSPierre Pronchery                                             uint64_t frame_type,
35*e7be843bSPierre Pronchery                                             QUIC_STREAM **result);
36*e7be843bSPierre Pronchery 
depack_do_frame_padding(PACKET * pkt)37*e7be843bSPierre Pronchery static int depack_do_frame_padding(PACKET *pkt)
38*e7be843bSPierre Pronchery {
39*e7be843bSPierre Pronchery     /* We ignore this frame */
40*e7be843bSPierre Pronchery     ossl_quic_wire_decode_padding(pkt);
41*e7be843bSPierre Pronchery     return 1;
42*e7be843bSPierre Pronchery }
43*e7be843bSPierre Pronchery 
depack_do_frame_ping(PACKET * pkt,QUIC_CHANNEL * ch,uint32_t enc_level,OSSL_ACKM_RX_PKT * ackm_data)44*e7be843bSPierre Pronchery static int depack_do_frame_ping(PACKET *pkt, QUIC_CHANNEL *ch,
45*e7be843bSPierre Pronchery                                 uint32_t enc_level,
46*e7be843bSPierre Pronchery                                 OSSL_ACKM_RX_PKT *ackm_data)
47*e7be843bSPierre Pronchery {
48*e7be843bSPierre Pronchery     /* We ignore this frame, apart from eliciting an ACK */
49*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_ping(pkt)) {
50*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
51*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
52*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_PING,
53*e7be843bSPierre Pronchery                                                "decode error");
54*e7be843bSPierre Pronchery         return 0;
55*e7be843bSPierre Pronchery     }
56*e7be843bSPierre Pronchery 
57*e7be843bSPierre Pronchery     ossl_quic_tx_packetiser_schedule_ack_eliciting(ch->txp, enc_level);
58*e7be843bSPierre Pronchery     return 1;
59*e7be843bSPierre Pronchery }
60*e7be843bSPierre Pronchery 
depack_do_frame_ack(PACKET * pkt,QUIC_CHANNEL * ch,int packet_space,OSSL_TIME received,uint64_t frame_type,OSSL_QRX_PKT * qpacket)61*e7be843bSPierre Pronchery static int depack_do_frame_ack(PACKET *pkt, QUIC_CHANNEL *ch,
62*e7be843bSPierre Pronchery                                int packet_space, OSSL_TIME received,
63*e7be843bSPierre Pronchery                                uint64_t frame_type,
64*e7be843bSPierre Pronchery                                OSSL_QRX_PKT *qpacket)
65*e7be843bSPierre Pronchery {
66*e7be843bSPierre Pronchery     OSSL_QUIC_FRAME_ACK ack;
67*e7be843bSPierre Pronchery     OSSL_QUIC_ACK_RANGE *p;
68*e7be843bSPierre Pronchery     uint64_t total_ranges = 0;
69*e7be843bSPierre Pronchery     uint32_t ack_delay_exp = ch->rx_ack_delay_exp;
70*e7be843bSPierre Pronchery 
71*e7be843bSPierre Pronchery     if (!ossl_quic_wire_peek_frame_ack_num_ranges(pkt, &total_ranges)
72*e7be843bSPierre Pronchery         /* In case sizeof(uint64_t) > sizeof(size_t) */
73*e7be843bSPierre Pronchery         || total_ranges > SIZE_MAX / sizeof(OSSL_QUIC_ACK_RANGE))
74*e7be843bSPierre Pronchery         goto malformed;
75*e7be843bSPierre Pronchery 
76*e7be843bSPierre Pronchery     if (ch->num_ack_range_scratch < (size_t)total_ranges) {
77*e7be843bSPierre Pronchery         if ((p = OPENSSL_realloc(ch->ack_range_scratch,
78*e7be843bSPierre Pronchery                                  sizeof(OSSL_QUIC_ACK_RANGE)
79*e7be843bSPierre Pronchery                                  * (size_t)total_ranges)) == NULL)
80*e7be843bSPierre Pronchery             goto malformed;
81*e7be843bSPierre Pronchery 
82*e7be843bSPierre Pronchery         ch->ack_range_scratch       = p;
83*e7be843bSPierre Pronchery         ch->num_ack_range_scratch   = (size_t)total_ranges;
84*e7be843bSPierre Pronchery     }
85*e7be843bSPierre Pronchery 
86*e7be843bSPierre Pronchery     ack.ack_ranges = ch->ack_range_scratch;
87*e7be843bSPierre Pronchery     ack.num_ack_ranges = (size_t)total_ranges;
88*e7be843bSPierre Pronchery 
89*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_ack(pkt, ack_delay_exp, &ack, NULL))
90*e7be843bSPierre Pronchery         goto malformed;
91*e7be843bSPierre Pronchery 
92*e7be843bSPierre Pronchery     if (qpacket->hdr->type == QUIC_PKT_TYPE_1RTT
93*e7be843bSPierre Pronchery         && (qpacket->key_epoch < ossl_qrx_get_key_epoch(ch->qrx)
94*e7be843bSPierre Pronchery             || ch->rxku_expected)
95*e7be843bSPierre Pronchery         && ack.ack_ranges[0].end >= ch->txku_pn) {
96*e7be843bSPierre Pronchery         /*
97*e7be843bSPierre Pronchery          * RFC 9001 s. 6.2: An endpoint that receives an acknowledgment that is
98*e7be843bSPierre Pronchery          * carried in a packet protected with old keys where any acknowledged
99*e7be843bSPierre Pronchery          * packet was protected with newer keys MAY treat that as a connection
100*e7be843bSPierre Pronchery          * error of type KEY_UPDATE_ERROR.
101*e7be843bSPierre Pronchery          *
102*e7be843bSPierre Pronchery          * Two cases to handle here:
103*e7be843bSPierre Pronchery          *
104*e7be843bSPierre Pronchery          *   - We did spontaneous TXKU, the peer has responded in kind and we
105*e7be843bSPierre Pronchery          *     have detected RXKU; !ch->rxku_expected, but then it sent a packet
106*e7be843bSPierre Pronchery          *     with old keys acknowledging a packet in the new key epoch.
107*e7be843bSPierre Pronchery          *
108*e7be843bSPierre Pronchery          *     This also covers the case where we got RXKU and triggered
109*e7be843bSPierre Pronchery          *     solicited TXKU, and then for some reason the peer sent an ACK of
110*e7be843bSPierre Pronchery          *     a PN in our new TX key epoch with old keys.
111*e7be843bSPierre Pronchery          *
112*e7be843bSPierre Pronchery          *   - We did spontaneous TXKU; ch->txku_pn is the starting PN of our
113*e7be843bSPierre Pronchery          *     new TX key epoch; the peer has not initiated a solicited TXKU in
114*e7be843bSPierre Pronchery          *     response (so we have not detected RXKU); in this case the RX key
115*e7be843bSPierre Pronchery          *     epoch has not incremented and ch->rxku_expected is still 1.
116*e7be843bSPierre Pronchery          */
117*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
118*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_KEY_UPDATE_ERROR,
119*e7be843bSPierre Pronchery                                                frame_type,
120*e7be843bSPierre Pronchery                                                "acked packet which initiated a "
121*e7be843bSPierre Pronchery                                                "key update without a "
122*e7be843bSPierre Pronchery                                                "corresponding key update");
123*e7be843bSPierre Pronchery         return 0;
124*e7be843bSPierre Pronchery     }
125*e7be843bSPierre Pronchery 
126*e7be843bSPierre Pronchery     if (!ossl_ackm_on_rx_ack_frame(ch->ackm, &ack,
127*e7be843bSPierre Pronchery                                    packet_space, received))
128*e7be843bSPierre Pronchery         goto malformed;
129*e7be843bSPierre Pronchery 
130*e7be843bSPierre Pronchery     ++ch->diag_num_rx_ack;
131*e7be843bSPierre Pronchery     return 1;
132*e7be843bSPierre Pronchery 
133*e7be843bSPierre Pronchery malformed:
134*e7be843bSPierre Pronchery     ossl_quic_channel_raise_protocol_error(ch,
135*e7be843bSPierre Pronchery                                            OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
136*e7be843bSPierre Pronchery                                            frame_type,
137*e7be843bSPierre Pronchery                                            "decode error");
138*e7be843bSPierre Pronchery     return 0;
139*e7be843bSPierre Pronchery }
140*e7be843bSPierre Pronchery 
depack_do_frame_reset_stream(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)141*e7be843bSPierre Pronchery static int depack_do_frame_reset_stream(PACKET *pkt,
142*e7be843bSPierre Pronchery                                         QUIC_CHANNEL *ch,
143*e7be843bSPierre Pronchery                                         OSSL_ACKM_RX_PKT *ackm_data)
144*e7be843bSPierre Pronchery {
145*e7be843bSPierre Pronchery     OSSL_QUIC_FRAME_RESET_STREAM frame_data;
146*e7be843bSPierre Pronchery     QUIC_STREAM *stream = NULL;
147*e7be843bSPierre Pronchery     uint64_t fce;
148*e7be843bSPierre Pronchery 
149*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_reset_stream(pkt, &frame_data)) {
150*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
151*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
152*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_RESET_STREAM,
153*e7be843bSPierre Pronchery                                                "decode error");
154*e7be843bSPierre Pronchery         return 0;
155*e7be843bSPierre Pronchery     }
156*e7be843bSPierre Pronchery 
157*e7be843bSPierre Pronchery     if (!depack_do_implicit_stream_create(ch, frame_data.stream_id,
158*e7be843bSPierre Pronchery                                           OSSL_QUIC_FRAME_TYPE_RESET_STREAM,
159*e7be843bSPierre Pronchery                                           &stream))
160*e7be843bSPierre Pronchery         return 0; /* error already raised for us */
161*e7be843bSPierre Pronchery 
162*e7be843bSPierre Pronchery     if (stream == NULL)
163*e7be843bSPierre Pronchery         return 1; /* old deleted stream, not a protocol violation, ignore */
164*e7be843bSPierre Pronchery 
165*e7be843bSPierre Pronchery     if (!ossl_quic_stream_has_recv(stream)) {
166*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
167*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_STREAM_STATE_ERROR,
168*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_RESET_STREAM,
169*e7be843bSPierre Pronchery                                                "RESET_STREAM frame for "
170*e7be843bSPierre Pronchery                                                "TX only stream");
171*e7be843bSPierre Pronchery         return 0;
172*e7be843bSPierre Pronchery     }
173*e7be843bSPierre Pronchery 
174*e7be843bSPierre Pronchery     /*
175*e7be843bSPierre Pronchery      * The final size field of the RESET_STREAM frame must be used to determine
176*e7be843bSPierre Pronchery      * how much flow control credit the aborted stream was considered to have
177*e7be843bSPierre Pronchery      * consumed.
178*e7be843bSPierre Pronchery      *
179*e7be843bSPierre Pronchery      * We also need to ensure that if we already have a final size for the
180*e7be843bSPierre Pronchery      * stream, the RESET_STREAM frame's Final Size field matches this; we SHOULD
181*e7be843bSPierre Pronchery      * terminate the connection otherwise (RFC 9000 s. 4.5). The RXFC takes care
182*e7be843bSPierre Pronchery      * of this for us.
183*e7be843bSPierre Pronchery      */
184*e7be843bSPierre Pronchery     if (!ossl_quic_rxfc_on_rx_stream_frame(&stream->rxfc,
185*e7be843bSPierre Pronchery                                            frame_data.final_size, /*is_fin=*/1)) {
186*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
187*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_INTERNAL_ERROR,
188*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_RESET_STREAM,
189*e7be843bSPierre Pronchery                                                "internal error (flow control)");
190*e7be843bSPierre Pronchery         return 0;
191*e7be843bSPierre Pronchery     }
192*e7be843bSPierre Pronchery 
193*e7be843bSPierre Pronchery     /* Has a flow control error occurred? */
194*e7be843bSPierre Pronchery     fce = ossl_quic_rxfc_get_error(&stream->rxfc, 0);
195*e7be843bSPierre Pronchery     if (fce != OSSL_QUIC_ERR_NO_ERROR) {
196*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
197*e7be843bSPierre Pronchery                                                fce,
198*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_RESET_STREAM,
199*e7be843bSPierre Pronchery                                                "flow control violation");
200*e7be843bSPierre Pronchery         return 0;
201*e7be843bSPierre Pronchery     }
202*e7be843bSPierre Pronchery 
203*e7be843bSPierre Pronchery     /*
204*e7be843bSPierre Pronchery      * Depending on the receive part state this is handled either as a reset
205*e7be843bSPierre Pronchery      * transition or a no-op (e.g. if a reset has already been received before,
206*e7be843bSPierre Pronchery      * or the application already retired a FIN). Best effort - there are no
207*e7be843bSPierre Pronchery      * protocol error conditions we need to check for here.
208*e7be843bSPierre Pronchery      */
209*e7be843bSPierre Pronchery     ossl_quic_stream_map_notify_reset_recv_part(&ch->qsm, stream,
210*e7be843bSPierre Pronchery                                                 frame_data.app_error_code,
211*e7be843bSPierre Pronchery                                                 frame_data.final_size);
212*e7be843bSPierre Pronchery 
213*e7be843bSPierre Pronchery     ossl_quic_stream_map_update_state(&ch->qsm, stream);
214*e7be843bSPierre Pronchery     return 1;
215*e7be843bSPierre Pronchery }
216*e7be843bSPierre Pronchery 
depack_do_frame_stop_sending(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)217*e7be843bSPierre Pronchery static int depack_do_frame_stop_sending(PACKET *pkt,
218*e7be843bSPierre Pronchery                                         QUIC_CHANNEL *ch,
219*e7be843bSPierre Pronchery                                         OSSL_ACKM_RX_PKT *ackm_data)
220*e7be843bSPierre Pronchery {
221*e7be843bSPierre Pronchery     OSSL_QUIC_FRAME_STOP_SENDING frame_data;
222*e7be843bSPierre Pronchery     QUIC_STREAM *stream = NULL;
223*e7be843bSPierre Pronchery 
224*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_stop_sending(pkt, &frame_data)) {
225*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
226*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
227*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_STOP_SENDING,
228*e7be843bSPierre Pronchery                                                "decode error");
229*e7be843bSPierre Pronchery         return 0;
230*e7be843bSPierre Pronchery     }
231*e7be843bSPierre Pronchery 
232*e7be843bSPierre Pronchery     if (!depack_do_implicit_stream_create(ch, frame_data.stream_id,
233*e7be843bSPierre Pronchery                                           OSSL_QUIC_FRAME_TYPE_STOP_SENDING,
234*e7be843bSPierre Pronchery                                           &stream))
235*e7be843bSPierre Pronchery         return 0; /* error already raised for us */
236*e7be843bSPierre Pronchery 
237*e7be843bSPierre Pronchery     if (stream == NULL)
238*e7be843bSPierre Pronchery         return 1; /* old deleted stream, not a protocol violation, ignore */
239*e7be843bSPierre Pronchery 
240*e7be843bSPierre Pronchery     if (!ossl_quic_stream_has_send(stream)) {
241*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
242*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_STREAM_STATE_ERROR,
243*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_STOP_SENDING,
244*e7be843bSPierre Pronchery                                                "STOP_SENDING frame for "
245*e7be843bSPierre Pronchery                                                "RX only stream");
246*e7be843bSPierre Pronchery         return 0;
247*e7be843bSPierre Pronchery     }
248*e7be843bSPierre Pronchery 
249*e7be843bSPierre Pronchery     stream->peer_stop_sending       = 1;
250*e7be843bSPierre Pronchery     stream->peer_stop_sending_aec   = frame_data.app_error_code;
251*e7be843bSPierre Pronchery 
252*e7be843bSPierre Pronchery     /*
253*e7be843bSPierre Pronchery      * RFC 9000 s. 3.5: Receiving a STOP_SENDING frame means we must respond in
254*e7be843bSPierre Pronchery      * turn with a RESET_STREAM frame for the same part of the stream. The other
255*e7be843bSPierre Pronchery      * part is unaffected.
256*e7be843bSPierre Pronchery      */
257*e7be843bSPierre Pronchery     ossl_quic_stream_map_reset_stream_send_part(&ch->qsm, stream,
258*e7be843bSPierre Pronchery                                                 frame_data.app_error_code);
259*e7be843bSPierre Pronchery     return 1;
260*e7be843bSPierre Pronchery }
261*e7be843bSPierre Pronchery 
depack_do_frame_crypto(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_QRX_PKT * parent_pkt,OSSL_ACKM_RX_PKT * ackm_data,uint64_t * datalen)262*e7be843bSPierre Pronchery static int depack_do_frame_crypto(PACKET *pkt, QUIC_CHANNEL *ch,
263*e7be843bSPierre Pronchery                                   OSSL_QRX_PKT *parent_pkt,
264*e7be843bSPierre Pronchery                                   OSSL_ACKM_RX_PKT *ackm_data,
265*e7be843bSPierre Pronchery                                   uint64_t *datalen)
266*e7be843bSPierre Pronchery {
267*e7be843bSPierre Pronchery     OSSL_QUIC_FRAME_CRYPTO f;
268*e7be843bSPierre Pronchery     QUIC_RSTREAM *rstream;
269*e7be843bSPierre Pronchery     QUIC_RXFC *rxfc;
270*e7be843bSPierre Pronchery 
271*e7be843bSPierre Pronchery     *datalen = 0;
272*e7be843bSPierre Pronchery 
273*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_crypto(pkt, 0, &f)) {
274*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
275*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
276*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_CRYPTO,
277*e7be843bSPierre Pronchery                                                "decode error");
278*e7be843bSPierre Pronchery         return 0;
279*e7be843bSPierre Pronchery     }
280*e7be843bSPierre Pronchery 
281*e7be843bSPierre Pronchery     if (f.len == 0)
282*e7be843bSPierre Pronchery         return 1; /* nothing to do */
283*e7be843bSPierre Pronchery 
284*e7be843bSPierre Pronchery     rstream = ch->crypto_recv[ackm_data->pkt_space];
285*e7be843bSPierre Pronchery     if (!ossl_assert(rstream != NULL))
286*e7be843bSPierre Pronchery         /*
287*e7be843bSPierre Pronchery          * This should not happen; we should only have a NULL stream here if
288*e7be843bSPierre Pronchery          * the EL has been discarded, and if the EL has been discarded we
289*e7be843bSPierre Pronchery          * shouldn't be here.
290*e7be843bSPierre Pronchery          */
291*e7be843bSPierre Pronchery         return 0;
292*e7be843bSPierre Pronchery 
293*e7be843bSPierre Pronchery     rxfc = &ch->crypto_rxfc[ackm_data->pkt_space];
294*e7be843bSPierre Pronchery 
295*e7be843bSPierre Pronchery     if (!ossl_quic_rxfc_on_rx_stream_frame(rxfc, f.offset + f.len,
296*e7be843bSPierre Pronchery                                            /*is_fin=*/0)) {
297*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
298*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_INTERNAL_ERROR,
299*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_CRYPTO,
300*e7be843bSPierre Pronchery                                                "internal error (crypto RXFC)");
301*e7be843bSPierre Pronchery         return 0;
302*e7be843bSPierre Pronchery     }
303*e7be843bSPierre Pronchery 
304*e7be843bSPierre Pronchery     if (ossl_quic_rxfc_get_error(rxfc, 0) != OSSL_QUIC_ERR_NO_ERROR) {
305*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_CRYPTO_BUFFER_EXCEEDED,
306*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_CRYPTO,
307*e7be843bSPierre Pronchery                                                "exceeded maximum crypto buffer");
308*e7be843bSPierre Pronchery         return 0;
309*e7be843bSPierre Pronchery     }
310*e7be843bSPierre Pronchery 
311*e7be843bSPierre Pronchery     if (!ossl_quic_rstream_queue_data(rstream, parent_pkt,
312*e7be843bSPierre Pronchery                                       f.offset, f.data, f.len, 0)) {
313*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
314*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_INTERNAL_ERROR,
315*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_CRYPTO,
316*e7be843bSPierre Pronchery                                                "internal error (rstream queue)");
317*e7be843bSPierre Pronchery         return 0;
318*e7be843bSPierre Pronchery     }
319*e7be843bSPierre Pronchery 
320*e7be843bSPierre Pronchery     ch->did_crypto_frame = 1;
321*e7be843bSPierre Pronchery     *datalen = f.len;
322*e7be843bSPierre Pronchery 
323*e7be843bSPierre Pronchery     return 1;
324*e7be843bSPierre Pronchery }
325*e7be843bSPierre Pronchery 
depack_do_frame_new_token(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)326*e7be843bSPierre Pronchery static int depack_do_frame_new_token(PACKET *pkt, QUIC_CHANNEL *ch,
327*e7be843bSPierre Pronchery                                      OSSL_ACKM_RX_PKT *ackm_data)
328*e7be843bSPierre Pronchery {
329*e7be843bSPierre Pronchery     const uint8_t *token;
330*e7be843bSPierre Pronchery     size_t token_len;
331*e7be843bSPierre Pronchery 
332*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_new_token(pkt, &token, &token_len)) {
333*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
334*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
335*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_NEW_TOKEN,
336*e7be843bSPierre Pronchery                                                "decode error");
337*e7be843bSPierre Pronchery         return 0;
338*e7be843bSPierre Pronchery     }
339*e7be843bSPierre Pronchery 
340*e7be843bSPierre Pronchery     if (token_len == 0) {
341*e7be843bSPierre Pronchery         /*
342*e7be843bSPierre Pronchery          * RFC 9000 s. 19.7: "A client MUST treat receipt of a NEW_TOKEN frame
343*e7be843bSPierre Pronchery          * with an empty Token field as a connection error of type
344*e7be843bSPierre Pronchery          * FRAME_ENCODING_ERROR."
345*e7be843bSPierre Pronchery          */
346*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
347*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
348*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_NEW_TOKEN,
349*e7be843bSPierre Pronchery                                                "zero-length NEW_TOKEN");
350*e7be843bSPierre Pronchery         return 0;
351*e7be843bSPierre Pronchery     }
352*e7be843bSPierre Pronchery 
353*e7be843bSPierre Pronchery     /* store the new token in our token cache */
354*e7be843bSPierre Pronchery     if (!ossl_quic_set_peer_token(ossl_quic_port_get_channel_ctx(ch->port),
355*e7be843bSPierre Pronchery                                   &ch->cur_peer_addr, token, token_len))
356*e7be843bSPierre Pronchery         return 0;
357*e7be843bSPierre Pronchery 
358*e7be843bSPierre Pronchery     return 1;
359*e7be843bSPierre Pronchery }
360*e7be843bSPierre Pronchery 
361*e7be843bSPierre Pronchery /*
362*e7be843bSPierre Pronchery  * Returns 1 if no protocol violation has occurred. In this case *result will be
363*e7be843bSPierre Pronchery  * non-NULL unless this is an old deleted stream and we should ignore the frame
364*e7be843bSPierre Pronchery  * causing this function to be called. Returns 0 on protocol violation.
365*e7be843bSPierre Pronchery  */
depack_do_implicit_stream_create(QUIC_CHANNEL * ch,uint64_t stream_id,uint64_t frame_type,QUIC_STREAM ** result)366*e7be843bSPierre Pronchery static int depack_do_implicit_stream_create(QUIC_CHANNEL *ch,
367*e7be843bSPierre Pronchery                                             uint64_t stream_id,
368*e7be843bSPierre Pronchery                                             uint64_t frame_type,
369*e7be843bSPierre Pronchery                                             QUIC_STREAM **result)
370*e7be843bSPierre Pronchery {
371*e7be843bSPierre Pronchery     QUIC_STREAM *stream;
372*e7be843bSPierre Pronchery     uint64_t peer_role, stream_ordinal;
373*e7be843bSPierre Pronchery     uint64_t *p_next_ordinal_local, *p_next_ordinal_remote;
374*e7be843bSPierre Pronchery     QUIC_RXFC *max_streams_fc;
375*e7be843bSPierre Pronchery     int is_uni, is_remote_init;
376*e7be843bSPierre Pronchery 
377*e7be843bSPierre Pronchery     stream = ossl_quic_stream_map_get_by_id(&ch->qsm, stream_id);
378*e7be843bSPierre Pronchery     if (stream != NULL) {
379*e7be843bSPierre Pronchery         *result = stream;
380*e7be843bSPierre Pronchery         return 1;
381*e7be843bSPierre Pronchery     }
382*e7be843bSPierre Pronchery 
383*e7be843bSPierre Pronchery     /*
384*e7be843bSPierre Pronchery      * If we do not yet have a stream with the given ID, there are three
385*e7be843bSPierre Pronchery      * possibilities:
386*e7be843bSPierre Pronchery      *
387*e7be843bSPierre Pronchery      *   (a) The stream ID is for a remotely-created stream and the peer
388*e7be843bSPierre Pronchery      *       is creating a stream.
389*e7be843bSPierre Pronchery      *
390*e7be843bSPierre Pronchery      *   (b) The stream ID is for a locally-created stream which has
391*e7be843bSPierre Pronchery      *       previously been deleted.
392*e7be843bSPierre Pronchery      *
393*e7be843bSPierre Pronchery      *   (c) The stream ID is for a locally-created stream which does
394*e7be843bSPierre Pronchery      *       not exist yet. This is a protocol violation and we must
395*e7be843bSPierre Pronchery      *       terminate the connection in this case.
396*e7be843bSPierre Pronchery      *
397*e7be843bSPierre Pronchery      * We distinguish between (b) and (c) using the stream ID allocator
398*e7be843bSPierre Pronchery      * variable. Since stream ordinals are allocated monotonically, we
399*e7be843bSPierre Pronchery      * simply determine if the stream ordinal is in the future.
400*e7be843bSPierre Pronchery      */
401*e7be843bSPierre Pronchery     peer_role = ch->is_server
402*e7be843bSPierre Pronchery         ? QUIC_STREAM_INITIATOR_CLIENT
403*e7be843bSPierre Pronchery         : QUIC_STREAM_INITIATOR_SERVER;
404*e7be843bSPierre Pronchery 
405*e7be843bSPierre Pronchery     is_remote_init = ((stream_id & QUIC_STREAM_INITIATOR_MASK) == peer_role);
406*e7be843bSPierre Pronchery     is_uni = ((stream_id & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_UNI);
407*e7be843bSPierre Pronchery 
408*e7be843bSPierre Pronchery     stream_ordinal = stream_id >> 2;
409*e7be843bSPierre Pronchery 
410*e7be843bSPierre Pronchery     if (is_remote_init) {
411*e7be843bSPierre Pronchery         /*
412*e7be843bSPierre Pronchery          * Peer-created stream which does not yet exist. Create it. QUIC stream
413*e7be843bSPierre Pronchery          * ordinals within a given stream type MUST be used in sequence and
414*e7be843bSPierre Pronchery          * receiving a STREAM frame for ordinal n must implicitly create streams
415*e7be843bSPierre Pronchery          * with ordinals [0, n) within that stream type even if no explicit
416*e7be843bSPierre Pronchery          * STREAM frames are received for those ordinals.
417*e7be843bSPierre Pronchery          */
418*e7be843bSPierre Pronchery         p_next_ordinal_remote = is_uni
419*e7be843bSPierre Pronchery             ? &ch->next_remote_stream_ordinal_uni
420*e7be843bSPierre Pronchery             : &ch->next_remote_stream_ordinal_bidi;
421*e7be843bSPierre Pronchery 
422*e7be843bSPierre Pronchery         /* Check this isn't violating stream count flow control. */
423*e7be843bSPierre Pronchery         max_streams_fc = is_uni
424*e7be843bSPierre Pronchery             ? &ch->max_streams_uni_rxfc
425*e7be843bSPierre Pronchery             : &ch->max_streams_bidi_rxfc;
426*e7be843bSPierre Pronchery 
427*e7be843bSPierre Pronchery         if (!ossl_quic_rxfc_on_rx_stream_frame(max_streams_fc,
428*e7be843bSPierre Pronchery                                                stream_ordinal + 1,
429*e7be843bSPierre Pronchery                                                /*is_fin=*/0)) {
430*e7be843bSPierre Pronchery             ossl_quic_channel_raise_protocol_error(ch,
431*e7be843bSPierre Pronchery                                                    OSSL_QUIC_ERR_INTERNAL_ERROR,
432*e7be843bSPierre Pronchery                                                    frame_type,
433*e7be843bSPierre Pronchery                                                    "internal error (stream count RXFC)");
434*e7be843bSPierre Pronchery             return 0;
435*e7be843bSPierre Pronchery         }
436*e7be843bSPierre Pronchery 
437*e7be843bSPierre Pronchery         if (ossl_quic_rxfc_get_error(max_streams_fc, 0) != OSSL_QUIC_ERR_NO_ERROR) {
438*e7be843bSPierre Pronchery             ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_STREAM_LIMIT_ERROR,
439*e7be843bSPierre Pronchery                                                    frame_type,
440*e7be843bSPierre Pronchery                                                    "exceeded maximum allowed streams");
441*e7be843bSPierre Pronchery             return 0;
442*e7be843bSPierre Pronchery         }
443*e7be843bSPierre Pronchery 
444*e7be843bSPierre Pronchery         /*
445*e7be843bSPierre Pronchery          * Create the named stream and any streams coming before it yet to be
446*e7be843bSPierre Pronchery          * created.
447*e7be843bSPierre Pronchery          */
448*e7be843bSPierre Pronchery         while (*p_next_ordinal_remote <= stream_ordinal) {
449*e7be843bSPierre Pronchery             uint64_t cur_stream_id = (*p_next_ordinal_remote << 2) |
450*e7be843bSPierre Pronchery                 (stream_id
451*e7be843bSPierre Pronchery                  & (QUIC_STREAM_DIR_MASK | QUIC_STREAM_INITIATOR_MASK));
452*e7be843bSPierre Pronchery 
453*e7be843bSPierre Pronchery             stream = ossl_quic_channel_new_stream_remote(ch, cur_stream_id);
454*e7be843bSPierre Pronchery             if (stream == NULL) {
455*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
456*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_INTERNAL_ERROR,
457*e7be843bSPierre Pronchery                                                        frame_type,
458*e7be843bSPierre Pronchery                                                        "internal error (stream allocation)");
459*e7be843bSPierre Pronchery                 return 0;
460*e7be843bSPierre Pronchery             }
461*e7be843bSPierre Pronchery 
462*e7be843bSPierre Pronchery             ++*p_next_ordinal_remote;
463*e7be843bSPierre Pronchery         }
464*e7be843bSPierre Pronchery 
465*e7be843bSPierre Pronchery         *result = stream;
466*e7be843bSPierre Pronchery     } else {
467*e7be843bSPierre Pronchery         /* Locally-created stream which does not yet exist. */
468*e7be843bSPierre Pronchery         p_next_ordinal_local = is_uni
469*e7be843bSPierre Pronchery             ? &ch->next_local_stream_ordinal_uni
470*e7be843bSPierre Pronchery             : &ch->next_local_stream_ordinal_bidi;
471*e7be843bSPierre Pronchery 
472*e7be843bSPierre Pronchery         if (stream_ordinal >= *p_next_ordinal_local) {
473*e7be843bSPierre Pronchery             /*
474*e7be843bSPierre Pronchery              * We never created this stream yet, this is a protocol
475*e7be843bSPierre Pronchery              * violation.
476*e7be843bSPierre Pronchery              */
477*e7be843bSPierre Pronchery             ossl_quic_channel_raise_protocol_error(ch,
478*e7be843bSPierre Pronchery                                                    OSSL_QUIC_ERR_STREAM_STATE_ERROR,
479*e7be843bSPierre Pronchery                                                    frame_type,
480*e7be843bSPierre Pronchery                                                    "STREAM frame for nonexistent "
481*e7be843bSPierre Pronchery                                                    "stream");
482*e7be843bSPierre Pronchery             return 0;
483*e7be843bSPierre Pronchery         }
484*e7be843bSPierre Pronchery 
485*e7be843bSPierre Pronchery         /*
486*e7be843bSPierre Pronchery          * Otherwise this is for an old locally-initiated stream which we
487*e7be843bSPierre Pronchery          * have subsequently deleted. Ignore the data; it may simply be a
488*e7be843bSPierre Pronchery          * retransmission. We already take care of notifying the peer of the
489*e7be843bSPierre Pronchery          * termination of the stream during the stream deletion lifecycle.
490*e7be843bSPierre Pronchery          */
491*e7be843bSPierre Pronchery         *result = NULL;
492*e7be843bSPierre Pronchery     }
493*e7be843bSPierre Pronchery 
494*e7be843bSPierre Pronchery     return 1;
495*e7be843bSPierre Pronchery }
496*e7be843bSPierre Pronchery 
depack_do_frame_stream(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_QRX_PKT * parent_pkt,OSSL_ACKM_RX_PKT * ackm_data,uint64_t frame_type,uint64_t * datalen)497*e7be843bSPierre Pronchery static int depack_do_frame_stream(PACKET *pkt, QUIC_CHANNEL *ch,
498*e7be843bSPierre Pronchery                                   OSSL_QRX_PKT *parent_pkt,
499*e7be843bSPierre Pronchery                                   OSSL_ACKM_RX_PKT *ackm_data,
500*e7be843bSPierre Pronchery                                   uint64_t frame_type,
501*e7be843bSPierre Pronchery                                   uint64_t *datalen)
502*e7be843bSPierre Pronchery {
503*e7be843bSPierre Pronchery     OSSL_QUIC_FRAME_STREAM frame_data;
504*e7be843bSPierre Pronchery     QUIC_STREAM *stream;
505*e7be843bSPierre Pronchery     uint64_t fce;
506*e7be843bSPierre Pronchery     size_t rs_avail;
507*e7be843bSPierre Pronchery     int rs_fin = 0;
508*e7be843bSPierre Pronchery 
509*e7be843bSPierre Pronchery     *datalen = 0;
510*e7be843bSPierre Pronchery 
511*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_stream(pkt, 0, &frame_data)) {
512*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
513*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
514*e7be843bSPierre Pronchery                                                frame_type,
515*e7be843bSPierre Pronchery                                                "decode error");
516*e7be843bSPierre Pronchery         return 0;
517*e7be843bSPierre Pronchery     }
518*e7be843bSPierre Pronchery 
519*e7be843bSPierre Pronchery     if (!depack_do_implicit_stream_create(ch, frame_data.stream_id,
520*e7be843bSPierre Pronchery                                           frame_type, &stream))
521*e7be843bSPierre Pronchery         return 0; /* protocol error raised by above call */
522*e7be843bSPierre Pronchery 
523*e7be843bSPierre Pronchery     if (stream == NULL)
524*e7be843bSPierre Pronchery         /*
525*e7be843bSPierre Pronchery          * Data for old stream which is not a protocol violation but should be
526*e7be843bSPierre Pronchery          * ignored, so stop here.
527*e7be843bSPierre Pronchery          */
528*e7be843bSPierre Pronchery         return 1;
529*e7be843bSPierre Pronchery 
530*e7be843bSPierre Pronchery     if (!ossl_quic_stream_has_recv(stream)) {
531*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
532*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_STREAM_STATE_ERROR,
533*e7be843bSPierre Pronchery                                                frame_type,
534*e7be843bSPierre Pronchery                                                "STREAM frame for TX only "
535*e7be843bSPierre Pronchery                                                "stream");
536*e7be843bSPierre Pronchery         return 0;
537*e7be843bSPierre Pronchery     }
538*e7be843bSPierre Pronchery 
539*e7be843bSPierre Pronchery     /* Notify stream flow controller. */
540*e7be843bSPierre Pronchery     if (!ossl_quic_rxfc_on_rx_stream_frame(&stream->rxfc,
541*e7be843bSPierre Pronchery                                            frame_data.offset + frame_data.len,
542*e7be843bSPierre Pronchery                                            frame_data.is_fin)) {
543*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
544*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_INTERNAL_ERROR,
545*e7be843bSPierre Pronchery                                                frame_type,
546*e7be843bSPierre Pronchery                                                "internal error (flow control)");
547*e7be843bSPierre Pronchery         return 0;
548*e7be843bSPierre Pronchery     }
549*e7be843bSPierre Pronchery 
550*e7be843bSPierre Pronchery     /* Has a flow control error occurred? */
551*e7be843bSPierre Pronchery     fce = ossl_quic_rxfc_get_error(&stream->rxfc, 0);
552*e7be843bSPierre Pronchery     if (fce != OSSL_QUIC_ERR_NO_ERROR) {
553*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
554*e7be843bSPierre Pronchery                                                fce,
555*e7be843bSPierre Pronchery                                                frame_type,
556*e7be843bSPierre Pronchery                                                "flow control violation");
557*e7be843bSPierre Pronchery         return 0;
558*e7be843bSPierre Pronchery     }
559*e7be843bSPierre Pronchery 
560*e7be843bSPierre Pronchery     switch (stream->recv_state) {
561*e7be843bSPierre Pronchery     case QUIC_RSTREAM_STATE_RECV:
562*e7be843bSPierre Pronchery     case QUIC_RSTREAM_STATE_SIZE_KNOWN:
563*e7be843bSPierre Pronchery         /*
564*e7be843bSPierre Pronchery          * It only makes sense to process incoming STREAM frames in these
565*e7be843bSPierre Pronchery          * states.
566*e7be843bSPierre Pronchery          */
567*e7be843bSPierre Pronchery         break;
568*e7be843bSPierre Pronchery 
569*e7be843bSPierre Pronchery     case QUIC_RSTREAM_STATE_DATA_RECVD:
570*e7be843bSPierre Pronchery     case QUIC_RSTREAM_STATE_DATA_READ:
571*e7be843bSPierre Pronchery     case QUIC_RSTREAM_STATE_RESET_RECVD:
572*e7be843bSPierre Pronchery     case QUIC_RSTREAM_STATE_RESET_READ:
573*e7be843bSPierre Pronchery     default:
574*e7be843bSPierre Pronchery         /*
575*e7be843bSPierre Pronchery          * We have no use for STREAM frames once the receive part reaches any of
576*e7be843bSPierre Pronchery          * these states, so just ignore.
577*e7be843bSPierre Pronchery          */
578*e7be843bSPierre Pronchery         return 1;
579*e7be843bSPierre Pronchery     }
580*e7be843bSPierre Pronchery 
581*e7be843bSPierre Pronchery     /* If we are in RECV, auto-transition to SIZE_KNOWN on FIN. */
582*e7be843bSPierre Pronchery     if (frame_data.is_fin
583*e7be843bSPierre Pronchery         && !ossl_quic_stream_recv_get_final_size(stream, NULL)) {
584*e7be843bSPierre Pronchery 
585*e7be843bSPierre Pronchery         /* State was already checked above, so can't fail. */
586*e7be843bSPierre Pronchery         ossl_quic_stream_map_notify_size_known_recv_part(&ch->qsm, stream,
587*e7be843bSPierre Pronchery                                                          frame_data.offset
588*e7be843bSPierre Pronchery                                                          + frame_data.len);
589*e7be843bSPierre Pronchery     }
590*e7be843bSPierre Pronchery 
591*e7be843bSPierre Pronchery     /*
592*e7be843bSPierre Pronchery      * If we requested STOP_SENDING do not bother buffering the data. Note that
593*e7be843bSPierre Pronchery      * this must happen after RXFC checks above as even if we sent STOP_SENDING
594*e7be843bSPierre Pronchery      * we must still enforce correct flow control (RFC 9000 s. 3.5).
595*e7be843bSPierre Pronchery      */
596*e7be843bSPierre Pronchery     if (stream->stop_sending)
597*e7be843bSPierre Pronchery         return 1; /* not an error - packet reordering, etc. */
598*e7be843bSPierre Pronchery 
599*e7be843bSPierre Pronchery     /*
600*e7be843bSPierre Pronchery      * The receive stream buffer may or may not choose to consume the data
601*e7be843bSPierre Pronchery      * without copying by reffing the OSSL_QRX_PKT. In this case
602*e7be843bSPierre Pronchery      * ossl_qrx_pkt_release() will be eventually called when the data is no
603*e7be843bSPierre Pronchery      * longer needed.
604*e7be843bSPierre Pronchery      *
605*e7be843bSPierre Pronchery      * It is OK for the peer to send us a zero-length non-FIN STREAM frame,
606*e7be843bSPierre Pronchery      * which is a no-op, aside from the fact that it ensures the stream exists.
607*e7be843bSPierre Pronchery      * In this case we have nothing to report to the receive buffer.
608*e7be843bSPierre Pronchery      */
609*e7be843bSPierre Pronchery     if ((frame_data.len > 0 || frame_data.is_fin)
610*e7be843bSPierre Pronchery         && !ossl_quic_rstream_queue_data(stream->rstream, parent_pkt,
611*e7be843bSPierre Pronchery                                       frame_data.offset,
612*e7be843bSPierre Pronchery                                       frame_data.data,
613*e7be843bSPierre Pronchery                                       frame_data.len,
614*e7be843bSPierre Pronchery                                       frame_data.is_fin)) {
615*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
616*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_INTERNAL_ERROR,
617*e7be843bSPierre Pronchery                                                frame_type,
618*e7be843bSPierre Pronchery                                                "internal error (rstream queue)");
619*e7be843bSPierre Pronchery         return 0;
620*e7be843bSPierre Pronchery     }
621*e7be843bSPierre Pronchery 
622*e7be843bSPierre Pronchery     /*
623*e7be843bSPierre Pronchery      * rs_fin will be 1 only if we can read all data up to and including the FIN
624*e7be843bSPierre Pronchery      * without any gaps before it; this implies we have received all data. Avoid
625*e7be843bSPierre Pronchery      * calling ossl_quic_rstream_available() where it is not necessary as it is
626*e7be843bSPierre Pronchery      * more expensive.
627*e7be843bSPierre Pronchery      */
628*e7be843bSPierre Pronchery     if (stream->recv_state == QUIC_RSTREAM_STATE_SIZE_KNOWN
629*e7be843bSPierre Pronchery         && !ossl_quic_rstream_available(stream->rstream, &rs_avail, &rs_fin)) {
630*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
631*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_INTERNAL_ERROR,
632*e7be843bSPierre Pronchery                                                frame_type,
633*e7be843bSPierre Pronchery                                                "internal error (rstream available)");
634*e7be843bSPierre Pronchery         return 0;
635*e7be843bSPierre Pronchery     }
636*e7be843bSPierre Pronchery 
637*e7be843bSPierre Pronchery     if (rs_fin)
638*e7be843bSPierre Pronchery         ossl_quic_stream_map_notify_totally_received(&ch->qsm, stream);
639*e7be843bSPierre Pronchery 
640*e7be843bSPierre Pronchery     *datalen = frame_data.len;
641*e7be843bSPierre Pronchery 
642*e7be843bSPierre Pronchery     return 1;
643*e7be843bSPierre Pronchery }
644*e7be843bSPierre Pronchery 
update_streams(QUIC_STREAM * s,void * arg)645*e7be843bSPierre Pronchery static void update_streams(QUIC_STREAM *s, void *arg)
646*e7be843bSPierre Pronchery {
647*e7be843bSPierre Pronchery     QUIC_CHANNEL *ch = arg;
648*e7be843bSPierre Pronchery 
649*e7be843bSPierre Pronchery     ossl_quic_stream_map_update_state(&ch->qsm, s);
650*e7be843bSPierre Pronchery }
651*e7be843bSPierre Pronchery 
update_streams_bidi(QUIC_STREAM * s,void * arg)652*e7be843bSPierre Pronchery static void update_streams_bidi(QUIC_STREAM *s, void *arg)
653*e7be843bSPierre Pronchery {
654*e7be843bSPierre Pronchery     QUIC_CHANNEL *ch = arg;
655*e7be843bSPierre Pronchery 
656*e7be843bSPierre Pronchery     if (!ossl_quic_stream_is_bidi(s))
657*e7be843bSPierre Pronchery         return;
658*e7be843bSPierre Pronchery 
659*e7be843bSPierre Pronchery     ossl_quic_stream_map_update_state(&ch->qsm, s);
660*e7be843bSPierre Pronchery }
661*e7be843bSPierre Pronchery 
update_streams_uni(QUIC_STREAM * s,void * arg)662*e7be843bSPierre Pronchery static void update_streams_uni(QUIC_STREAM *s, void *arg)
663*e7be843bSPierre Pronchery {
664*e7be843bSPierre Pronchery     QUIC_CHANNEL *ch = arg;
665*e7be843bSPierre Pronchery 
666*e7be843bSPierre Pronchery     if (ossl_quic_stream_is_bidi(s))
667*e7be843bSPierre Pronchery         return;
668*e7be843bSPierre Pronchery 
669*e7be843bSPierre Pronchery     ossl_quic_stream_map_update_state(&ch->qsm, s);
670*e7be843bSPierre Pronchery }
671*e7be843bSPierre Pronchery 
depack_do_frame_max_data(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)672*e7be843bSPierre Pronchery static int depack_do_frame_max_data(PACKET *pkt, QUIC_CHANNEL *ch,
673*e7be843bSPierre Pronchery                                     OSSL_ACKM_RX_PKT *ackm_data)
674*e7be843bSPierre Pronchery {
675*e7be843bSPierre Pronchery     uint64_t max_data = 0;
676*e7be843bSPierre Pronchery 
677*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_max_data(pkt, &max_data)) {
678*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
679*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
680*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_MAX_DATA,
681*e7be843bSPierre Pronchery                                                "decode error");
682*e7be843bSPierre Pronchery         return 0;
683*e7be843bSPierre Pronchery     }
684*e7be843bSPierre Pronchery 
685*e7be843bSPierre Pronchery     ossl_quic_txfc_bump_cwm(&ch->conn_txfc, max_data);
686*e7be843bSPierre Pronchery     ossl_quic_stream_map_visit(&ch->qsm, update_streams, ch);
687*e7be843bSPierre Pronchery     return 1;
688*e7be843bSPierre Pronchery }
689*e7be843bSPierre Pronchery 
depack_do_frame_max_stream_data(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)690*e7be843bSPierre Pronchery static int depack_do_frame_max_stream_data(PACKET *pkt,
691*e7be843bSPierre Pronchery                                            QUIC_CHANNEL *ch,
692*e7be843bSPierre Pronchery                                            OSSL_ACKM_RX_PKT *ackm_data)
693*e7be843bSPierre Pronchery {
694*e7be843bSPierre Pronchery     uint64_t stream_id = 0;
695*e7be843bSPierre Pronchery     uint64_t max_stream_data = 0;
696*e7be843bSPierre Pronchery     QUIC_STREAM *stream;
697*e7be843bSPierre Pronchery 
698*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_max_stream_data(pkt, &stream_id,
699*e7be843bSPierre Pronchery                                                      &max_stream_data)) {
700*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
701*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
702*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA,
703*e7be843bSPierre Pronchery                                                "decode error");
704*e7be843bSPierre Pronchery         return 0;
705*e7be843bSPierre Pronchery     }
706*e7be843bSPierre Pronchery 
707*e7be843bSPierre Pronchery     if (!depack_do_implicit_stream_create(ch, stream_id,
708*e7be843bSPierre Pronchery                                           OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA,
709*e7be843bSPierre Pronchery                                           &stream))
710*e7be843bSPierre Pronchery         return 0; /* error already raised for us */
711*e7be843bSPierre Pronchery 
712*e7be843bSPierre Pronchery     if (stream == NULL)
713*e7be843bSPierre Pronchery         return 1; /* old deleted stream, not a protocol violation, ignore */
714*e7be843bSPierre Pronchery 
715*e7be843bSPierre Pronchery     if (!ossl_quic_stream_has_send(stream)) {
716*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
717*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_STREAM_STATE_ERROR,
718*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA,
719*e7be843bSPierre Pronchery                                                "MAX_STREAM_DATA for TX only "
720*e7be843bSPierre Pronchery                                                "stream");
721*e7be843bSPierre Pronchery         return 0;
722*e7be843bSPierre Pronchery     }
723*e7be843bSPierre Pronchery 
724*e7be843bSPierre Pronchery     ossl_quic_txfc_bump_cwm(&stream->txfc, max_stream_data);
725*e7be843bSPierre Pronchery     ossl_quic_stream_map_update_state(&ch->qsm, stream);
726*e7be843bSPierre Pronchery     return 1;
727*e7be843bSPierre Pronchery }
728*e7be843bSPierre Pronchery 
depack_do_frame_max_streams(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data,uint64_t frame_type)729*e7be843bSPierre Pronchery static int depack_do_frame_max_streams(PACKET *pkt,
730*e7be843bSPierre Pronchery                                        QUIC_CHANNEL *ch,
731*e7be843bSPierre Pronchery                                        OSSL_ACKM_RX_PKT *ackm_data,
732*e7be843bSPierre Pronchery                                        uint64_t frame_type)
733*e7be843bSPierre Pronchery {
734*e7be843bSPierre Pronchery     uint64_t max_streams = 0;
735*e7be843bSPierre Pronchery 
736*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_max_streams(pkt, &max_streams)) {
737*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
738*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
739*e7be843bSPierre Pronchery                                                frame_type,
740*e7be843bSPierre Pronchery                                                "decode error");
741*e7be843bSPierre Pronchery         return 0;
742*e7be843bSPierre Pronchery     }
743*e7be843bSPierre Pronchery 
744*e7be843bSPierre Pronchery     if (max_streams > (((uint64_t)1) << 60)) {
745*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
746*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
747*e7be843bSPierre Pronchery                                                frame_type,
748*e7be843bSPierre Pronchery                                                "invalid max streams value");
749*e7be843bSPierre Pronchery         return 0;
750*e7be843bSPierre Pronchery     }
751*e7be843bSPierre Pronchery 
752*e7be843bSPierre Pronchery     switch (frame_type) {
753*e7be843bSPierre Pronchery     case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI:
754*e7be843bSPierre Pronchery         if (max_streams > ch->max_local_streams_bidi)
755*e7be843bSPierre Pronchery             ch->max_local_streams_bidi = max_streams;
756*e7be843bSPierre Pronchery 
757*e7be843bSPierre Pronchery         /* Some streams may now be able to send. */
758*e7be843bSPierre Pronchery         ossl_quic_stream_map_visit(&ch->qsm, update_streams_bidi, ch);
759*e7be843bSPierre Pronchery         break;
760*e7be843bSPierre Pronchery     case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI:
761*e7be843bSPierre Pronchery         if (max_streams > ch->max_local_streams_uni)
762*e7be843bSPierre Pronchery             ch->max_local_streams_uni = max_streams;
763*e7be843bSPierre Pronchery 
764*e7be843bSPierre Pronchery         /* Some streams may now be able to send. */
765*e7be843bSPierre Pronchery         ossl_quic_stream_map_visit(&ch->qsm, update_streams_uni, ch);
766*e7be843bSPierre Pronchery         break;
767*e7be843bSPierre Pronchery     default:
768*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
769*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
770*e7be843bSPierre Pronchery                                                frame_type,
771*e7be843bSPierre Pronchery                                                "decode error");
772*e7be843bSPierre Pronchery         return 0;
773*e7be843bSPierre Pronchery     }
774*e7be843bSPierre Pronchery 
775*e7be843bSPierre Pronchery     return 1;
776*e7be843bSPierre Pronchery }
777*e7be843bSPierre Pronchery 
depack_do_frame_data_blocked(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)778*e7be843bSPierre Pronchery static int depack_do_frame_data_blocked(PACKET *pkt,
779*e7be843bSPierre Pronchery                                         QUIC_CHANNEL *ch,
780*e7be843bSPierre Pronchery                                         OSSL_ACKM_RX_PKT *ackm_data)
781*e7be843bSPierre Pronchery {
782*e7be843bSPierre Pronchery     uint64_t max_data = 0;
783*e7be843bSPierre Pronchery 
784*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_data_blocked(pkt, &max_data)) {
785*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
786*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
787*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_DATA_BLOCKED,
788*e7be843bSPierre Pronchery                                                "decode error");
789*e7be843bSPierre Pronchery         return 0;
790*e7be843bSPierre Pronchery     }
791*e7be843bSPierre Pronchery 
792*e7be843bSPierre Pronchery     /* No-op - informative/debugging frame. */
793*e7be843bSPierre Pronchery     return 1;
794*e7be843bSPierre Pronchery }
795*e7be843bSPierre Pronchery 
depack_do_frame_stream_data_blocked(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)796*e7be843bSPierre Pronchery static int depack_do_frame_stream_data_blocked(PACKET *pkt,
797*e7be843bSPierre Pronchery                                                QUIC_CHANNEL *ch,
798*e7be843bSPierre Pronchery                                                OSSL_ACKM_RX_PKT *ackm_data)
799*e7be843bSPierre Pronchery {
800*e7be843bSPierre Pronchery     uint64_t stream_id = 0;
801*e7be843bSPierre Pronchery     uint64_t max_data = 0;
802*e7be843bSPierre Pronchery     QUIC_STREAM *stream;
803*e7be843bSPierre Pronchery 
804*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_stream_data_blocked(pkt, &stream_id,
805*e7be843bSPierre Pronchery                                                          &max_data)) {
806*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
807*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
808*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED,
809*e7be843bSPierre Pronchery                                                "decode error");
810*e7be843bSPierre Pronchery         return 0;
811*e7be843bSPierre Pronchery     }
812*e7be843bSPierre Pronchery 
813*e7be843bSPierre Pronchery     /*
814*e7be843bSPierre Pronchery      * This is an informative/debugging frame, so we don't have to do anything,
815*e7be843bSPierre Pronchery      * but it does trigger stream creation.
816*e7be843bSPierre Pronchery      */
817*e7be843bSPierre Pronchery     if (!depack_do_implicit_stream_create(ch, stream_id,
818*e7be843bSPierre Pronchery                                           OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED,
819*e7be843bSPierre Pronchery                                           &stream))
820*e7be843bSPierre Pronchery         return 0; /* error already raised for us */
821*e7be843bSPierre Pronchery 
822*e7be843bSPierre Pronchery     if (stream == NULL)
823*e7be843bSPierre Pronchery         return 1; /* old deleted stream, not a protocol violation, ignore */
824*e7be843bSPierre Pronchery 
825*e7be843bSPierre Pronchery     if (!ossl_quic_stream_has_recv(stream)) {
826*e7be843bSPierre Pronchery         /*
827*e7be843bSPierre Pronchery          * RFC 9000 s. 19.14: "An endpoint that receives a STREAM_DATA_BLOCKED
828*e7be843bSPierre Pronchery          * frame for a send-only stream MUST terminate the connection with error
829*e7be843bSPierre Pronchery          * STREAM_STATE_ERROR."
830*e7be843bSPierre Pronchery          */
831*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
832*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_STREAM_STATE_ERROR,
833*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED,
834*e7be843bSPierre Pronchery                                                "STREAM_DATA_BLOCKED frame for "
835*e7be843bSPierre Pronchery                                                "TX only stream");
836*e7be843bSPierre Pronchery         return 0;
837*e7be843bSPierre Pronchery     }
838*e7be843bSPierre Pronchery 
839*e7be843bSPierre Pronchery     /* No-op - informative/debugging frame. */
840*e7be843bSPierre Pronchery     return 1;
841*e7be843bSPierre Pronchery }
842*e7be843bSPierre Pronchery 
depack_do_frame_streams_blocked(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data,uint64_t frame_type)843*e7be843bSPierre Pronchery static int depack_do_frame_streams_blocked(PACKET *pkt,
844*e7be843bSPierre Pronchery                                            QUIC_CHANNEL *ch,
845*e7be843bSPierre Pronchery                                            OSSL_ACKM_RX_PKT *ackm_data,
846*e7be843bSPierre Pronchery                                            uint64_t frame_type)
847*e7be843bSPierre Pronchery {
848*e7be843bSPierre Pronchery     uint64_t max_data = 0;
849*e7be843bSPierre Pronchery 
850*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_streams_blocked(pkt, &max_data)) {
851*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
852*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
853*e7be843bSPierre Pronchery                                                frame_type,
854*e7be843bSPierre Pronchery                                                "decode error");
855*e7be843bSPierre Pronchery         return 0;
856*e7be843bSPierre Pronchery     }
857*e7be843bSPierre Pronchery 
858*e7be843bSPierre Pronchery     if (max_data > (((uint64_t)1) << 60)) {
859*e7be843bSPierre Pronchery         /*
860*e7be843bSPierre Pronchery          * RFC 9000 s. 19.14: "This value cannot exceed 2**60, as it is not
861*e7be843bSPierre Pronchery          * possible to encode stream IDs larger than 2**62 - 1. Receipt of a
862*e7be843bSPierre Pronchery          * frame that encodes a larger stream ID MUST be treated as a connection
863*e7be843bSPierre Pronchery          * error of type STREAM_LIMIT_ERROR or FRAME_ENCODING_ERROR."
864*e7be843bSPierre Pronchery          */
865*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
866*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_STREAM_LIMIT_ERROR,
867*e7be843bSPierre Pronchery                                                frame_type,
868*e7be843bSPierre Pronchery                                                "invalid stream count limit");
869*e7be843bSPierre Pronchery         return 0;
870*e7be843bSPierre Pronchery     }
871*e7be843bSPierre Pronchery 
872*e7be843bSPierre Pronchery     /* No-op - informative/debugging frame. */
873*e7be843bSPierre Pronchery     return 1;
874*e7be843bSPierre Pronchery }
875*e7be843bSPierre Pronchery 
depack_do_frame_new_conn_id(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)876*e7be843bSPierre Pronchery static int depack_do_frame_new_conn_id(PACKET *pkt,
877*e7be843bSPierre Pronchery                                        QUIC_CHANNEL *ch,
878*e7be843bSPierre Pronchery                                        OSSL_ACKM_RX_PKT *ackm_data)
879*e7be843bSPierre Pronchery {
880*e7be843bSPierre Pronchery     OSSL_QUIC_FRAME_NEW_CONN_ID frame_data;
881*e7be843bSPierre Pronchery 
882*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_new_conn_id(pkt, &frame_data)) {
883*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
884*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
885*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,
886*e7be843bSPierre Pronchery                                                "decode error");
887*e7be843bSPierre Pronchery         return 0;
888*e7be843bSPierre Pronchery     }
889*e7be843bSPierre Pronchery 
890*e7be843bSPierre Pronchery     ossl_quic_channel_on_new_conn_id(ch, &frame_data);
891*e7be843bSPierre Pronchery 
892*e7be843bSPierre Pronchery     return 1;
893*e7be843bSPierre Pronchery }
894*e7be843bSPierre Pronchery 
depack_do_frame_retire_conn_id(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)895*e7be843bSPierre Pronchery static int depack_do_frame_retire_conn_id(PACKET *pkt,
896*e7be843bSPierre Pronchery                                           QUIC_CHANNEL *ch,
897*e7be843bSPierre Pronchery                                           OSSL_ACKM_RX_PKT *ackm_data)
898*e7be843bSPierre Pronchery {
899*e7be843bSPierre Pronchery     uint64_t seq_num;
900*e7be843bSPierre Pronchery 
901*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_retire_conn_id(pkt, &seq_num)) {
902*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
903*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
904*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID,
905*e7be843bSPierre Pronchery                                                "decode error");
906*e7be843bSPierre Pronchery         return 0;
907*e7be843bSPierre Pronchery     }
908*e7be843bSPierre Pronchery 
909*e7be843bSPierre Pronchery     /*
910*e7be843bSPierre Pronchery      * RFC 9000 s. 19.16: "An endpoint cannot send this frame if it was provided
911*e7be843bSPierre Pronchery      * with a zero-length connection ID by its peer. An endpoint that provides a
912*e7be843bSPierre Pronchery      * zero-length connection ID MUST treat receipt of a RETIRE_CONNECTION_ID
913*e7be843bSPierre Pronchery      * frame as a connection error of type PROTOCOL_VIOLATION."
914*e7be843bSPierre Pronchery      *
915*e7be843bSPierre Pronchery      * Since we always use a zero-length SCID as a client, there is no case
916*e7be843bSPierre Pronchery      * where it is valid for a server to send this. Our server support is
917*e7be843bSPierre Pronchery      * currently non-conformant and for internal testing use; simply handle it
918*e7be843bSPierre Pronchery      * as a no-op in this case.
919*e7be843bSPierre Pronchery      *
920*e7be843bSPierre Pronchery      * TODO(QUIC FUTURE): Revise and implement correctly for server support.
921*e7be843bSPierre Pronchery      */
922*e7be843bSPierre Pronchery     if (!ch->is_server) {
923*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
924*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
925*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID,
926*e7be843bSPierre Pronchery                                                "conn has zero-length CID");
927*e7be843bSPierre Pronchery         return 0;
928*e7be843bSPierre Pronchery     }
929*e7be843bSPierre Pronchery 
930*e7be843bSPierre Pronchery     return 1;
931*e7be843bSPierre Pronchery }
932*e7be843bSPierre Pronchery 
free_path_response(unsigned char * buf,size_t buf_len,void * arg)933*e7be843bSPierre Pronchery static void free_path_response(unsigned char *buf, size_t buf_len, void *arg)
934*e7be843bSPierre Pronchery {
935*e7be843bSPierre Pronchery     OPENSSL_free(buf);
936*e7be843bSPierre Pronchery }
937*e7be843bSPierre Pronchery 
depack_do_frame_path_challenge(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)938*e7be843bSPierre Pronchery static int depack_do_frame_path_challenge(PACKET *pkt,
939*e7be843bSPierre Pronchery                                           QUIC_CHANNEL *ch,
940*e7be843bSPierre Pronchery                                           OSSL_ACKM_RX_PKT *ackm_data)
941*e7be843bSPierre Pronchery {
942*e7be843bSPierre Pronchery     uint64_t frame_data = 0;
943*e7be843bSPierre Pronchery     unsigned char *encoded = NULL;
944*e7be843bSPierre Pronchery     size_t encoded_len;
945*e7be843bSPierre Pronchery     WPACKET wpkt;
946*e7be843bSPierre Pronchery 
947*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_path_challenge(pkt, &frame_data)) {
948*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
949*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
950*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE,
951*e7be843bSPierre Pronchery                                                "decode error");
952*e7be843bSPierre Pronchery         return 0;
953*e7be843bSPierre Pronchery     }
954*e7be843bSPierre Pronchery 
955*e7be843bSPierre Pronchery     /*
956*e7be843bSPierre Pronchery      * RFC 9000 s. 8.2.2: On receiving a PATH_CHALLENGE frame, an endpoint MUST
957*e7be843bSPierre Pronchery      * respond by echoing the data contained in the PATH_CHALLENGE frame in a
958*e7be843bSPierre Pronchery      * PATH_RESPONSE frame.
959*e7be843bSPierre Pronchery      *
960*e7be843bSPierre Pronchery      * TODO(QUIC FUTURE): We should try to avoid allocation here in the future.
961*e7be843bSPierre Pronchery      */
962*e7be843bSPierre Pronchery     encoded_len = sizeof(uint64_t) + 1;
963*e7be843bSPierre Pronchery     if ((encoded = OPENSSL_malloc(encoded_len)) == NULL)
964*e7be843bSPierre Pronchery         goto err;
965*e7be843bSPierre Pronchery 
966*e7be843bSPierre Pronchery     if (!WPACKET_init_static_len(&wpkt, encoded, encoded_len, 0))
967*e7be843bSPierre Pronchery         goto err;
968*e7be843bSPierre Pronchery 
969*e7be843bSPierre Pronchery     if (!ossl_quic_wire_encode_frame_path_response(&wpkt, frame_data)) {
970*e7be843bSPierre Pronchery         WPACKET_cleanup(&wpkt);
971*e7be843bSPierre Pronchery         goto err;
972*e7be843bSPierre Pronchery     }
973*e7be843bSPierre Pronchery 
974*e7be843bSPierre Pronchery     WPACKET_finish(&wpkt);
975*e7be843bSPierre Pronchery 
976*e7be843bSPierre Pronchery     if (!ossl_quic_cfq_add_frame(ch->cfq, 0, QUIC_PN_SPACE_APP,
977*e7be843bSPierre Pronchery                                  OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE,
978*e7be843bSPierre Pronchery                                  QUIC_CFQ_ITEM_FLAG_UNRELIABLE,
979*e7be843bSPierre Pronchery                                  encoded, encoded_len,
980*e7be843bSPierre Pronchery                                  free_path_response, NULL))
981*e7be843bSPierre Pronchery         goto err;
982*e7be843bSPierre Pronchery 
983*e7be843bSPierre Pronchery     return 1;
984*e7be843bSPierre Pronchery 
985*e7be843bSPierre Pronchery err:
986*e7be843bSPierre Pronchery     OPENSSL_free(encoded);
987*e7be843bSPierre Pronchery     ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INTERNAL_ERROR,
988*e7be843bSPierre Pronchery                                            OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE,
989*e7be843bSPierre Pronchery                                            "internal error");
990*e7be843bSPierre Pronchery     return 0;
991*e7be843bSPierre Pronchery }
992*e7be843bSPierre Pronchery 
depack_do_frame_path_response(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)993*e7be843bSPierre Pronchery static int depack_do_frame_path_response(PACKET *pkt,
994*e7be843bSPierre Pronchery                                          QUIC_CHANNEL *ch,
995*e7be843bSPierre Pronchery                                          OSSL_ACKM_RX_PKT *ackm_data)
996*e7be843bSPierre Pronchery {
997*e7be843bSPierre Pronchery     uint64_t frame_data = 0;
998*e7be843bSPierre Pronchery 
999*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_path_response(pkt, &frame_data)) {
1000*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
1001*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
1002*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE,
1003*e7be843bSPierre Pronchery                                                "decode error");
1004*e7be843bSPierre Pronchery         return 0;
1005*e7be843bSPierre Pronchery     }
1006*e7be843bSPierre Pronchery 
1007*e7be843bSPierre Pronchery     /* TODO(QUIC MULTIPATH): ADD CODE to send |frame_data| to the ch manager */
1008*e7be843bSPierre Pronchery 
1009*e7be843bSPierre Pronchery     return 1;
1010*e7be843bSPierre Pronchery }
1011*e7be843bSPierre Pronchery 
depack_do_frame_conn_close(PACKET * pkt,QUIC_CHANNEL * ch,uint64_t frame_type)1012*e7be843bSPierre Pronchery static int depack_do_frame_conn_close(PACKET *pkt, QUIC_CHANNEL *ch,
1013*e7be843bSPierre Pronchery                                       uint64_t frame_type)
1014*e7be843bSPierre Pronchery {
1015*e7be843bSPierre Pronchery     OSSL_QUIC_FRAME_CONN_CLOSE frame_data;
1016*e7be843bSPierre Pronchery 
1017*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_conn_close(pkt, &frame_data)) {
1018*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
1019*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
1020*e7be843bSPierre Pronchery                                                frame_type,
1021*e7be843bSPierre Pronchery                                                "decode error");
1022*e7be843bSPierre Pronchery         return 0;
1023*e7be843bSPierre Pronchery     }
1024*e7be843bSPierre Pronchery 
1025*e7be843bSPierre Pronchery     ossl_quic_channel_on_remote_conn_close(ch, &frame_data);
1026*e7be843bSPierre Pronchery     return 1;
1027*e7be843bSPierre Pronchery }
1028*e7be843bSPierre Pronchery 
depack_do_frame_handshake_done(PACKET * pkt,QUIC_CHANNEL * ch,OSSL_ACKM_RX_PKT * ackm_data)1029*e7be843bSPierre Pronchery static int depack_do_frame_handshake_done(PACKET *pkt,
1030*e7be843bSPierre Pronchery                                           QUIC_CHANNEL *ch,
1031*e7be843bSPierre Pronchery                                           OSSL_ACKM_RX_PKT *ackm_data)
1032*e7be843bSPierre Pronchery {
1033*e7be843bSPierre Pronchery     if (!ossl_quic_wire_decode_frame_handshake_done(pkt)) {
1034*e7be843bSPierre Pronchery         /* This can fail only with an internal error. */
1035*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
1036*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_INTERNAL_ERROR,
1037*e7be843bSPierre Pronchery                                                OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE,
1038*e7be843bSPierre Pronchery                                                "internal error (decode frame handshake done)");
1039*e7be843bSPierre Pronchery         return 0;
1040*e7be843bSPierre Pronchery     }
1041*e7be843bSPierre Pronchery 
1042*e7be843bSPierre Pronchery     ossl_quic_channel_on_handshake_confirmed(ch);
1043*e7be843bSPierre Pronchery     return 1;
1044*e7be843bSPierre Pronchery }
1045*e7be843bSPierre Pronchery 
1046*e7be843bSPierre Pronchery /* Main frame processor */
1047*e7be843bSPierre Pronchery 
depack_process_frames(QUIC_CHANNEL * ch,PACKET * pkt,OSSL_QRX_PKT * parent_pkt,uint32_t enc_level,OSSL_TIME received,OSSL_ACKM_RX_PKT * ackm_data)1048*e7be843bSPierre Pronchery static int depack_process_frames(QUIC_CHANNEL *ch, PACKET *pkt,
1049*e7be843bSPierre Pronchery                                  OSSL_QRX_PKT *parent_pkt, uint32_t enc_level,
1050*e7be843bSPierre Pronchery                                  OSSL_TIME received, OSSL_ACKM_RX_PKT *ackm_data)
1051*e7be843bSPierre Pronchery {
1052*e7be843bSPierre Pronchery     uint32_t pkt_type = parent_pkt->hdr->type;
1053*e7be843bSPierre Pronchery     uint32_t packet_space = ossl_quic_enc_level_to_pn_space(enc_level);
1054*e7be843bSPierre Pronchery 
1055*e7be843bSPierre Pronchery     if (PACKET_remaining(pkt) == 0) {
1056*e7be843bSPierre Pronchery         /*
1057*e7be843bSPierre Pronchery          * RFC 9000 s. 12.4: An endpoint MUST treat receipt of a packet
1058*e7be843bSPierre Pronchery          * containing no frames as a connection error of type
1059*e7be843bSPierre Pronchery          * PROTOCOL_VIOLATION.
1060*e7be843bSPierre Pronchery          */
1061*e7be843bSPierre Pronchery         ossl_quic_channel_raise_protocol_error(ch,
1062*e7be843bSPierre Pronchery                                                OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1063*e7be843bSPierre Pronchery                                                0,
1064*e7be843bSPierre Pronchery                                                "empty packet payload");
1065*e7be843bSPierre Pronchery         return 0;
1066*e7be843bSPierre Pronchery     }
1067*e7be843bSPierre Pronchery 
1068*e7be843bSPierre Pronchery     while (PACKET_remaining(pkt) > 0) {
1069*e7be843bSPierre Pronchery         int was_minimal;
1070*e7be843bSPierre Pronchery         uint64_t frame_type;
1071*e7be843bSPierre Pronchery         const unsigned char *sof = NULL;
1072*e7be843bSPierre Pronchery         uint64_t datalen = 0;
1073*e7be843bSPierre Pronchery 
1074*e7be843bSPierre Pronchery         if (ch->msg_callback != NULL)
1075*e7be843bSPierre Pronchery             sof = PACKET_data(pkt);
1076*e7be843bSPierre Pronchery 
1077*e7be843bSPierre Pronchery         if (!ossl_quic_wire_peek_frame_header(pkt, &frame_type, &was_minimal)) {
1078*e7be843bSPierre Pronchery             ossl_quic_channel_raise_protocol_error(ch,
1079*e7be843bSPierre Pronchery                                                    OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1080*e7be843bSPierre Pronchery                                                    0,
1081*e7be843bSPierre Pronchery                                                    "malformed frame header");
1082*e7be843bSPierre Pronchery             return 0;
1083*e7be843bSPierre Pronchery         }
1084*e7be843bSPierre Pronchery 
1085*e7be843bSPierre Pronchery         if (!was_minimal) {
1086*e7be843bSPierre Pronchery             ossl_quic_channel_raise_protocol_error(ch,
1087*e7be843bSPierre Pronchery                                                    OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1088*e7be843bSPierre Pronchery                                                    frame_type,
1089*e7be843bSPierre Pronchery                                                    "non-minimal frame type encoding");
1090*e7be843bSPierre Pronchery             return 0;
1091*e7be843bSPierre Pronchery         }
1092*e7be843bSPierre Pronchery 
1093*e7be843bSPierre Pronchery         /*
1094*e7be843bSPierre Pronchery          * There are only a few frame types which are not ACK-eliciting. Handle
1095*e7be843bSPierre Pronchery          * these centrally to make error handling cases more resilient, as we
1096*e7be843bSPierre Pronchery          * should tell the ACKM about an ACK-eliciting frame even if it was not
1097*e7be843bSPierre Pronchery          * successfully handled.
1098*e7be843bSPierre Pronchery          */
1099*e7be843bSPierre Pronchery         switch (frame_type) {
1100*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_PADDING:
1101*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN:
1102*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN:
1103*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT:
1104*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP:
1105*e7be843bSPierre Pronchery             break;
1106*e7be843bSPierre Pronchery         default:
1107*e7be843bSPierre Pronchery             ackm_data->is_ack_eliciting = 1;
1108*e7be843bSPierre Pronchery             break;
1109*e7be843bSPierre Pronchery         }
1110*e7be843bSPierre Pronchery 
1111*e7be843bSPierre Pronchery         switch (frame_type) {
1112*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_PING:
1113*e7be843bSPierre Pronchery             /* Allowed in all packet types */
1114*e7be843bSPierre Pronchery             if (!depack_do_frame_ping(pkt, ch, enc_level, ackm_data))
1115*e7be843bSPierre Pronchery                 return 0;
1116*e7be843bSPierre Pronchery             break;
1117*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_PADDING:
1118*e7be843bSPierre Pronchery             /* Allowed in all packet types */
1119*e7be843bSPierre Pronchery             if (!depack_do_frame_padding(pkt))
1120*e7be843bSPierre Pronchery                 return 0;
1121*e7be843bSPierre Pronchery             break;
1122*e7be843bSPierre Pronchery 
1123*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN:
1124*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN:
1125*e7be843bSPierre Pronchery             /* ACK frames are valid everywhere except in 0RTT packets */
1126*e7be843bSPierre Pronchery             if (pkt_type == QUIC_PKT_TYPE_0RTT) {
1127*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1128*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1129*e7be843bSPierre Pronchery                                                        frame_type,
1130*e7be843bSPierre Pronchery                                                        "ACK not valid in 0-RTT");
1131*e7be843bSPierre Pronchery                 return 0;
1132*e7be843bSPierre Pronchery             }
1133*e7be843bSPierre Pronchery             if (!depack_do_frame_ack(pkt, ch, packet_space, received,
1134*e7be843bSPierre Pronchery                                      frame_type, parent_pkt))
1135*e7be843bSPierre Pronchery                 return 0;
1136*e7be843bSPierre Pronchery             break;
1137*e7be843bSPierre Pronchery 
1138*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_RESET_STREAM:
1139*e7be843bSPierre Pronchery             /* RESET_STREAM frames are valid in 0RTT and 1RTT packets */
1140*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1141*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1142*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1143*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1144*e7be843bSPierre Pronchery                                                        frame_type,
1145*e7be843bSPierre Pronchery                                                        "RESET_STREAM not valid in "
1146*e7be843bSPierre Pronchery                                                        "INITIAL/HANDSHAKE");
1147*e7be843bSPierre Pronchery                 return 0;
1148*e7be843bSPierre Pronchery             }
1149*e7be843bSPierre Pronchery             if (!depack_do_frame_reset_stream(pkt, ch, ackm_data))
1150*e7be843bSPierre Pronchery                 return 0;
1151*e7be843bSPierre Pronchery             break;
1152*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STOP_SENDING:
1153*e7be843bSPierre Pronchery             /* STOP_SENDING frames are valid in 0RTT and 1RTT packets */
1154*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1155*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1156*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1157*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1158*e7be843bSPierre Pronchery                                                        frame_type,
1159*e7be843bSPierre Pronchery                                                        "STOP_SENDING not valid in "
1160*e7be843bSPierre Pronchery                                                        "INITIAL/HANDSHAKE");
1161*e7be843bSPierre Pronchery                 return 0;
1162*e7be843bSPierre Pronchery             }
1163*e7be843bSPierre Pronchery             if (!depack_do_frame_stop_sending(pkt, ch, ackm_data))
1164*e7be843bSPierre Pronchery                 return 0;
1165*e7be843bSPierre Pronchery             break;
1166*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_CRYPTO:
1167*e7be843bSPierre Pronchery             /* CRYPTO frames are valid everywhere except in 0RTT packets */
1168*e7be843bSPierre Pronchery             if (pkt_type == QUIC_PKT_TYPE_0RTT) {
1169*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1170*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1171*e7be843bSPierre Pronchery                                                        frame_type,
1172*e7be843bSPierre Pronchery                                                        "CRYPTO frame not valid in 0-RTT");
1173*e7be843bSPierre Pronchery                 return 0;
1174*e7be843bSPierre Pronchery             }
1175*e7be843bSPierre Pronchery             if (!depack_do_frame_crypto(pkt, ch, parent_pkt, ackm_data, &datalen))
1176*e7be843bSPierre Pronchery                 return 0;
1177*e7be843bSPierre Pronchery             break;
1178*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN:
1179*e7be843bSPierre Pronchery             /* NEW_TOKEN frames are valid in 1RTT packets */
1180*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_1RTT) {
1181*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1182*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1183*e7be843bSPierre Pronchery                                                        frame_type,
1184*e7be843bSPierre Pronchery                                                        "NEW_TOKEN valid only in 1-RTT");
1185*e7be843bSPierre Pronchery                 return 0;
1186*e7be843bSPierre Pronchery             }
1187*e7be843bSPierre Pronchery 
1188*e7be843bSPierre Pronchery             /*
1189*e7be843bSPierre Pronchery              * RFC 9000 s. 19.7: "A server MUST treat receipt of a NEW_TOKEN
1190*e7be843bSPierre Pronchery              * frame as a connection error of type PROTOCOL_VIOLATION."
1191*e7be843bSPierre Pronchery              */
1192*e7be843bSPierre Pronchery             if (ch->is_server) {
1193*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1194*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1195*e7be843bSPierre Pronchery                                                        frame_type,
1196*e7be843bSPierre Pronchery                                                        "NEW_TOKEN can only be sent by a server");
1197*e7be843bSPierre Pronchery                 return 0;
1198*e7be843bSPierre Pronchery             }
1199*e7be843bSPierre Pronchery 
1200*e7be843bSPierre Pronchery             if (!depack_do_frame_new_token(pkt, ch, ackm_data))
1201*e7be843bSPierre Pronchery                 return 0;
1202*e7be843bSPierre Pronchery             break;
1203*e7be843bSPierre Pronchery 
1204*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAM:
1205*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAM_FIN:
1206*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAM_LEN:
1207*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAM_LEN_FIN:
1208*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAM_OFF:
1209*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_FIN:
1210*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN:
1211*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN_FIN:
1212*e7be843bSPierre Pronchery             /* STREAM frames are valid in 0RTT and 1RTT packets */
1213*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1214*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1215*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1216*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1217*e7be843bSPierre Pronchery                                                        frame_type,
1218*e7be843bSPierre Pronchery                                                        "STREAM valid only in 0/1-RTT");
1219*e7be843bSPierre Pronchery                 return 0;
1220*e7be843bSPierre Pronchery             }
1221*e7be843bSPierre Pronchery             if (!depack_do_frame_stream(pkt, ch, parent_pkt, ackm_data,
1222*e7be843bSPierre Pronchery                                         frame_type, &datalen))
1223*e7be843bSPierre Pronchery                 return 0;
1224*e7be843bSPierre Pronchery             break;
1225*e7be843bSPierre Pronchery 
1226*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_MAX_DATA:
1227*e7be843bSPierre Pronchery             /* MAX_DATA frames are valid in 0RTT and 1RTT packets */
1228*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1229*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1230*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1231*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1232*e7be843bSPierre Pronchery                                                        frame_type,
1233*e7be843bSPierre Pronchery                                                        "MAX_DATA valid only in 0/1-RTT");
1234*e7be843bSPierre Pronchery                 return 0;
1235*e7be843bSPierre Pronchery             }
1236*e7be843bSPierre Pronchery             if (!depack_do_frame_max_data(pkt, ch, ackm_data))
1237*e7be843bSPierre Pronchery                 return 0;
1238*e7be843bSPierre Pronchery             break;
1239*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA:
1240*e7be843bSPierre Pronchery             /* MAX_STREAM_DATA frames are valid in 0RTT and 1RTT packets */
1241*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1242*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1243*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1244*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1245*e7be843bSPierre Pronchery                                                        frame_type,
1246*e7be843bSPierre Pronchery                                                        "MAX_STREAM_DATA valid only in 0/1-RTT");
1247*e7be843bSPierre Pronchery                 return 0;
1248*e7be843bSPierre Pronchery             }
1249*e7be843bSPierre Pronchery             if (!depack_do_frame_max_stream_data(pkt, ch, ackm_data))
1250*e7be843bSPierre Pronchery                 return 0;
1251*e7be843bSPierre Pronchery             break;
1252*e7be843bSPierre Pronchery 
1253*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI:
1254*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI:
1255*e7be843bSPierre Pronchery             /* MAX_STREAMS frames are valid in 0RTT and 1RTT packets */
1256*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1257*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1258*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1259*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1260*e7be843bSPierre Pronchery                                                        frame_type,
1261*e7be843bSPierre Pronchery                                                        "MAX_STREAMS valid only in 0/1-RTT");
1262*e7be843bSPierre Pronchery                 return 0;
1263*e7be843bSPierre Pronchery             }
1264*e7be843bSPierre Pronchery             if (!depack_do_frame_max_streams(pkt, ch, ackm_data,
1265*e7be843bSPierre Pronchery                                              frame_type))
1266*e7be843bSPierre Pronchery                 return 0;
1267*e7be843bSPierre Pronchery             break;
1268*e7be843bSPierre Pronchery 
1269*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_DATA_BLOCKED:
1270*e7be843bSPierre Pronchery             /* DATA_BLOCKED frames are valid in 0RTT and 1RTT packets */
1271*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1272*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1273*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1274*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1275*e7be843bSPierre Pronchery                                                        frame_type,
1276*e7be843bSPierre Pronchery                                                        "DATA_BLOCKED valid only in 0/1-RTT");
1277*e7be843bSPierre Pronchery                 return 0;
1278*e7be843bSPierre Pronchery             }
1279*e7be843bSPierre Pronchery             if (!depack_do_frame_data_blocked(pkt, ch, ackm_data))
1280*e7be843bSPierre Pronchery                 return 0;
1281*e7be843bSPierre Pronchery             break;
1282*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED:
1283*e7be843bSPierre Pronchery             /* STREAM_DATA_BLOCKED frames are valid in 0RTT and 1RTT packets */
1284*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1285*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1286*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1287*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1288*e7be843bSPierre Pronchery                                                        frame_type,
1289*e7be843bSPierre Pronchery                                                        "STREAM_DATA_BLOCKED valid only in 0/1-RTT");
1290*e7be843bSPierre Pronchery                 return 0;
1291*e7be843bSPierre Pronchery             }
1292*e7be843bSPierre Pronchery             if (!depack_do_frame_stream_data_blocked(pkt, ch, ackm_data))
1293*e7be843bSPierre Pronchery                 return 0;
1294*e7be843bSPierre Pronchery             break;
1295*e7be843bSPierre Pronchery 
1296*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI:
1297*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_UNI:
1298*e7be843bSPierre Pronchery             /* STREAMS_BLOCKED frames are valid in 0RTT and 1RTT packets */
1299*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1300*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1301*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1302*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1303*e7be843bSPierre Pronchery                                                        frame_type,
1304*e7be843bSPierre Pronchery                                                        "STREAMS valid only in 0/1-RTT");
1305*e7be843bSPierre Pronchery                 return 0;
1306*e7be843bSPierre Pronchery             }
1307*e7be843bSPierre Pronchery             if (!depack_do_frame_streams_blocked(pkt, ch, ackm_data,
1308*e7be843bSPierre Pronchery                                                  frame_type))
1309*e7be843bSPierre Pronchery                 return 0;
1310*e7be843bSPierre Pronchery             break;
1311*e7be843bSPierre Pronchery 
1312*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID:
1313*e7be843bSPierre Pronchery             /* NEW_CONN_ID frames are valid in 0RTT and 1RTT packets */
1314*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1315*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1316*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1317*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1318*e7be843bSPierre Pronchery                                                        frame_type,
1319*e7be843bSPierre Pronchery                                                        "NEW_CONN_ID valid only in 0/1-RTT");
1320*e7be843bSPierre Pronchery             }
1321*e7be843bSPierre Pronchery             if (!depack_do_frame_new_conn_id(pkt, ch, ackm_data))
1322*e7be843bSPierre Pronchery                 return 0;
1323*e7be843bSPierre Pronchery             break;
1324*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID:
1325*e7be843bSPierre Pronchery             /* RETIRE_CONN_ID frames are valid in 0RTT and 1RTT packets */
1326*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1327*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1328*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1329*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1330*e7be843bSPierre Pronchery                                                        frame_type,
1331*e7be843bSPierre Pronchery                                                        "RETIRE_CONN_ID valid only in 0/1-RTT");
1332*e7be843bSPierre Pronchery                 return 0;
1333*e7be843bSPierre Pronchery             }
1334*e7be843bSPierre Pronchery             if (!depack_do_frame_retire_conn_id(pkt, ch, ackm_data))
1335*e7be843bSPierre Pronchery                 return 0;
1336*e7be843bSPierre Pronchery             break;
1337*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE:
1338*e7be843bSPierre Pronchery             /* PATH_CHALLENGE frames are valid in 0RTT and 1RTT packets */
1339*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1340*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1341*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1342*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1343*e7be843bSPierre Pronchery                                                        frame_type,
1344*e7be843bSPierre Pronchery                                                        "PATH_CHALLENGE valid only in 0/1-RTT");
1345*e7be843bSPierre Pronchery                 return 0;
1346*e7be843bSPierre Pronchery             }
1347*e7be843bSPierre Pronchery             if (!depack_do_frame_path_challenge(pkt, ch, ackm_data))
1348*e7be843bSPierre Pronchery                 return 0;
1349*e7be843bSPierre Pronchery 
1350*e7be843bSPierre Pronchery             break;
1351*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE:
1352*e7be843bSPierre Pronchery             /* PATH_RESPONSE frames are valid in 1RTT packets */
1353*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_1RTT) {
1354*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1355*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1356*e7be843bSPierre Pronchery                                                        frame_type,
1357*e7be843bSPierre Pronchery                                                        "PATH_CHALLENGE valid only in 1-RTT");
1358*e7be843bSPierre Pronchery                 return 0;
1359*e7be843bSPierre Pronchery             }
1360*e7be843bSPierre Pronchery             if (!depack_do_frame_path_response(pkt, ch, ackm_data))
1361*e7be843bSPierre Pronchery                 return 0;
1362*e7be843bSPierre Pronchery             break;
1363*e7be843bSPierre Pronchery 
1364*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP:
1365*e7be843bSPierre Pronchery             /* CONN_CLOSE_APP frames are valid in 0RTT and 1RTT packets */
1366*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_0RTT
1367*e7be843bSPierre Pronchery                 && pkt_type != QUIC_PKT_TYPE_1RTT) {
1368*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1369*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1370*e7be843bSPierre Pronchery                                                        frame_type,
1371*e7be843bSPierre Pronchery                                                        "CONN_CLOSE (APP) valid only in 0/1-RTT");
1372*e7be843bSPierre Pronchery                 return 0;
1373*e7be843bSPierre Pronchery             }
1374*e7be843bSPierre Pronchery             /* FALLTHRU */
1375*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT:
1376*e7be843bSPierre Pronchery             /* CONN_CLOSE_TRANSPORT frames are valid in all packets */
1377*e7be843bSPierre Pronchery             if (!depack_do_frame_conn_close(pkt, ch, frame_type))
1378*e7be843bSPierre Pronchery                 return 0;
1379*e7be843bSPierre Pronchery             break;
1380*e7be843bSPierre Pronchery 
1381*e7be843bSPierre Pronchery         case OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE:
1382*e7be843bSPierre Pronchery             /* HANDSHAKE_DONE frames are valid in 1RTT packets */
1383*e7be843bSPierre Pronchery             if (pkt_type != QUIC_PKT_TYPE_1RTT) {
1384*e7be843bSPierre Pronchery                 ossl_quic_channel_raise_protocol_error(ch,
1385*e7be843bSPierre Pronchery                                                        OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
1386*e7be843bSPierre Pronchery                                                        frame_type,
1387*e7be843bSPierre Pronchery                                                        "HANDSHAKE_DONE valid only in 1-RTT");
1388*e7be843bSPierre Pronchery                 return 0;
1389*e7be843bSPierre Pronchery             }
1390*e7be843bSPierre Pronchery             if (!depack_do_frame_handshake_done(pkt, ch, ackm_data))
1391*e7be843bSPierre Pronchery                 return 0;
1392*e7be843bSPierre Pronchery             break;
1393*e7be843bSPierre Pronchery 
1394*e7be843bSPierre Pronchery         default:
1395*e7be843bSPierre Pronchery             /* Unknown frame type */
1396*e7be843bSPierre Pronchery             ossl_quic_channel_raise_protocol_error(ch,
1397*e7be843bSPierre Pronchery                                                    OSSL_QUIC_ERR_FRAME_ENCODING_ERROR,
1398*e7be843bSPierre Pronchery                                                    frame_type,
1399*e7be843bSPierre Pronchery                                                    "Unknown frame type received");
1400*e7be843bSPierre Pronchery             return 0;
1401*e7be843bSPierre Pronchery         }
1402*e7be843bSPierre Pronchery 
1403*e7be843bSPierre Pronchery         if (ch->msg_callback != NULL) {
1404*e7be843bSPierre Pronchery             int ctype = SSL3_RT_QUIC_FRAME_FULL;
1405*e7be843bSPierre Pronchery 
1406*e7be843bSPierre Pronchery             size_t framelen = PACKET_data(pkt) - sof;
1407*e7be843bSPierre Pronchery 
1408*e7be843bSPierre Pronchery             if (frame_type == OSSL_QUIC_FRAME_TYPE_PADDING) {
1409*e7be843bSPierre Pronchery                 ctype = SSL3_RT_QUIC_FRAME_PADDING;
1410*e7be843bSPierre Pronchery             } else if (OSSL_QUIC_FRAME_TYPE_IS_STREAM(frame_type)
1411*e7be843bSPierre Pronchery                     || frame_type == OSSL_QUIC_FRAME_TYPE_CRYPTO) {
1412*e7be843bSPierre Pronchery                 ctype = SSL3_RT_QUIC_FRAME_HEADER;
1413*e7be843bSPierre Pronchery                 framelen -= (size_t)datalen;
1414*e7be843bSPierre Pronchery             }
1415*e7be843bSPierre Pronchery 
1416*e7be843bSPierre Pronchery             ch->msg_callback(0, OSSL_QUIC1_VERSION, ctype, sof, framelen,
1417*e7be843bSPierre Pronchery                              ch->msg_callback_ssl, ch->msg_callback_arg);
1418*e7be843bSPierre Pronchery         }
1419*e7be843bSPierre Pronchery     }
1420*e7be843bSPierre Pronchery 
1421*e7be843bSPierre Pronchery     return 1;
1422*e7be843bSPierre Pronchery }
1423*e7be843bSPierre Pronchery 
1424*e7be843bSPierre Pronchery QUIC_NEEDS_LOCK
ossl_quic_handle_frames(QUIC_CHANNEL * ch,OSSL_QRX_PKT * qpacket)1425*e7be843bSPierre Pronchery int ossl_quic_handle_frames(QUIC_CHANNEL *ch, OSSL_QRX_PKT *qpacket)
1426*e7be843bSPierre Pronchery {
1427*e7be843bSPierre Pronchery     PACKET pkt;
1428*e7be843bSPierre Pronchery     OSSL_ACKM_RX_PKT ackm_data;
1429*e7be843bSPierre Pronchery     uint32_t enc_level;
1430*e7be843bSPierre Pronchery     size_t dgram_len = qpacket->datagram_len;
1431*e7be843bSPierre Pronchery 
1432*e7be843bSPierre Pronchery     /*
1433*e7be843bSPierre Pronchery      * ok has three states:
1434*e7be843bSPierre Pronchery      * -1 error with ackm_data uninitialized
1435*e7be843bSPierre Pronchery      *  0 error with ackm_data initialized
1436*e7be843bSPierre Pronchery      *  1 success (ackm_data initialized)
1437*e7be843bSPierre Pronchery      */
1438*e7be843bSPierre Pronchery     int ok = -1;                  /* Assume the worst */
1439*e7be843bSPierre Pronchery 
1440*e7be843bSPierre Pronchery     if (ch == NULL)
1441*e7be843bSPierre Pronchery         goto end;
1442*e7be843bSPierre Pronchery 
1443*e7be843bSPierre Pronchery     ch->did_crypto_frame = 0;
1444*e7be843bSPierre Pronchery 
1445*e7be843bSPierre Pronchery     /* Initialize |ackm_data| (and reinitialize |ok|)*/
1446*e7be843bSPierre Pronchery     memset(&ackm_data, 0, sizeof(ackm_data));
1447*e7be843bSPierre Pronchery     /*
1448*e7be843bSPierre Pronchery      * ASSUMPTION: All packets that aren't special case have a
1449*e7be843bSPierre Pronchery      * packet number.
1450*e7be843bSPierre Pronchery      */
1451*e7be843bSPierre Pronchery     ackm_data.pkt_num = qpacket->pn;
1452*e7be843bSPierre Pronchery     ackm_data.time = qpacket->time;
1453*e7be843bSPierre Pronchery     enc_level = ossl_quic_pkt_type_to_enc_level(qpacket->hdr->type);
1454*e7be843bSPierre Pronchery     if (enc_level >= QUIC_ENC_LEVEL_NUM)
1455*e7be843bSPierre Pronchery         /*
1456*e7be843bSPierre Pronchery          * Retry and Version Negotiation packets should not be passed to this
1457*e7be843bSPierre Pronchery          * function.
1458*e7be843bSPierre Pronchery          */
1459*e7be843bSPierre Pronchery         goto end;
1460*e7be843bSPierre Pronchery 
1461*e7be843bSPierre Pronchery     ok = 0; /* Still assume the worst */
1462*e7be843bSPierre Pronchery     ackm_data.pkt_space = ossl_quic_enc_level_to_pn_space(enc_level);
1463*e7be843bSPierre Pronchery 
1464*e7be843bSPierre Pronchery     /*
1465*e7be843bSPierre Pronchery      * RFC 9000 s. 8.1
1466*e7be843bSPierre Pronchery      * We can consider the connection to be validated, if we receive a packet
1467*e7be843bSPierre Pronchery      * from the client protected via handshake keys, meaning that the
1468*e7be843bSPierre Pronchery      * amplification limit no longer applies (i.e. we can set it as validated.
1469*e7be843bSPierre Pronchery      * Otherwise, add the size of this packet to the unvalidated credit for
1470*e7be843bSPierre Pronchery      * the connection.
1471*e7be843bSPierre Pronchery      */
1472*e7be843bSPierre Pronchery     if (enc_level == QUIC_ENC_LEVEL_HANDSHAKE)
1473*e7be843bSPierre Pronchery         ossl_quic_tx_packetiser_set_validated(ch->txp);
1474*e7be843bSPierre Pronchery     else
1475*e7be843bSPierre Pronchery         ossl_quic_tx_packetiser_add_unvalidated_credit(ch->txp, dgram_len);
1476*e7be843bSPierre Pronchery 
1477*e7be843bSPierre Pronchery     /* Now that special cases are out of the way, parse frames */
1478*e7be843bSPierre Pronchery     if (!PACKET_buf_init(&pkt, qpacket->hdr->data, qpacket->hdr->len)
1479*e7be843bSPierre Pronchery         || !depack_process_frames(ch, &pkt, qpacket,
1480*e7be843bSPierre Pronchery                                   enc_level,
1481*e7be843bSPierre Pronchery                                   qpacket->time,
1482*e7be843bSPierre Pronchery                                   &ackm_data))
1483*e7be843bSPierre Pronchery         goto end;
1484*e7be843bSPierre Pronchery 
1485*e7be843bSPierre Pronchery     ok = 1;
1486*e7be843bSPierre Pronchery  end:
1487*e7be843bSPierre Pronchery     /*
1488*e7be843bSPierre Pronchery      * ASSUMPTION: If this function is called at all, |qpacket| is
1489*e7be843bSPierre Pronchery      * a legitimate packet, even if its contents aren't.
1490*e7be843bSPierre Pronchery      * Therefore, we call ossl_ackm_on_rx_packet() unconditionally, as long as
1491*e7be843bSPierre Pronchery      * |ackm_data| has at least been initialized.
1492*e7be843bSPierre Pronchery      */
1493*e7be843bSPierre Pronchery     if (ok >= 0)
1494*e7be843bSPierre Pronchery         ossl_ackm_on_rx_packet(ch->ackm, &ackm_data);
1495*e7be843bSPierre Pronchery 
1496*e7be843bSPierre Pronchery     return ok > 0;
1497*e7be843bSPierre Pronchery }
1498