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