TX key update support, RX time and PN reporting, general refactoring
[openssl.git] / include / internal / quic_demux.h
1 /*
2  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #ifndef OSSL_QUIC_DEMUX_H
11 # define OSSL_QUIC_DEMUX_H
12
13 # include <openssl/ssl.h>
14 # include "internal/quic_types.h"
15 # include "internal/bio_addr.h"
16 # include "internal/time.h"
17
18 /*
19  * QUIC Demuxer
20  * ============
21  *
22  * The QUIC connection demuxer is the entity responsible for receiving datagrams
23  * from the network via a datagram BIO. It parses packet headers to determine
24  * each packet's destination connection ID (DCID) and hands off processing of
25  * the packet to the correct QUIC Record Layer (QRL)'s RX side (known as the
26  * QRX).
27  *
28  * A QRX is instantiated per QUIC connection and contains the cryptographic
29  * resources needed to decrypt QUIC packets for that connection. Received
30  * datagrams are passed from the demuxer to the QRX via a callback registered
31  * for a specific DCID by the QRX; thus the demuxer has no specific knowledge of
32  * the QRX and is not coupled to it.
33  *
34  * A connection may have multiple connection IDs associated with it; a QRX
35  * handles this simply by registering multiple connection IDs with the demuxer
36  * via multiple register calls.
37  *
38  * URX Queue
39  * ---------
40  *
41  * Since the demuxer must handle the initial reception of datagrams from the OS,
42  * RX queue management for new, unprocessed datagrams is also handled by the
43  * demuxer.
44  *
45  * The demuxer maintains a queue of Unprocessed RX Entries (URXEs), which store
46  * unprocessed (i.e., encrypted, unvalidated) data received from the network.
47  * The URXE queue is designed to allow multiple datagrams to be received in a
48  * single call to BIO_recvmmsg, where supported.
49  *
50  * One URXE is used per received datagram. Each datagram may contain multiple
51  * packets, however, this is not the demuxer's concern. QUIC prohibits different
52  * packets in the same datagram from containing different DCIDs; the demuxer
53  * only considers the DCID of the first packet in a datagram when deciding how
54  * to route a received datagram, and it is the responsibility of the QRX to
55  * enforce this rule. Packets other than the first packet in a datagram are not
56  * examined by the demuxer, and the demuxer does not perform validation of
57  * packet headers other than to the minimum extent necessary to extract the
58  * DCID; further parsing and validation of packet headers is the responsibility
59  * of the QRX.
60  *
61  * Rather than defining an opaque interface, the URXE structure internals
62  * are exposed. Since the demuxer is only exposed to other parts of the QUIC
63  * implementation internals, this poses no problem, and has a number of
64  * advantages:
65  *
66  *   - Fields in the URXE can be allocated to support requirements in other
67  *     components, like the QRX, which would otherwise have to allocate extra
68  *     memory corresponding to each URXE.
69  *
70  *   - Other components, like the QRX, can keep the URXE in queues of its own
71  *     when it is not being managed by the demuxer.
72  *
73  * URX Queue Structure
74  * -------------------
75  *
76  * The URXE queue is maintained as a simple doubly-linked list. URXE entries are
77  * moved between different lists in their lifecycle (for example, from a free
78  * list to a pending list and vice versa). The buffer into which datagrams are
79  * received immediately follows this URXE header structure and is part of the
80  * same allocation.
81  */
82
83 typedef struct quic_urxe_st QUIC_URXE;
84
85 /* Maximum number of packets we allow to exist in one datagram. */
86 #define QUIC_MAX_PKT_PER_URXE       (sizeof(uint64_t) * 8)
87
88 struct quic_urxe_st {
89     QUIC_URXE *prev, *next;
90
91     /*
92      * The URXE data starts after this structure so we don't need a pointer.
93      * data_len stores the current length (i.e., the length of the received
94      * datagram) and alloc_len stores the allocation length. The URXE will be
95      * reallocated if we need a larger allocation than is available, though this
96      * should not be common as we will have a good idea of worst-case MTUs up
97      * front.
98      */
99     size_t          data_len, alloc_len;
100
101     /*
102      * Bitfields per packet. processed indicates the packet has been processed
103      * and must not be processed again, hpr_removed indicates header protection
104      * has already been removed. Used by QRX only; not used by the demuxer.
105      */
106     uint64_t        processed, hpr_removed;
107
108     /*
109      * Address of peer we received the datagram from, and the local interface
110      * address we received it on. If local address support is not enabled, local
111      * is zeroed.
112      */
113     BIO_ADDR        peer, local;
114
115     /*
116      * Time at which datagram was received (or ossl_time_zero()) if a now
117      * function was not provided).
118      */
119     OSSL_TIME       time;
120 };
121
122 /* Accessors for URXE buffer. */
123 static ossl_unused ossl_inline unsigned char *
124 ossl_quic_urxe_data(const QUIC_URXE *e)
125 {
126     return (unsigned char *)&e[1];
127 }
128
129 static ossl_unused ossl_inline unsigned char *
130 ossl_quic_urxe_data_end(const QUIC_URXE *e)
131 {
132     return ossl_quic_urxe_data(e) + e->data_len;
133 }
134
135 /* List structure tracking a queue of URXEs. */
136 typedef struct quic_urxe_list_st {
137     QUIC_URXE *head, *tail;
138 } QUIC_URXE_LIST;
139
140 /*
141  * List management helpers. These are used by the demuxer but can also be used
142  * by users of the demuxer to manage URXEs.
143  */
144 void ossl_quic_urxe_remove(QUIC_URXE_LIST *l, QUIC_URXE *e);
145 void ossl_quic_urxe_insert_head(QUIC_URXE_LIST *l, QUIC_URXE *e);
146 void ossl_quic_urxe_insert_tail(QUIC_URXE_LIST *l, QUIC_URXE *e);
147
148 /* Opaque type representing a demuxer. */
149 typedef struct quic_demux_st QUIC_DEMUX;
150
151 /*
152  * Called when a datagram is received for a given connection ID.
153  *
154  * e is a URXE containing the datagram payload. It is permissible for the callee
155  * to mutate this buffer; once the demuxer calls this callback, it will never
156  * read the buffer again.
157  *
158  * The callee must arrange for ossl_quic_demux_release_urxe to be called on the URXE
159  * at some point in the future (this need not be before the callback returns).
160  *
161  * At the time the callback is made, the URXE will not be in any queue,
162  * therefore the callee can use the prev and next fields as it wishes.
163  */
164 typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg);
165
166 /*
167  * Creates a new demuxer. The given BIO is used to receive datagrams from the
168  * network using BIO_recvmmsg. short_conn_id_len is the length of destination
169  * connection IDs used in RX'd packets; it must have the same value for all
170  * connections used on a socket. default_urxe_alloc_len is the buffer size to
171  * receive datagrams into; it should be a value large enough to contain any
172  * received datagram according to local MTUs, etc.
173  *
174  * now is an optional function used to determine the time a datagram was
175  * received. now_arg is an opaque argument passed to the function. If now is
176  * NULL, ossl_time_zero() is used as the datagram reception time.
177  */
178 QUIC_DEMUX *ossl_quic_demux_new(BIO *net_bio,
179                                 size_t short_conn_id_len,
180                                 size_t default_urxe_alloc_len,
181                                 OSSL_TIME (*now)(void *arg),
182                                 void *now_arg);
183
184 /*
185  * Destroy a demuxer. All URXEs must have been released back to the demuxer
186  * before calling this. No-op if demux is NULL.
187  */
188 void ossl_quic_demux_free(QUIC_DEMUX *demux);
189
190 /*
191  * Register a datagram handler callback for a connection ID.
192  *
193  * ossl_quic_demux_pump will call the specified function if it receives a datagram
194  * the first packet of which has the specified destination connection ID.
195  *
196  * It is assumed all packets in a datagram have the same destination connection
197  * ID (as QUIC mandates this), but it is the user's responsibility to check for
198  * this and reject subsequent packets in a datagram that violate this rule.
199  *
200  * dst_conn_id is a destination connection ID; it is copied and need not remain
201  * valid after this function returns.
202  *
203  * cb_arg is passed to cb when it is called. For information on the callback,
204  * see its typedef above.
205  *
206  * Only one handler can be set for a given connection ID. If a handler is
207  * already set for the given connection ID, returns 0.
208  *
209  * Returns 1 on success or 0 on failure.
210  */
211 int ossl_quic_demux_register(QUIC_DEMUX *demux,
212                              const QUIC_CONN_ID *dst_conn_id,
213                              ossl_quic_demux_cb_fn *cb,
214                              void *cb_arg);
215
216 /*
217  * Unregisters any datagram handler callback set for the given connection ID.
218  * Fails if no handler is registered for the given connection ID.
219  *
220  * Returns 1 on success or 0 on failure.
221  */
222 int ossl_quic_demux_unregister(QUIC_DEMUX *demux,
223                                const QUIC_CONN_ID *dst_conn_id);
224
225 /*
226  * Unregisters any datagram handler callback from all connection IDs it is used
227  * for. cb and cb_arg must both match the values passed to
228  * ossl_quic_demux_register.
229  */
230 void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux,
231                                       ossl_quic_demux_cb_fn *cb,
232                                       void *cb_arg);
233
234 /*
235  * Releases a URXE back to the demuxer. No reference must be made to the URXE or
236  * its buffer after calling this function. The URXE must not be in any queue;
237  * that is, its prev and next pointers must be NULL.
238  */
239 void ossl_quic_demux_release_urxe(QUIC_DEMUX *demux,
240                                   QUIC_URXE *e);
241
242 /*
243  * Process any unprocessed RX'd datagrams, by calling registered callbacks by
244  * connection ID, reading more datagrams from the BIO if necessary.
245  *
246  * Returns 1 on success or 0 on failure.
247  */
248 int ossl_quic_demux_pump(QUIC_DEMUX *demux);
249
250 /*
251  * Artificially inject a packet into the demuxer for testing purposes. The
252  * buffer must not exceed the URXE size being used by the demuxer.
253  *
254  * If peer or local are NULL, their respective fields are zeroed in the injected
255  * URXE.
256  *
257  * Returns 1 on success or 0 on failure.
258  */
259 int ossl_quic_demux_inject(QUIC_DEMUX *demux,
260                            const unsigned char *buf,
261                            size_t buf_len,
262                            const BIO_ADDR *peer,
263                            const BIO_ADDR *local);
264
265 #endif