lsquic_enc_sess.h revision 03e6b668
1/* Copyright (c) 2017 - 2019 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    HS_DELAYED = 3,
55    HS_PK_OFFLOAD = 4,
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    enum enc_packout
106    (*esf_encrypt_packet) (enc_session_t *, const struct lsquic_engine_public *,
107        struct lsquic_conn *, struct lsquic_packet_out *);
108
109    enum dec_packin
110    (*esf_decrypt_packet)(enc_session_t *, struct lsquic_engine_public *,
111        const struct lsquic_conn *, struct lsquic_packet_in *);
112
113    struct stack_st_X509 *
114    (*esf_get_server_cert_chain) (enc_session_t *);
115
116    int
117    (*esf_verify_reset_token) (enc_session_t *, const unsigned char *, size_t);
118
119    int
120    (*esf_did_zero_rtt_succeed) (enc_session_t *);
121
122    int
123    (*esf_is_zero_rtt_enabled) (enc_session_t *);
124
125    unsigned
126    esf_tag_len;
127};
128
129struct enc_session_funcs_gquic
130{
131#if LSQUIC_KEEP_ENC_SESS_HISTORY
132    /* Grab encryption session history */
133    void (*esf_get_hist) (enc_session_t *,
134                                            char buf[ESHIST_STR_SIZE]);
135#endif
136
137    /* Destroy enc session */
138    void (*esf_destroy)(enc_session_t *enc_session);
139
140    /* Return true if handshake has been completed */
141    int (*esf_is_hsk_done)(enc_session_t *enc_session);
142
143    /* Get value of setting specified by `tag' */
144    int (*esf_get_peer_setting) (enc_session_t *, uint32_t tag,
145                                                                uint32_t *val);
146
147    /* Get value of peer option (that from COPT array) */
148    int (*esf_get_peer_option) (enc_session_t *enc_session,
149                                                                uint32_t tag);
150
151    /* Create server session */
152    enc_session_t *
153    (*esf_create_server) (lsquic_cid_t cid, const struct lsquic_engine_public *);
154
155    /* out_len should have init value as the max length of out */
156    enum handshake_error
157    (*esf_handle_chlo) (enc_session_t *enc_session, enum lsquic_version,
158                const uint8_t *in, int in_len, time_t t,
159                const struct sockaddr *ip_addr, const struct sockaddr *local,
160                uint8_t *out, size_t *out_len,
161                uint8_t nonce[DNONC_LENGTH], int *nonce_set);
162
163    void (*esf_hsk_destroy)(void *hsk_ctx);
164
165#ifndef NDEBUG
166    /* Need to expose this function for testing */
167    int (*esf_determine_diversification_key) (enc_session_t *,
168                              uint8_t *diversification_nonce, int is_client);
169#endif
170
171    const char *
172    (*esf_get_ua) (enc_session_t *);
173
174    int
175    (*esf_have_key_gt_one) (enc_session_t *enc_session);
176
177#ifndef NDEBUG
178    /* Functions that are only relevant in maintest.  We may want to get rid
179     * of them somehow and only use the public API to test.
180     */
181
182    uint8_t
183    (*esf_have_key) (enc_session_t *);
184
185    void
186    (*esf_set_have_key) (enc_session_t *, uint8_t);
187
188    const unsigned char *
189    (*esf_get_enc_key_i) (enc_session_t *);
190
191    const unsigned char *
192    (*esf_get_dec_key_i) (enc_session_t *);
193
194    const unsigned char *
195    (*esf_get_enc_key_nonce_i) (enc_session_t *);
196
197    const unsigned char *
198    (*esf_get_dec_key_nonce_i) (enc_session_t *);
199
200    const unsigned char *
201    (*esf_get_enc_key_nonce_f) (enc_session_t *);
202
203    const unsigned char *
204    (*esf_get_dec_key_nonce_f) (enc_session_t *);
205#endif /* !defined(NDEBUG) */
206
207#if LSQUIC_ENABLE_HANDSHAKE_DISABLE
208    void
209    (*esf_set_handshake_completed) (enc_session_t *);
210#endif
211
212    /* Create client session */
213    enc_session_t *
214    (*esf_create_client) (const char *domain, lsquic_cid_t cid,
215                                    const struct lsquic_engine_public *,
216                                    const unsigned char *, size_t);
217
218    /* -1 error, 0, OK, response in `buf' */
219    int
220    (*esf_gen_chlo) (enc_session_t *, enum lsquic_version,
221                                                uint8_t *buf, size_t *len);
222
223    int
224    (*esf_handle_chlo_reply) (enc_session_t *,
225                                                const uint8_t *data, int len);
226
227    size_t
228    (*esf_mem_used)(enc_session_t *);
229
230    /* Zero-rtt serialization needs the knowledge of the QUIC version, that's
231     * why there is a separate method for thus.  Plus, we want to be able to
232     * call it after the "handshake is done" callback is called.
233     */
234    void (*esf_maybe_dispatch_zero_rtt) (enc_session_t *,
235            struct lsquic_conn *conn,
236            void (*cb)(struct lsquic_conn *, const unsigned char *, size_t));
237
238    void (*esf_reset_cid) (enc_session_t *, const lsquic_cid_t *);
239};
240
241enum iquic_handshake_status {
242    IHS_WANT_READ,
243    IHS_WANT_WRITE,
244    IHS_STOP,
245};
246
247struct crypto_stream_if
248{
249    ssize_t     (*csi_write) (void *stream, const void *buf, size_t len);
250    int         (*csi_flush) (void *stream);
251    ssize_t     (*csi_readf) (void *stream,
252        size_t (*readf)(void *, const unsigned char *, size_t, int), void *ctx);
253    int         (*csi_wantwrite) (void *stream, int is_want);
254    int         (*csi_wantread) (void *stream, int is_want);
255    enum enc_level
256                (*csi_enc_level) (void *stream);
257};
258
259struct enc_session_funcs_iquic
260{
261    enc_session_t *
262    (*esfi_create_client) (const char *domain, struct lsquic_engine_public *,
263                           struct lsquic_conn *, const struct lsquic_cid *,
264                           const struct ver_neg *, void *(crypto_streams)[4],
265                           const struct crypto_stream_if *,
266                           const unsigned char *, size_t,
267                           struct lsquic_alarmset *, unsigned);
268
269    void
270    (*esfi_destroy) (enc_session_t *);
271
272    struct ssl_st *
273    (*esfi_get_ssl) (enc_session_t *);
274
275    struct transport_params *
276    (*esfi_get_peer_transport_params) (enc_session_t *);
277
278    int
279    (*esfi_reset_dcid) (enc_session_t *, const struct lsquic_cid *,
280                                                const struct lsquic_cid *);
281
282    int
283    (*esfi_init_server) (enc_session_t *);
284
285    void
286    (*esfi_set_conn) (enc_session_t *, struct lsquic_conn *);
287
288    void
289    (*esfi_set_streams) (enc_session_t *, void *(crypto_streams)[4],
290                           const struct crypto_stream_if *);
291
292    enc_session_t *
293    (*esfi_create_server) (struct lsquic_engine_public *, struct lsquic_conn *,
294                                                    const struct lsquic_cid *,
295                           void *(crypto_streams)[4],
296                           const struct crypto_stream_if *,
297                           const struct lsquic_cid *odcid);
298
299    void
300    (*esfi_shake_stream)(enc_session_t *, struct lsquic_stream *,
301                         const char *);
302
303    void
304    (*esfi_1rtt_acked)(enc_session_t *);
305};
306
307extern
308#ifdef NDEBUG
309const
310#endif
311struct enc_session_funcs_common lsquic_enc_session_common_gquic_1;
312extern const struct enc_session_funcs_common lsquic_enc_session_common_ietf_v1;
313
314extern
315#ifdef NDEBUG
316const
317#endif
318struct enc_session_funcs_gquic lsquic_enc_session_gquic_gquic_1;
319
320extern const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1;
321
322#define select_esf_common_by_ver(ver) ( \
323    ver == LSQVER_ID23 ? &lsquic_enc_session_common_ietf_v1 : \
324    ver == LSQVER_ID24 ? &lsquic_enc_session_common_ietf_v1 : \
325    ver == LSQVER_VERNEG ? &lsquic_enc_session_common_ietf_v1 : \
326    &lsquic_enc_session_common_gquic_1 )
327
328#define select_esf_gquic_by_ver(ver) ( \
329    ver ? &lsquic_enc_session_gquic_gquic_1 : &lsquic_enc_session_gquic_gquic_1)
330
331#define select_esf_iquic_by_ver(ver) ( \
332    ver ? &lsquic_enc_session_iquic_ietf_v1 : &lsquic_enc_session_iquic_ietf_v1)
333
334extern const char *const lsquic_enclev2str[];
335
336extern const struct lsquic_stream_if lsquic_cry_sm_if;
337
338extern const struct lsquic_stream_if lsquic_mini_cry_sm_if;
339
340/* RFC 7301, Section 3.2 */
341#define ALERT_NO_APPLICATION_PROTOCOL 120
342
343enum lsquic_version
344lsquic_zero_rtt_version (const unsigned char *, size_t);
345
346/* This is seems to be true for all of the ciphers used by IETF QUIC.
347 * XXX: Perhaps add a check?
348 */
349#define IQUIC_TAG_LEN 16
350
351#endif
352