lsquic_handshake.h revision 50aadb33
1/* Copyright (c) 2017 LiteSpeed Technologies Inc.  See LICENSE. */
2#ifndef LSQUIC_HANDSHAKE_H
3#define LSQUIC_HANDSHAKE_H
4
5#include <stdint.h>
6#include <openssl/base.h>
7#include <openssl/aead.h>
8
9#include <time.h>
10#include "lsquic_str.h"
11
12struct lsquic_engine_public;
13struct sockaddr;
14
15#include "lsquic_qtags.h"
16
17#define STK_LENGTH   60
18#define SNO_LENGTH   56
19#define SCID_LENGTH  16
20#define DNONC_LENGTH 32
21#define aes128_key_len 16
22#define aes128_iv_len 4
23
24/* client side, certs and hashs
25 */
26typedef struct cert_hash_item_st
27{
28    struct lsquic_str*   domain; /*with port, such as "xyz.com:8088" as the key */
29    struct lsquic_str*   crts;
30    struct lsquic_str*   hashs;
31    int         count;
32} cert_hash_item_t;
33
34enum handshake_error            /* TODO: rename this enum */
35{
36    DATA_NOT_ENOUGH = -2,
37    DATA_FORMAT_ERROR = -1,
38    HS_ERROR = -1,
39    DATA_NO_ERROR = 0,
40    HS_SHLO = 0,
41    HS_1RTT = 1,
42    HS_2RTT = 2,
43};
44
45enum handshake_state
46{
47    HSK_CHLO_REJ = 0,
48    HSK_SHLO,
49    HSK_COMPLETED,
50    N_HSK_STATES
51};
52
53typedef struct tag_value_st
54{
55    uint32_t    tag;
56    const char *      value;
57    int         len;
58} tag_value_t;
59
60typedef struct hs_ctx_st
61{
62    enum {
63        HSET_TCID     =   (1 << 0),     /* tcid is set */
64        HSET_SMHL     =   (1 << 1),     /* smhl is set */
65        HSET_SCID     =   (1 << 2),
66    }           set;
67    enum {
68        HOPT_NSTP     =   (1 << 0),     /* NSTP option present in COPT */
69        HOPT_SREJ     =   (1 << 1),     /* SREJ option present in COPT */
70    }           opts;
71    uint32_t    pdmd;
72    uint32_t    aead;
73    uint32_t    kexs;
74
75    uint32_t    mids;
76    uint32_t    scls;
77    uint32_t    cfcw;
78    uint32_t    sfcw;
79    uint32_t    srbf;
80    uint32_t    icsl;
81
82    uint32_t    irtt;
83    uint64_t    rcid;
84    uint32_t    tcid;
85    uint32_t    smhl;
86    uint64_t    ctim;  /* any usage? */
87    uint64_t    sttl;
88    unsigned char scid[SCID_LENGTH];
89    //unsigned char chlo_hash[32]; //SHA256 HASH of CHLO
90    unsigned char nonc[DNONC_LENGTH]; /* 4 tm, 8 orbit ---> REJ, 20 rand */
91    unsigned char  pubs[32];
92
93    uint32_t    rrej;
94    struct lsquic_str ccs;
95    struct lsquic_str sni;   /* 0 rtt */
96    struct lsquic_str ccrt;
97    struct lsquic_str stk;
98    struct lsquic_str sno;
99    struct lsquic_str prof;
100
101    struct lsquic_str csct;
102    struct lsquic_str crt; /* compressed certs buffer */
103} hs_ctx_t;
104
105/* client side need to store 0rtt info per STK */
106typedef struct lsquic_session_cache_info_st
107{
108    unsigned char   sscid[SCID_LENGTH];
109    unsigned char   spubs[32];  /* server pub key for next time 0rtt */
110    uint32_t    ver;  /* one VERSION */
111    uint32_t    aead;
112    uint32_t    kexs;
113    uint32_t    pdmd;
114    uint64_t    orbt;
115    uint64_t    expy;
116    int         scfg_flag; /* 0, no-init, 1, no parse, 2, parsed */
117    struct lsquic_str    sstk;
118    struct lsquic_str    scfg;
119    struct lsquic_str    sni_key;   /* This is only used as key */
120
121} lsquic_session_cache_info_t;
122
123#ifndef LSQUIC_KEEP_ENC_SESS_HISTORY
124#   ifndef NDEBUG
125#       define LSQUIC_KEEP_ENC_SESS_HISTORY 1
126#   else
127#       define LSQUIC_KEEP_ENC_SESS_HISTORY 0
128#   endif
129#endif
130
131#if LSQUIC_KEEP_ENC_SESS_HISTORY
132
133#define ESHIST_BITS 7
134#define ESHIST_MASK ((1 << ESHIST_BITS) - 1)
135#define ESHIST_STR_SIZE ((1 << ESHIST_BITS) + 1)
136typedef unsigned char eshist_idx_t;
137
138enum enc_sess_history_event
139{
140    ESHE_EMPTY              =  '\0',
141    ESHE_SET_SNI            =  'I',
142    ESHE_SET_SNO            =  'O',
143    ESHE_SET_STK            =  'K',
144    ESHE_SET_SCID           =  'D',
145    ESHE_SET_PROF           =  'P',
146};
147
148#endif
149
150typedef struct lsquic_enc_session
151{
152    enum handshake_state hsk_state;
153
154    uint8_t have_key; /* 0, no 1, I, 2, D, 3, F */
155    uint8_t peer_have_final_key;
156    uint8_t server_start_use_final_key;
157
158    lsquic_cid_t cid;
159    unsigned char priv_key[32];
160    EVP_AEAD_CTX *enc_ctx_i;
161    EVP_AEAD_CTX *dec_ctx_i;
162
163    /* Have to save the initial key for diversification need */
164    unsigned char enc_key_i[aes128_key_len];
165    unsigned char dec_key_i[aes128_key_len];
166    unsigned char enc_key_nonce_i[aes128_iv_len];
167    unsigned char dec_key_nonce_i[aes128_iv_len];
168
169    EVP_AEAD_CTX *enc_ctx_f;
170    EVP_AEAD_CTX *dec_ctx_f;
171    unsigned char enc_key_nonce_f[aes128_iv_len];
172    unsigned char dec_key_nonce_f[aes128_iv_len];
173
174    hs_ctx_t hs_ctx;
175    lsquic_session_cache_info_t *info;
176    SSL_CTX *  ssl_ctx;
177    const struct lsquic_engine_public *enpub;
178    struct lsquic_str * cert_ptr; /* pointer to the leaf cert of the server, not real copy */
179    struct lsquic_str   chlo; /* real copy of CHLO message */
180    struct lsquic_str   sstk;
181    struct lsquic_str   ssno;
182
183#if LSQUIC_KEEP_ENC_SESS_HISTORY
184    eshist_idx_t        es_hist_idx;
185    unsigned char       es_hist_buf[1 << ESHIST_BITS];
186#endif
187} lsquic_enc_session_t;
188
189#if LSQUIC_KEEP_ENC_SESS_HISTORY
190void
191lsquic_get_enc_hist (const lsquic_enc_session_t *, char buf[ESHIST_STR_SIZE]);
192#endif
193
194int handshake_init(int flags);
195void handshake_cleanup();
196
197lsquic_enc_session_t *
198new_enc_session_c(const char *domain, lsquic_cid_t cid,
199                                const struct lsquic_engine_public *);
200
201void free_enc_session(lsquic_enc_session_t *enc_session);
202void free_info(lsquic_session_cache_info_t *info);
203
204lsquic_cid_t generate_cid(void);
205
206/* save to hash table */
207lsquic_session_cache_info_t *retrieve_session_info_entry(const char *key);
208void remove_expire_session_info_entry();
209void remove_session_info_entry(struct lsquic_str *key);
210
211cert_hash_item_t *make_cert_hash_item(struct lsquic_str *domain, struct lsquic_str **certs, int count);
212void c_free_cert_hash_item(cert_hash_item_t *item);
213cert_hash_item_t* c_find_certs(struct lsquic_str *domain);
214int c_insert_certs(cert_hash_item_t *item);
215
216/* -1 error, 0, OK, response in `buf' */
217int gen_chlo(lsquic_enc_session_t *enc_session, enum lsquic_version,
218                                                uint8_t *buf, size_t *len);
219int handle_chlo_reply(lsquic_enc_session_t *enc_session, const uint8_t *data,
220                      int len);
221
222int is_hs_done(lsquic_enc_session_t *enc_session);
223
224/**
225 * The belows are global functions
226 */
227
228int lsquic_enc(lsquic_enc_session_t *enc_session, enum lsquic_version,
229               uint8_t path_id, uint64_t pack_num,
230               const unsigned char *header, size_t header_len,
231               const unsigned char *data, size_t data_len,
232               unsigned char *buf_out, size_t max_out_len, size_t *out_len,
233               int is_hello);
234
235int lsquic_dec(lsquic_enc_session_t *enc_session, enum lsquic_version,
236               uint8_t path_id, uint64_t pack_num,
237               unsigned char *buf, size_t *header_len, size_t data_len,
238               unsigned char *diversification_nonce,
239               unsigned char *buf_out, size_t max_out_len, size_t *out_len);
240
241int
242get_peer_setting (const lsquic_enc_session_t *, uint32_t tag, uint32_t *val);
243
244int
245get_peer_option (const lsquic_enc_session_t *enc_session, uint32_t tag);
246
247#ifdef NDEBUG
248#define lsquic_enc_session_have_key_gt_one(e) ((e) && (e)->have_key > 1)
249#else
250int
251lsquic_enc_session_have_key_gt_one (const lsquic_enc_session_t *enc_session);
252#endif
253
254#endif
255