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