1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2#ifndef LSQUIC_ENC_SESS_H
3#define LSQUIC_ENC_SESS_H 1
4
5#include "lsquic_shared_support.h"
6
7struct lsquic_alarmset;
8struct lsquic_engine_public;
9struct lsquic_packet_out;
10struct lsquic_packet_in;
11struct stream_wrapper;
12struct ver_neg;
13struct lsquic_conn;
14struct transport_params;
15struct lsquic_cid;
16struct ssl_stream_method_st;
17struct ssl_st;
18struct sockaddr;
19struct conn_cid_elem;
20struct lsquic_engine_settings;
21enum lsquic_version;
22
23#define DNONC_LENGTH 32
24#define SRST_LENGTH 16
25
26/* From [draft-ietf-quic-tls-14]:
27 *
28 * Data is protected using a number of encryption levels:
29 *
30 * o  Plaintext
31 *
32 * o  Early Data (0-RTT) Keys
33 *
34 * o  Handshake Keys
35 *
36 * o  Application Data (1-RTT) Keys
37 */
38
39/* This enum maps to the list above */
40enum enc_level
41{
42    ENC_LEV_CLEAR,
43    ENC_LEV_EARLY,
44    ENC_LEV_INIT,
45    ENC_LEV_FORW,
46    N_ENC_LEVS
47};
48
49enum handshake_error            /* TODO: rename this enum */
50{
51    DATA_NOT_ENOUGH = -2,
52    DATA_FORMAT_ERROR = -1,
53    HS_ERROR = -1,
54    DATA_NO_ERROR = 0,
55    HS_SHLO = 0,
56    HS_1RTT = 1,
57    HS_SREJ = 2,
58};
59
60#ifndef LSQUIC_KEEP_ENC_SESS_HISTORY
61#   ifndef NDEBUG
62#       define LSQUIC_KEEP_ENC_SESS_HISTORY 1
63#   else
64#       define LSQUIC_KEEP_ENC_SESS_HISTORY 0
65#   endif
66#endif
67
68#if LSQUIC_KEEP_ENC_SESS_HISTORY
69#define ESHIST_BITS 7
70#define ESHIST_MASK ((1 << ESHIST_BITS) - 1)
71#define ESHIST_STR_SIZE ((1 << ESHIST_BITS) + 1)
72#endif
73
74enum enc_packout { ENCPA_OK, ENCPA_NOMEM, ENCPA_BADCRYPT, };
75
76enum dec_packin {
77    DECPI_OK,
78    DECPI_NOMEM,
79    DECPI_TOO_SHORT,
80    DECPI_NOT_YET,
81    DECPI_BADCRYPT,
82    DECPI_VIOLATION,
83};
84
85typedef void enc_session_t;
86
87struct enc_session_funcs_common
88{
89    /* Global initialization: call once per implementation */
90    int (*esf_global_init)(int flags);
91
92    /* Global cleanup: call once per implementation */
93    void (*esf_global_cleanup) (void);
94
95    const char *
96    (*esf_cipher) (enc_session_t *);
97
98    int
99    (*esf_keysize) (enc_session_t *);
100
101    int
102    (*esf_alg_keysize) (enc_session_t *);
103
104    const char *
105    (*esf_get_sni) (enc_session_t *);
106
107    /* Need to pass lconn in encrypt and decrypt methods because enc_session
108     * is allowed to be NULL for gQUIC.
109     */
110    enum enc_packout
111    (*esf_encrypt_packet) (enc_session_t *, const struct lsquic_engine_public *,
112        struct lsquic_conn *, struct lsquic_packet_out *);
113
114    enum dec_packin
115    (*esf_decrypt_packet)(enc_session_t *, struct lsquic_engine_public *,
116        const struct lsquic_conn *, struct lsquic_packet_in *);
117
118    struct stack_st_X509 *
119    (*esf_get_server_cert_chain) (enc_session_t *);
120
121    int
122    (*esf_verify_reset_token) (enc_session_t *, const unsigned char *, size_t);
123
124    int
125    (*esf_did_sess_resume_succeed) (enc_session_t *);
126
127    int
128    (*esf_is_sess_resume_enabled) (enc_session_t *);
129
130    void
131    (*esf_set_conn) (enc_session_t *, struct lsquic_conn *);
132
133    /* Optional.  This function gets called after packets are encrypted,
134     * batched, and are about to be sent.
135     */
136    void
137    (*esf_flush_encryption) (enc_session_t *);
138
139    unsigned
140    esf_tag_len;
141};
142
143struct enc_session_funcs_gquic
144{
145#if LSQUIC_KEEP_ENC_SESS_HISTORY
146    /* Grab encryption session history */
147    void (*esf_get_hist) (enc_session_t *,
148                                            char buf[ESHIST_STR_SIZE]);
149#endif
150
151    /* Destroy enc session */
152    void (*esf_destroy)(enc_session_t *enc_session);
153
154    /* Return true if handshake has been completed */
155    int (*esf_is_hsk_done)(enc_session_t *enc_session);
156
157    /* Get value of setting specified by `tag' */
158    int (*esf_get_peer_setting) (enc_session_t *, uint32_t tag,
159                                                                uint32_t *val);
160
161    /* Get value of peer option (that from COPT array) */
162    int (*esf_get_peer_option) (enc_session_t *enc_session,
163                                                                uint32_t tag);
164
165    /* Create server session */
166    enc_session_t *
167    (*esf_create_server) (struct lsquic_conn *,
168                        lsquic_cid_t cid, struct lsquic_engine_public *);
169
170    /* out_len should have init value as the max length of out */
171    enum handshake_error
172    (*esf_handle_chlo) (enc_session_t *enc_session, enum lsquic_version,
173                const uint8_t *in, int in_len, time_t t,
174                const struct sockaddr *ip_addr, const struct sockaddr *local,
175                uint8_t *out, size_t *out_len,
176                uint8_t nonce[DNONC_LENGTH], int *nonce_set);
177
178    void (*esf_hsk_destroy)(void *hsk_ctx);
179
180#ifndef NDEBUG
181    /* Need to expose this function for testing */
182    int (*esf_determine_diversification_key) (enc_session_t *,
183                              uint8_t *diversification_nonce);
184#endif
185
186    const char *
187    (*esf_get_ua) (enc_session_t *);
188
189    int
190    (*esf_have_key_gt_one) (enc_session_t *enc_session);
191
192#ifndef NDEBUG
193    /* Functions that are only relevant in maintest.  We may want to get rid
194     * of them somehow and only use the public API to test.
195     */
196
197    uint8_t
198    (*esf_have_key) (enc_session_t *);
199
200    void
201    (*esf_set_have_key) (enc_session_t *, uint8_t);
202
203    const unsigned char *
204    (*esf_get_enc_key_i) (enc_session_t *);
205
206    const unsigned char *
207    (*esf_get_dec_key_i) (enc_session_t *);
208
209    const unsigned char *
210    (*esf_get_enc_key_nonce_i) (enc_session_t *);
211
212    const unsigned char *
213    (*esf_get_dec_key_nonce_i) (enc_session_t *);
214
215    const unsigned char *
216    (*esf_get_enc_key_nonce_f) (enc_session_t *);
217
218    const unsigned char *
219    (*esf_get_dec_key_nonce_f) (enc_session_t *);
220#endif /* !defined(NDEBUG) */
221
222    /* Create client session */
223    enc_session_t *
224    (*esf_create_client) (struct lsquic_conn *, const char *domain,
225                            lsquic_cid_t cid,
226                                    struct lsquic_engine_public *,
227                                    const unsigned char *, size_t);
228
229    /* -1 error, 0, OK, response in `buf' */
230    int
231    (*esf_gen_chlo) (enc_session_t *, enum lsquic_version,
232                                                uint8_t *buf, size_t *len);
233
234    int
235    (*esf_handle_chlo_reply) (enc_session_t *,
236                                                const uint8_t *data, int len);
237
238    size_t
239    (*esf_mem_used)(enc_session_t *);
240
241    /* Session resumption serialization needs the knowledge of the QUIC
242     * version, that's why there is a separate method for thus.  Plus, we
243     * want to be able to call it after the "handshake is done" callback
244     * is called.
245     */
246    void (*esf_maybe_dispatch_sess_resume) (enc_session_t *,
247            void (*cb)(struct lsquic_conn *, const unsigned char *, size_t));
248
249    void (*esf_reset_cid) (enc_session_t *, const lsquic_cid_t *);
250};
251
252struct crypto_stream_if
253{
254    ssize_t     (*csi_write) (void *stream, const void *buf, size_t len);
255    int         (*csi_flush) (void *stream);
256    ssize_t     (*csi_readf) (void *stream,
257        size_t (*readf)(void *, const unsigned char *, size_t, int), void *ctx);
258    int         (*csi_wantwrite) (void *stream, int is_want);
259    int         (*csi_wantread) (void *stream, int is_want);
260    enum enc_level
261                (*csi_enc_level) (void *stream);
262};
263
264struct enc_session_funcs_iquic
265{
266    enc_session_t *
267    (*esfi_create_client) (const char *domain, struct lsquic_engine_public *,
268                           struct lsquic_conn *, const struct lsquic_cid *,
269                           const struct ver_neg *, void *(crypto_streams)[4],
270                           const struct crypto_stream_if *,
271                           const unsigned char *, size_t,
272                           struct lsquic_alarmset *, unsigned, void*);
273
274    void
275    (*esfi_destroy) (enc_session_t *);
276
277    struct ssl_st *
278    (*esfi_get_ssl) (enc_session_t *);
279
280    struct transport_params *
281    (*esfi_get_peer_transport_params) (enc_session_t *);
282
283    int
284    (*esfi_reset_dcid) (enc_session_t *, const struct lsquic_cid *,
285                                                const struct lsquic_cid *);
286
287    void
288    (*esfi_set_iscid) (enc_session_t *, const struct lsquic_packet_in *);
289
290    int
291    (*esfi_init_server) (enc_session_t *);
292
293    void
294    (*esfi_set_streams) (enc_session_t *, void *(crypto_streams)[4],
295                           const struct crypto_stream_if *);
296
297    enc_session_t *
298    (*esfi_create_server) (struct lsquic_engine_public *, struct lsquic_conn *,
299                                                    const struct lsquic_cid *,
300                           void *(crypto_streams)[4],
301                           const struct crypto_stream_if *,
302                           const struct lsquic_cid *odcid,
303                           const struct lsquic_cid *iscid);
304
305    void
306    (*esfi_shake_stream)(enc_session_t *, struct lsquic_stream *,
307                         const char *);
308
309    void
310    (*esfi_handshake_confirmed)(enc_session_t *);
311
312    int
313    (*esfi_in_init)(enc_session_t *);
314
315    int
316    (*esfi_data_in)(enc_session_t *, enum enc_level,
317                                            const unsigned char *, size_t);
318};
319
320LSQUIC_EXTERN
321#ifdef NDEBUG
322const
323#endif
324struct enc_session_funcs_common lsquic_enc_session_common_gquic_1;
325
326LSQUIC_EXTERN
327#ifdef NDEBUG
328const
329#endif
330struct enc_session_funcs_common lsquic_enc_session_common_gquic_2;
331
332LSQUIC_EXTERN const struct enc_session_funcs_common lsquic_enc_session_common_ietf_v1;
333
334LSQUIC_EXTERN
335#ifdef NDEBUG
336const
337#endif
338struct enc_session_funcs_gquic lsquic_enc_session_gquic_gquic_1;
339
340LSQUIC_EXTERN const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1;
341
342#define select_esf_common_by_ver(ver) ( \
343    ver == LSQVER_ID27 ? &lsquic_enc_session_common_ietf_v1 : \
344    ver == LSQVER_ID29 ? &lsquic_enc_session_common_ietf_v1 : \
345    ver == LSQVER_I001 ? &lsquic_enc_session_common_ietf_v1 : \
346    ver == LSQVER_VERNEG ? &lsquic_enc_session_common_ietf_v1 : \
347    ver == LSQVER_050 ? &lsquic_enc_session_common_gquic_2 : \
348    &lsquic_enc_session_common_gquic_1 )
349
350#define select_esf_gquic_by_ver(ver) ( \
351    ver ? &lsquic_enc_session_gquic_gquic_1 : &lsquic_enc_session_gquic_gquic_1)
352
353#define select_esf_iquic_by_ver(ver) ( \
354    ver ? &lsquic_enc_session_iquic_ietf_v1 : &lsquic_enc_session_iquic_ietf_v1)
355
356extern const char *const lsquic_enclev2str[];
357
358LSQUIC_EXTERN const struct lsquic_stream_if lsquic_cry_sm_if;
359
360LSQUIC_EXTERN const struct lsquic_stream_if lsquic_mini_cry_sm_if;
361
362/* RFC 7301, Section 3.2 */
363#define ALERT_NO_APPLICATION_PROTOCOL 120
364
365enum lsquic_version
366lsquic_sess_resume_version (const unsigned char *, size_t);
367
368/* This is seems to be true for all of the ciphers used by IETF QUIC.
369 * XXX: Perhaps add a check?
370 */
371#define IQUIC_TAG_LEN 16
372
373/* Return number of bytes written to `buf' or -1 on error */
374int
375lsquic_enc_sess_ietf_gen_quic_ctx (
376                const struct lsquic_engine_settings *settings,
377                enum lsquic_version version, unsigned char *buf, size_t bufsz);
378
379#endif
380