Line data Source code
1 : #ifndef HEADER_fd_src_waltz_quic_crypto_fd_quic_crypto_suites_h
2 : #define HEADER_fd_src_waltz_quic_crypto_fd_quic_crypto_suites_h
3 :
4 : #include "../fd_quic_enum.h"
5 : #include "../../../ballet/aes/fd_aes_gcm.h"
6 :
7 : /* Defines the crypto suites used by QUIC v1.
8 :
9 : QUIC v2 is defined here:
10 : https://www.rfc-editor.org/rfc/rfc9001.html#name-header-protection
11 : https://www.rfc-editor.org/rfc/rfc8446.html#page-133
12 :
13 : The suites are defined thusly:
14 :
15 : +------------------------------+-------------+
16 : | Description | Value |
17 : +------------------------------+-------------+
18 : | TLS_AES_128_GCM_SHA256 | {0x13,0x01} |
19 : | TLS_AES_256_GCM_SHA384 | {0x13,0x02} |
20 : | TLS_CHACHA20_POLY1305_SHA256 | {0x13,0x03} |
21 : | TLS_AES_128_CCM_SHA256 | {0x13,0x04} |
22 : | TLS_AES_128_CCM_8_SHA256 | {0x13,0x05} |
23 : +------------------------------+-------------+
24 :
25 : Notes:
26 : TLS_AES_128_CCM_SHA256 does not seem to be mentioned in rfc9001, so is excluded
27 : TLS_AES_128_CCM_8_SHA256 has no packet-header encryption defined, and so must be excluded
28 :
29 : The remainder are defined below */
30 :
31 : typedef struct fd_quic_crypto_keys fd_quic_crypto_keys_t;
32 : typedef struct fd_quic_crypto_secrets fd_quic_crypto_secrets_t;
33 :
34 125081379 : #define FD_QUIC_CRYPTO_TAG_SZ 16
35 13845961 : #define FD_QUIC_CRYPTO_SAMPLE_SZ 16
36 13845961 : #define FD_QUIC_CRYPTO_SAMPLE_OFFSET_FROM_PKT_NUM_START 4
37 :
38 : struct fd_quic_crypto_keys {
39 : /* packet protection: */
40 : uchar pkt_key[FD_AES_128_KEY_SZ];
41 : uchar iv [FD_AES_GCM_IV_SZ ];
42 : uchar hp_key [FD_AES_128_KEY_SZ];
43 : };
44 :
45 : /* define enums for encryption levels */
46 106891602 : #define fd_quic_enc_level_initial_id 0
47 : #define fd_quic_enc_level_early_data_id 1
48 106250305 : #define fd_quic_enc_level_handshake_id 2
49 203671418 : #define fd_quic_enc_level_appdata_id 3
50 : #define FD_QUIC_NUM_ENC_LEVELS 4
51 :
52 : /* labels defined in rfc9001 */
53 24588 : #define FD_QUIC_CRYPTO_LABEL_CLIENT_IN "client in"
54 24588 : #define FD_QUIC_CRYPTO_LABEL_SERVER_IN "server in"
55 :
56 193920 : #define FD_QUIC_CRYPTO_LABEL_QUIC_KEY "quic key"
57 193920 : #define FD_QUIC_CRYPTO_LABEL_QUIC_IV "quic iv"
58 145416 : #define FD_QUIC_CRYPTO_LABEL_QUIC_HP "quic hp"
59 :
60 48504 : #define FD_QUIC_CRYPTO_LABEL_KEY_UPDATE "quic ku"
61 :
62 : /* each of these has "-1" to avoid counting the implied terminating NUL byte */
63 12294 : #define FD_QUIC_CRYPTO_LABEL_CLIENT_IN_LEN ( sizeof( FD_QUIC_CRYPTO_LABEL_CLIENT_IN ) - 1 )
64 12294 : #define FD_QUIC_CRYPTO_LABEL_SERVER_IN_LEN ( sizeof( FD_QUIC_CRYPTO_LABEL_SERVER_IN ) - 1 )
65 :
66 96960 : #define FD_QUIC_CRYPTO_LABEL_QUIC_KEY_LEN ( sizeof( FD_QUIC_CRYPTO_LABEL_QUIC_KEY ) - 1 )
67 96960 : #define FD_QUIC_CRYPTO_LABEL_QUIC_IV_LEN ( sizeof( FD_QUIC_CRYPTO_LABEL_QUIC_IV ) - 1 )
68 72708 : #define FD_QUIC_CRYPTO_LABEL_QUIC_HP_LEN ( sizeof( FD_QUIC_CRYPTO_LABEL_QUIC_HP ) - 1 )
69 :
70 24252 : #define FD_QUIC_CRYPTO_LABEL_KEY_UPDATE_LEN ( sizeof( FD_QUIC_CRYPTO_LABEL_KEY_UPDATE ) - 1 )
71 :
72 : struct fd_quic_crypto_secrets {
73 : uchar initial_secret[FD_QUIC_INITIAL_SECRET_SZ];
74 :
75 : /* secret[enc_level][dir][FD_QUIC_SECRET_SZ]
76 : a secret for each encryption level,
77 : and each direction (dir=0 is incoming, dir=1 is outgoing) */
78 : uchar secret[FD_QUIC_NUM_ENC_LEVELS][2][FD_QUIC_SECRET_SZ];
79 :
80 : /* new secret for switching keys during key update */
81 : uchar new_secret[2][FD_QUIC_SECRET_SZ];
82 : };
83 :
84 : /* fd_quic_gen_initial_secrets generates initial secrets for the given conn ID.
85 : Does not generate keys. Sets secrets->initial_secrets, secrets->secret[0][0],
86 : (incoming secret) and secret->secret[0][1] (outgoing secret). is_server is
87 : 1 if the current QUIC instance runs from the perspective of the server, 0
88 : otherwise.
89 :
90 : Key schedule:
91 :
92 : initial_salt (hardcoded constant)
93 : |
94 : v
95 : initial_secret = HKDF-Extract(.,conn_id)
96 : |
97 : +---> initial_client_secret = HKDF-Expand-Label(., "client in", "", 32)
98 : |
99 : +---> initial_server_secret = HKDF-Expand-Label(., "server in", "", 32) */
100 :
101 : void
102 : fd_quic_gen_initial_secrets(
103 : fd_quic_crypto_secrets_t * secrets,
104 : uchar const * conn_id,
105 : ulong conn_id_sz,
106 : int is_server );
107 :
108 : /* fd_quic_gen_keys derives the IV, a header protection key, and a packet
109 : protection key from a secret. Thus *keys is fully initialized. This
110 : function is called twice per encryption level (for incoming and for
111 : outgoing keys).
112 :
113 : Key schedule:
114 :
115 : secret
116 : |
117 : +---> header protection key = HKDF-Expand-Label(.,"quic-hp")
118 : +---> packet protection IV = HKDF-Expand-Label(.,"quic-iv")
119 : +---> packet protection key = HKDF-Expand-Label(.,"quic-key") */
120 :
121 : void
122 : fd_quic_gen_keys(
123 : fd_quic_crypto_keys_t * keys,
124 : uchar const secret[ 32 ] );
125 :
126 : /* fd_quic_key_update_derive derives the IVs and packet protection keys
127 : for the next key update. Header protection keys are not updated.
128 : Key updates are periodic key rotations that some QUIC peers do out of
129 : caution. Key updates are deterministic and can be computed infinitely
130 : far in advance if the client and server secrets are known.
131 :
132 : Key schedule:
133 :
134 : client/server secret n
135 : |
136 : v
137 : client/server secret n+1 = HKDF-Expand-Label(.,"quic-ku")
138 : |
139 : +---> server packet protection IV = HKDF-Expand-Label(.,"quic-iv")
140 : +---> server packet protection key = HKDF-Expand-Label(.,"quic-key") */
141 :
142 : void
143 : fd_quic_key_update_derive( fd_quic_crypto_secrets_t * secrets,
144 : fd_quic_crypto_keys_t new_keys[2] );
145 :
146 :
147 : /* encrypt a packet according to rfc9001 packet protection and header protection
148 :
149 : may fail in the following scenarios:
150 : the receiving buffer is too small
151 : the decryption functions report failure (fd_tls)
152 :
153 : returns
154 : FD_QUIC_SUCCESS if the operation succeeded
155 : FD_QUIC_FAILED otherwise
156 :
157 : args
158 : out destination for the full packet
159 : out_sz size of the output buffer, and also returned size of the written bytes
160 : hdr the input plain text header
161 : hdr_sz the size of the input header
162 : pkt the input plain text payload
163 : pkt_sz the size of the input payload
164 : keys the keys to use
165 : */
166 : int
167 : fd_quic_crypto_encrypt(
168 : uchar * const out,
169 : ulong * const out_sz,
170 : uchar const * const hdr,
171 : ulong const hdr_sz,
172 : uchar const * const pkt,
173 : ulong const pkt_sz,
174 : fd_quic_crypto_keys_t const * const pkt_keys,
175 : fd_quic_crypto_keys_t const * const hp_keys,
176 : ulong const pkt_number );
177 :
178 :
179 : /* decrypt a quic protected packet
180 :
181 : may fail in the following scenarios:
182 : the receiving buffer is too small
183 : the decryption functions report failure (fd_tls)
184 : the decrypted data is corrupt
185 :
186 : returns
187 : FD_QUIC_SUCCESS if the operation succeeded
188 : FD_QUIC_FAILED otherwise
189 :
190 : args
191 : buf buffer containing a QUIC packet with a decrypted
192 : header, and encrypted payload, and the auth tag
193 : of size FD_QUIC_CRYPTO_TAG_SZ. On return, the
194 : payload will be decrypted.
195 : buf_sz the size of the QUIC packet
196 : pkt_number_off the offset of the packet number within the cipher text
197 : this must be determined from unprotected header data
198 : keys the keys needed to decrypt */
199 :
200 : int
201 : fd_quic_crypto_decrypt(
202 : uchar * buf,
203 : ulong buf_sz,
204 : ulong pkt_number_off,
205 : ulong pkt_number,
206 : fd_quic_crypto_keys_t const * keys );
207 :
208 :
209 : /* decrypt a quic protected packet header
210 :
211 : this removes header protection (HP)
212 :
213 : may fail in the following scenarios:
214 : the receiving buffer is too small
215 : the decryption functions report failure (fd_tls)
216 : the decrypted data is corrupt
217 :
218 : returns
219 : FD_QUIC_SUCCESS if the operation succeeded
220 : FD_QUIC_FAILED otherwise
221 :
222 : args
223 : buf buffer containing an encrypted QUIC packet.
224 : On return, the header is decrypted, the rest
225 : still encrypted
226 : buf_sz size of the QUIC packet
227 : pkt_number_off the offset of the packet number within the cipher text
228 : this must be determined from unprotected header data
229 : keys the keys needed to decrypt */
230 :
231 : int
232 : fd_quic_crypto_decrypt_hdr(
233 : uchar * buf,
234 : ulong buf_sz,
235 : ulong pkt_number_off,
236 : fd_quic_crypto_keys_t const * keys );
237 :
238 : /* nonce is quic-iv XORed with 62-bits of byte-order packet-number */
239 : static inline void
240 : fd_quic_get_nonce(
241 : uchar * nonce,
242 : uchar const * iv,
243 39686132 : ulong pkt_number ) {
244 39686132 : #define MASK_LOWER_62 0x3fffffffffffffffu
245 39686132 : memcpy( nonce, iv, 4 );
246 39686132 : FD_STORE( ulong, nonce + 4, FD_LOAD( ulong, iv + 4 ) ^ fd_ulong_bswap( pkt_number & MASK_LOWER_62 ) );
247 39686132 : #undef MASK_LOWER_62
248 39686132 : }
249 :
250 : #endif /* HEADER_fd_src_waltz_quic_crypto_fd_quic_crypto_suites_h */
|