xref: /freebsd/crypto/openssl/include/internal/quic_rcidm.h (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2023-2024 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 #ifndef OSSL_INTERNAL_QUIC_RCIDM_H
11*e7be843bSPierre Pronchery # define OSSL_INTERNAL_QUIC_RCIDM_H
12*e7be843bSPierre Pronchery # pragma once
13*e7be843bSPierre Pronchery 
14*e7be843bSPierre Pronchery # include "internal/e_os.h"
15*e7be843bSPierre Pronchery # include "internal/time.h"
16*e7be843bSPierre Pronchery # include "internal/quic_types.h"
17*e7be843bSPierre Pronchery # include "internal/quic_wire.h"
18*e7be843bSPierre Pronchery 
19*e7be843bSPierre Pronchery # ifndef OPENSSL_NO_QUIC
20*e7be843bSPierre Pronchery 
21*e7be843bSPierre Pronchery /*
22*e7be843bSPierre Pronchery  * QUIC Remote Connection ID Manager
23*e7be843bSPierre Pronchery  * =================================
24*e7be843bSPierre Pronchery  *
25*e7be843bSPierre Pronchery  * This manages connection IDs for the TX side. The RCIDM tracks remote CIDs
26*e7be843bSPierre Pronchery  * (RCIDs) which a peer has issued to us and which we can use as the DCID of
27*e7be843bSPierre Pronchery  * packets we transmit. It is entirely separate from the LCIDM, which handles
28*e7be843bSPierre Pronchery  * routing received packets by their DCIDs.
29*e7be843bSPierre Pronchery  *
30*e7be843bSPierre Pronchery  * RCIDs fall into four categories:
31*e7be843bSPierre Pronchery  *
32*e7be843bSPierre Pronchery  *   1. A client's Initial ODCID                        (0..1)
33*e7be843bSPierre Pronchery  *   2. A peer's Initial SCID                           (1)
34*e7be843bSPierre Pronchery  *   3. A server's Retry SCID                           (0..1)
35*e7be843bSPierre Pronchery  *   4. A CID issued via a NEW_CONNECTION_ID frame      (n)
36*e7be843bSPierre Pronchery  *
37*e7be843bSPierre Pronchery  * Unlike a LCIDM, which is per port, a RCIDM is per connection, as there is no
38*e7be843bSPierre Pronchery  * need for routing of outgoing packets.
39*e7be843bSPierre Pronchery  */
40*e7be843bSPierre Pronchery typedef struct quic_rcidm_st QUIC_RCIDM;
41*e7be843bSPierre Pronchery 
42*e7be843bSPierre Pronchery /*
43*e7be843bSPierre Pronchery  * Creates a new RCIDM. Returns NULL on failure.
44*e7be843bSPierre Pronchery  *
45*e7be843bSPierre Pronchery  * For a client, initial_odcid is the client's Initial ODCID.
46*e7be843bSPierre Pronchery  * For a server, initial_odcid is NULL.
47*e7be843bSPierre Pronchery  */
48*e7be843bSPierre Pronchery QUIC_RCIDM *ossl_quic_rcidm_new(const QUIC_CONN_ID *initial_odcid);
49*e7be843bSPierre Pronchery 
50*e7be843bSPierre Pronchery /* Frees a RCIDM. */
51*e7be843bSPierre Pronchery void ossl_quic_rcidm_free(QUIC_RCIDM *rcidm);
52*e7be843bSPierre Pronchery 
53*e7be843bSPierre Pronchery /*
54*e7be843bSPierre Pronchery  * CID Events
55*e7be843bSPierre Pronchery  * ==========
56*e7be843bSPierre Pronchery  */
57*e7be843bSPierre Pronchery 
58*e7be843bSPierre Pronchery /*
59*e7be843bSPierre Pronchery  * To be called by a client when a server responds to the first Initial packet
60*e7be843bSPierre Pronchery  * sent with its own Initial packet with its own SCID; or to be called by a
61*e7be843bSPierre Pronchery  * server when we first get an Initial packet from a client with the client's
62*e7be843bSPierre Pronchery  * supplied SCID. The added RCID implicitly has a sequence number of 0.
63*e7be843bSPierre Pronchery  *
64*e7be843bSPierre Pronchery  * We immediately switch to using this SCID as our preferred RCID. This SCID
65*e7be843bSPierre Pronchery  * must be enrolled using this function. May only be called once.
66*e7be843bSPierre Pronchery  */
67*e7be843bSPierre Pronchery int ossl_quic_rcidm_add_from_initial(QUIC_RCIDM *rcidm,
68*e7be843bSPierre Pronchery                                      const QUIC_CONN_ID *rcid);
69*e7be843bSPierre Pronchery 
70*e7be843bSPierre Pronchery /*
71*e7be843bSPierre Pronchery  * To be called by a client when a server responds to the first Initial packet
72*e7be843bSPierre Pronchery  * sent with a Retry packet with its own SCID (the "Retry ODCID"). We
73*e7be843bSPierre Pronchery  * immediately switch to using this SCID as our preferred RCID when conducting
74*e7be843bSPierre Pronchery  * the retry. This SCID must be enrolled using this function. May only be called
75*e7be843bSPierre Pronchery  * once. The added RCID has no sequence number associated with it as it is
76*e7be843bSPierre Pronchery  * essentially a new ODCID (hereafter a Retry ODCID).
77*e7be843bSPierre Pronchery  *
78*e7be843bSPierre Pronchery  * Not for server use.
79*e7be843bSPierre Pronchery  */
80*e7be843bSPierre Pronchery int ossl_quic_rcidm_add_from_server_retry(QUIC_RCIDM *rcidm,
81*e7be843bSPierre Pronchery                                           const QUIC_CONN_ID *retry_odcid);
82*e7be843bSPierre Pronchery 
83*e7be843bSPierre Pronchery /*
84*e7be843bSPierre Pronchery  * Processes an incoming NEW_CONN_ID frame, recording the new CID as a potential
85*e7be843bSPierre Pronchery  * RCID. The RCIDM retirement mechanism is ratcheted according to the
86*e7be843bSPierre Pronchery  * ncid->retire_prior_to field. The stateless_reset field is ignored; the caller
87*e7be843bSPierre Pronchery  * is responsible for handling it separately.
88*e7be843bSPierre Pronchery  */
89*e7be843bSPierre Pronchery int ossl_quic_rcidm_add_from_ncid(QUIC_RCIDM *rcidm,
90*e7be843bSPierre Pronchery                                   const OSSL_QUIC_FRAME_NEW_CONN_ID *ncid);
91*e7be843bSPierre Pronchery 
92*e7be843bSPierre Pronchery /*
93*e7be843bSPierre Pronchery  * Other Events
94*e7be843bSPierre Pronchery  * ============
95*e7be843bSPierre Pronchery  */
96*e7be843bSPierre Pronchery 
97*e7be843bSPierre Pronchery /*
98*e7be843bSPierre Pronchery  * Notifies the RCIDM that the handshake for a connection is complete.
99*e7be843bSPierre Pronchery  * Should only be called once; further calls are ignored.
100*e7be843bSPierre Pronchery  *
101*e7be843bSPierre Pronchery  * This may influence the RCIDM's RCID change policy.
102*e7be843bSPierre Pronchery  */
103*e7be843bSPierre Pronchery void ossl_quic_rcidm_on_handshake_complete(QUIC_RCIDM *rcidm);
104*e7be843bSPierre Pronchery 
105*e7be843bSPierre Pronchery /*
106*e7be843bSPierre Pronchery  * Notifies the RCIDM that one or more packets have been sent.
107*e7be843bSPierre Pronchery  *
108*e7be843bSPierre Pronchery  * This may influence the RCIDM's RCID change policy.
109*e7be843bSPierre Pronchery  */
110*e7be843bSPierre Pronchery void ossl_quic_rcidm_on_packet_sent(QUIC_RCIDM *rcidm, uint64_t num_packets);
111*e7be843bSPierre Pronchery 
112*e7be843bSPierre Pronchery /*
113*e7be843bSPierre Pronchery  * Manually request switching to a new RCID as soon as possible.
114*e7be843bSPierre Pronchery  */
115*e7be843bSPierre Pronchery void ossl_quic_rcidm_request_roll(QUIC_RCIDM *rcidm);
116*e7be843bSPierre Pronchery 
117*e7be843bSPierre Pronchery /*
118*e7be843bSPierre Pronchery  * Queries
119*e7be843bSPierre Pronchery  * =======
120*e7be843bSPierre Pronchery  */
121*e7be843bSPierre Pronchery 
122*e7be843bSPierre Pronchery /*
123*e7be843bSPierre Pronchery  * The RCIDM decides when it will never use a given RCID again. When it does
124*e7be843bSPierre Pronchery  * this, it outputs the sequence number of that RCID using this function, which
125*e7be843bSPierre Pronchery  * pops from a logical queue of retired RCIDs. The caller is responsible
126*e7be843bSPierre Pronchery  * for polling this function and generating Retire CID frames from the result.
127*e7be843bSPierre Pronchery  *
128*e7be843bSPierre Pronchery  * If nothing needs doing and the queue is empty, this function returns 0. If
129*e7be843bSPierre Pronchery  * there is an RCID which needs retiring, the sequence number of that RCID is
130*e7be843bSPierre Pronchery  * written to *seq_num (if seq_num is non-NULL) and this function returns 1. The
131*e7be843bSPierre Pronchery  * queue entry is popped (and the caller is thus assumed to have taken
132*e7be843bSPierre Pronchery  * responsibility for transmitting the necessary Retire CID frame).
133*e7be843bSPierre Pronchery  *
134*e7be843bSPierre Pronchery  * Note that the caller should not transmit a Retire CID frame immediately as
135*e7be843bSPierre Pronchery  * packets using the RCID may still be in flight. The caller must determine an
136*e7be843bSPierre Pronchery  * appropriate delay using knowledge of network conditions (RTT, etc.) which is
137*e7be843bSPierre Pronchery  * outside the scope of the RCIDM. The caller is responsible for implementing
138*e7be843bSPierre Pronchery  * this delay based on the last time a packet was transmitted using the RCID
139*e7be843bSPierre Pronchery  * being retired.
140*e7be843bSPierre Pronchery  */
141*e7be843bSPierre Pronchery int ossl_quic_rcidm_pop_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
142*e7be843bSPierre Pronchery 
143*e7be843bSPierre Pronchery /*
144*e7be843bSPierre Pronchery  * Like ossl_quic_rcidm_pop_retire_seq_num, but does not pop the item from the
145*e7be843bSPierre Pronchery  * queue. If this call succeeds, the next call to
146*e7be843bSPierre Pronchery  * ossl_quic_rcidm_pop_retire_seq_num is guaranteed to output the same sequence
147*e7be843bSPierre Pronchery  * number.
148*e7be843bSPierre Pronchery  */
149*e7be843bSPierre Pronchery int ossl_quic_rcidm_peek_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
150*e7be843bSPierre Pronchery 
151*e7be843bSPierre Pronchery /*
152*e7be843bSPierre Pronchery  * Writes the DCID preferred for a newly transmitted packet at this time to
153*e7be843bSPierre Pronchery  * *tx_dcid. This function should be called to determine what DCID to use when
154*e7be843bSPierre Pronchery  * transmitting a packet to the peer. The RCIDM may implement arbitrary policy
155*e7be843bSPierre Pronchery  * to decide when to change the preferred RCID.
156*e7be843bSPierre Pronchery  *
157*e7be843bSPierre Pronchery  * Returns 1 on success and 0 on failure.
158*e7be843bSPierre Pronchery  */
159*e7be843bSPierre Pronchery int ossl_quic_rcidm_get_preferred_tx_dcid(QUIC_RCIDM *rcidm,
160*e7be843bSPierre Pronchery                                           QUIC_CONN_ID *tx_dcid);
161*e7be843bSPierre Pronchery 
162*e7be843bSPierre Pronchery /*
163*e7be843bSPierre Pronchery  * Returns 1 if the value output by ossl_quic_rcidm_get_preferred_tx_dcid() has
164*e7be843bSPierre Pronchery  * changed since the last call to this function with clear set. If clear is set,
165*e7be843bSPierre Pronchery  * clears the changed flag. Returns the old value of the changed flag.
166*e7be843bSPierre Pronchery  */
167*e7be843bSPierre Pronchery int ossl_quic_rcidm_get_preferred_tx_dcid_changed(QUIC_RCIDM *rcidm,
168*e7be843bSPierre Pronchery                                                   int clear);
169*e7be843bSPierre Pronchery 
170*e7be843bSPierre Pronchery /*
171*e7be843bSPierre Pronchery  * Returns the number of active numbered RCIDs we have. Note that this includes
172*e7be843bSPierre Pronchery  * RCIDs on the retir*ing* queue accessed via
173*e7be843bSPierre Pronchery  * ossl_quic_rcidm_pop_retire_seq_num() as these are still active until actually
174*e7be843bSPierre Pronchery  * retired.
175*e7be843bSPierre Pronchery  */
176*e7be843bSPierre Pronchery size_t ossl_quic_rcidm_get_num_active(const QUIC_RCIDM *rcidm);
177*e7be843bSPierre Pronchery 
178*e7be843bSPierre Pronchery /*
179*e7be843bSPierre Pronchery  * Returns the number of retir*ing* numbered RCIDs we have.
180*e7be843bSPierre Pronchery  */
181*e7be843bSPierre Pronchery size_t ossl_quic_rcidm_get_num_retiring(const QUIC_RCIDM *rcidm);
182*e7be843bSPierre Pronchery 
183*e7be843bSPierre Pronchery # endif
184*e7be843bSPierre Pronchery 
185*e7be843bSPierre Pronchery #endif
186