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