lsquic_handshake.h revision 50aadb33
150aadb33SDmitri Tikhonov/* Copyright (c) 2017 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov#ifndef LSQUIC_HANDSHAKE_H
350aadb33SDmitri Tikhonov#define LSQUIC_HANDSHAKE_H
450aadb33SDmitri Tikhonov
550aadb33SDmitri Tikhonov#include <stdint.h>
650aadb33SDmitri Tikhonov#include <openssl/base.h>
750aadb33SDmitri Tikhonov#include <openssl/aead.h>
850aadb33SDmitri Tikhonov
950aadb33SDmitri Tikhonov#include <time.h>
1050aadb33SDmitri Tikhonov#include "lsquic_str.h"
1150aadb33SDmitri Tikhonov
1250aadb33SDmitri Tikhonovstruct lsquic_engine_public;
1350aadb33SDmitri Tikhonovstruct sockaddr;
1450aadb33SDmitri Tikhonov
1550aadb33SDmitri Tikhonov#include "lsquic_qtags.h"
1650aadb33SDmitri Tikhonov
1750aadb33SDmitri Tikhonov#define STK_LENGTH   60
1850aadb33SDmitri Tikhonov#define SNO_LENGTH   56
1950aadb33SDmitri Tikhonov#define SCID_LENGTH  16
2050aadb33SDmitri Tikhonov#define DNONC_LENGTH 32
2150aadb33SDmitri Tikhonov#define aes128_key_len 16
2250aadb33SDmitri Tikhonov#define aes128_iv_len 4
2350aadb33SDmitri Tikhonov
2450aadb33SDmitri Tikhonov/* client side, certs and hashs
2550aadb33SDmitri Tikhonov */
2650aadb33SDmitri Tikhonovtypedef struct cert_hash_item_st
2750aadb33SDmitri Tikhonov{
2850aadb33SDmitri Tikhonov    struct lsquic_str*   domain; /*with port, such as "xyz.com:8088" as the key */
2950aadb33SDmitri Tikhonov    struct lsquic_str*   crts;
3050aadb33SDmitri Tikhonov    struct lsquic_str*   hashs;
3150aadb33SDmitri Tikhonov    int         count;
3250aadb33SDmitri Tikhonov} cert_hash_item_t;
3350aadb33SDmitri Tikhonov
3450aadb33SDmitri Tikhonovenum handshake_error            /* TODO: rename this enum */
3550aadb33SDmitri Tikhonov{
3650aadb33SDmitri Tikhonov    DATA_NOT_ENOUGH = -2,
3750aadb33SDmitri Tikhonov    DATA_FORMAT_ERROR = -1,
3850aadb33SDmitri Tikhonov    HS_ERROR = -1,
3950aadb33SDmitri Tikhonov    DATA_NO_ERROR = 0,
4050aadb33SDmitri Tikhonov    HS_SHLO = 0,
4150aadb33SDmitri Tikhonov    HS_1RTT = 1,
4250aadb33SDmitri Tikhonov    HS_2RTT = 2,
4350aadb33SDmitri Tikhonov};
4450aadb33SDmitri Tikhonov
4550aadb33SDmitri Tikhonovenum handshake_state
4650aadb33SDmitri Tikhonov{
4750aadb33SDmitri Tikhonov    HSK_CHLO_REJ = 0,
4850aadb33SDmitri Tikhonov    HSK_SHLO,
4950aadb33SDmitri Tikhonov    HSK_COMPLETED,
5050aadb33SDmitri Tikhonov    N_HSK_STATES
5150aadb33SDmitri Tikhonov};
5250aadb33SDmitri Tikhonov
5350aadb33SDmitri Tikhonovtypedef struct tag_value_st
5450aadb33SDmitri Tikhonov{
5550aadb33SDmitri Tikhonov    uint32_t    tag;
5650aadb33SDmitri Tikhonov    const char *      value;
5750aadb33SDmitri Tikhonov    int         len;
5850aadb33SDmitri Tikhonov} tag_value_t;
5950aadb33SDmitri Tikhonov
6050aadb33SDmitri Tikhonovtypedef struct hs_ctx_st
6150aadb33SDmitri Tikhonov{
6250aadb33SDmitri Tikhonov    enum {
6350aadb33SDmitri Tikhonov        HSET_TCID     =   (1 << 0),     /* tcid is set */
6450aadb33SDmitri Tikhonov        HSET_SMHL     =   (1 << 1),     /* smhl is set */
6550aadb33SDmitri Tikhonov        HSET_SCID     =   (1 << 2),
6650aadb33SDmitri Tikhonov    }           set;
6750aadb33SDmitri Tikhonov    enum {
6850aadb33SDmitri Tikhonov        HOPT_NSTP     =   (1 << 0),     /* NSTP option present in COPT */
6950aadb33SDmitri Tikhonov        HOPT_SREJ     =   (1 << 1),     /* SREJ option present in COPT */
7050aadb33SDmitri Tikhonov    }           opts;
7150aadb33SDmitri Tikhonov    uint32_t    pdmd;
7250aadb33SDmitri Tikhonov    uint32_t    aead;
7350aadb33SDmitri Tikhonov    uint32_t    kexs;
7450aadb33SDmitri Tikhonov
7550aadb33SDmitri Tikhonov    uint32_t    mids;
7650aadb33SDmitri Tikhonov    uint32_t    scls;
7750aadb33SDmitri Tikhonov    uint32_t    cfcw;
7850aadb33SDmitri Tikhonov    uint32_t    sfcw;
7950aadb33SDmitri Tikhonov    uint32_t    srbf;
8050aadb33SDmitri Tikhonov    uint32_t    icsl;
8150aadb33SDmitri Tikhonov
8250aadb33SDmitri Tikhonov    uint32_t    irtt;
8350aadb33SDmitri Tikhonov    uint64_t    rcid;
8450aadb33SDmitri Tikhonov    uint32_t    tcid;
8550aadb33SDmitri Tikhonov    uint32_t    smhl;
8650aadb33SDmitri Tikhonov    uint64_t    ctim;  /* any usage? */
8750aadb33SDmitri Tikhonov    uint64_t    sttl;
8850aadb33SDmitri Tikhonov    unsigned char scid[SCID_LENGTH];
8950aadb33SDmitri Tikhonov    //unsigned char chlo_hash[32]; //SHA256 HASH of CHLO
9050aadb33SDmitri Tikhonov    unsigned char nonc[DNONC_LENGTH]; /* 4 tm, 8 orbit ---> REJ, 20 rand */
9150aadb33SDmitri Tikhonov    unsigned char  pubs[32];
9250aadb33SDmitri Tikhonov
9350aadb33SDmitri Tikhonov    uint32_t    rrej;
9450aadb33SDmitri Tikhonov    struct lsquic_str ccs;
9550aadb33SDmitri Tikhonov    struct lsquic_str sni;   /* 0 rtt */
9650aadb33SDmitri Tikhonov    struct lsquic_str ccrt;
9750aadb33SDmitri Tikhonov    struct lsquic_str stk;
9850aadb33SDmitri Tikhonov    struct lsquic_str sno;
9950aadb33SDmitri Tikhonov    struct lsquic_str prof;
10050aadb33SDmitri Tikhonov
10150aadb33SDmitri Tikhonov    struct lsquic_str csct;
10250aadb33SDmitri Tikhonov    struct lsquic_str crt; /* compressed certs buffer */
10350aadb33SDmitri Tikhonov} hs_ctx_t;
10450aadb33SDmitri Tikhonov
10550aadb33SDmitri Tikhonov/* client side need to store 0rtt info per STK */
10650aadb33SDmitri Tikhonovtypedef struct lsquic_session_cache_info_st
10750aadb33SDmitri Tikhonov{
10850aadb33SDmitri Tikhonov    unsigned char   sscid[SCID_LENGTH];
10950aadb33SDmitri Tikhonov    unsigned char   spubs[32];  /* server pub key for next time 0rtt */
11050aadb33SDmitri Tikhonov    uint32_t    ver;  /* one VERSION */
11150aadb33SDmitri Tikhonov    uint32_t    aead;
11250aadb33SDmitri Tikhonov    uint32_t    kexs;
11350aadb33SDmitri Tikhonov    uint32_t    pdmd;
11450aadb33SDmitri Tikhonov    uint64_t    orbt;
11550aadb33SDmitri Tikhonov    uint64_t    expy;
11650aadb33SDmitri Tikhonov    int         scfg_flag; /* 0, no-init, 1, no parse, 2, parsed */
11750aadb33SDmitri Tikhonov    struct lsquic_str    sstk;
11850aadb33SDmitri Tikhonov    struct lsquic_str    scfg;
11950aadb33SDmitri Tikhonov    struct lsquic_str    sni_key;   /* This is only used as key */
12050aadb33SDmitri Tikhonov
12150aadb33SDmitri Tikhonov} lsquic_session_cache_info_t;
12250aadb33SDmitri Tikhonov
12350aadb33SDmitri Tikhonov#ifndef LSQUIC_KEEP_ENC_SESS_HISTORY
12450aadb33SDmitri Tikhonov#   ifndef NDEBUG
12550aadb33SDmitri Tikhonov#       define LSQUIC_KEEP_ENC_SESS_HISTORY 1
12650aadb33SDmitri Tikhonov#   else
12750aadb33SDmitri Tikhonov#       define LSQUIC_KEEP_ENC_SESS_HISTORY 0
12850aadb33SDmitri Tikhonov#   endif
12950aadb33SDmitri Tikhonov#endif
13050aadb33SDmitri Tikhonov
13150aadb33SDmitri Tikhonov#if LSQUIC_KEEP_ENC_SESS_HISTORY
13250aadb33SDmitri Tikhonov
13350aadb33SDmitri Tikhonov#define ESHIST_BITS 7
13450aadb33SDmitri Tikhonov#define ESHIST_MASK ((1 << ESHIST_BITS) - 1)
13550aadb33SDmitri Tikhonov#define ESHIST_STR_SIZE ((1 << ESHIST_BITS) + 1)
13650aadb33SDmitri Tikhonovtypedef unsigned char eshist_idx_t;
13750aadb33SDmitri Tikhonov
13850aadb33SDmitri Tikhonovenum enc_sess_history_event
13950aadb33SDmitri Tikhonov{
14050aadb33SDmitri Tikhonov    ESHE_EMPTY              =  '\0',
14150aadb33SDmitri Tikhonov    ESHE_SET_SNI            =  'I',
14250aadb33SDmitri Tikhonov    ESHE_SET_SNO            =  'O',
14350aadb33SDmitri Tikhonov    ESHE_SET_STK            =  'K',
14450aadb33SDmitri Tikhonov    ESHE_SET_SCID           =  'D',
14550aadb33SDmitri Tikhonov    ESHE_SET_PROF           =  'P',
14650aadb33SDmitri Tikhonov};
14750aadb33SDmitri Tikhonov
14850aadb33SDmitri Tikhonov#endif
14950aadb33SDmitri Tikhonov
15050aadb33SDmitri Tikhonovtypedef struct lsquic_enc_session
15150aadb33SDmitri Tikhonov{
15250aadb33SDmitri Tikhonov    enum handshake_state hsk_state;
15350aadb33SDmitri Tikhonov
15450aadb33SDmitri Tikhonov    uint8_t have_key; /* 0, no 1, I, 2, D, 3, F */
15550aadb33SDmitri Tikhonov    uint8_t peer_have_final_key;
15650aadb33SDmitri Tikhonov    uint8_t server_start_use_final_key;
15750aadb33SDmitri Tikhonov
15850aadb33SDmitri Tikhonov    lsquic_cid_t cid;
15950aadb33SDmitri Tikhonov    unsigned char priv_key[32];
16050aadb33SDmitri Tikhonov    EVP_AEAD_CTX *enc_ctx_i;
16150aadb33SDmitri Tikhonov    EVP_AEAD_CTX *dec_ctx_i;
16250aadb33SDmitri Tikhonov
16350aadb33SDmitri Tikhonov    /* Have to save the initial key for diversification need */
16450aadb33SDmitri Tikhonov    unsigned char enc_key_i[aes128_key_len];
16550aadb33SDmitri Tikhonov    unsigned char dec_key_i[aes128_key_len];
16650aadb33SDmitri Tikhonov    unsigned char enc_key_nonce_i[aes128_iv_len];
16750aadb33SDmitri Tikhonov    unsigned char dec_key_nonce_i[aes128_iv_len];
16850aadb33SDmitri Tikhonov
16950aadb33SDmitri Tikhonov    EVP_AEAD_CTX *enc_ctx_f;
17050aadb33SDmitri Tikhonov    EVP_AEAD_CTX *dec_ctx_f;
17150aadb33SDmitri Tikhonov    unsigned char enc_key_nonce_f[aes128_iv_len];
17250aadb33SDmitri Tikhonov    unsigned char dec_key_nonce_f[aes128_iv_len];
17350aadb33SDmitri Tikhonov
17450aadb33SDmitri Tikhonov    hs_ctx_t hs_ctx;
17550aadb33SDmitri Tikhonov    lsquic_session_cache_info_t *info;
17650aadb33SDmitri Tikhonov    SSL_CTX *  ssl_ctx;
17750aadb33SDmitri Tikhonov    const struct lsquic_engine_public *enpub;
17850aadb33SDmitri Tikhonov    struct lsquic_str * cert_ptr; /* pointer to the leaf cert of the server, not real copy */
17950aadb33SDmitri Tikhonov    struct lsquic_str   chlo; /* real copy of CHLO message */
18050aadb33SDmitri Tikhonov    struct lsquic_str   sstk;
18150aadb33SDmitri Tikhonov    struct lsquic_str   ssno;
18250aadb33SDmitri Tikhonov
18350aadb33SDmitri Tikhonov#if LSQUIC_KEEP_ENC_SESS_HISTORY
18450aadb33SDmitri Tikhonov    eshist_idx_t        es_hist_idx;
18550aadb33SDmitri Tikhonov    unsigned char       es_hist_buf[1 << ESHIST_BITS];
18650aadb33SDmitri Tikhonov#endif
18750aadb33SDmitri Tikhonov} lsquic_enc_session_t;
18850aadb33SDmitri Tikhonov
18950aadb33SDmitri Tikhonov#if LSQUIC_KEEP_ENC_SESS_HISTORY
19050aadb33SDmitri Tikhonovvoid
19150aadb33SDmitri Tikhonovlsquic_get_enc_hist (const lsquic_enc_session_t *, char buf[ESHIST_STR_SIZE]);
19250aadb33SDmitri Tikhonov#endif
19350aadb33SDmitri Tikhonov
19450aadb33SDmitri Tikhonovint handshake_init(int flags);
19550aadb33SDmitri Tikhonovvoid handshake_cleanup();
19650aadb33SDmitri Tikhonov
19750aadb33SDmitri Tikhonovlsquic_enc_session_t *
19850aadb33SDmitri Tikhonovnew_enc_session_c(const char *domain, lsquic_cid_t cid,
19950aadb33SDmitri Tikhonov                                const struct lsquic_engine_public *);
20050aadb33SDmitri Tikhonov
20150aadb33SDmitri Tikhonovvoid free_enc_session(lsquic_enc_session_t *enc_session);
20250aadb33SDmitri Tikhonovvoid free_info(lsquic_session_cache_info_t *info);
20350aadb33SDmitri Tikhonov
20450aadb33SDmitri Tikhonovlsquic_cid_t generate_cid(void);
20550aadb33SDmitri Tikhonov
20650aadb33SDmitri Tikhonov/* save to hash table */
20750aadb33SDmitri Tikhonovlsquic_session_cache_info_t *retrieve_session_info_entry(const char *key);
20850aadb33SDmitri Tikhonovvoid remove_expire_session_info_entry();
20950aadb33SDmitri Tikhonovvoid remove_session_info_entry(struct lsquic_str *key);
21050aadb33SDmitri Tikhonov
21150aadb33SDmitri Tikhonovcert_hash_item_t *make_cert_hash_item(struct lsquic_str *domain, struct lsquic_str **certs, int count);
21250aadb33SDmitri Tikhonovvoid c_free_cert_hash_item(cert_hash_item_t *item);
21350aadb33SDmitri Tikhonovcert_hash_item_t* c_find_certs(struct lsquic_str *domain);
21450aadb33SDmitri Tikhonovint c_insert_certs(cert_hash_item_t *item);
21550aadb33SDmitri Tikhonov
21650aadb33SDmitri Tikhonov/* -1 error, 0, OK, response in `buf' */
21750aadb33SDmitri Tikhonovint gen_chlo(lsquic_enc_session_t *enc_session, enum lsquic_version,
21850aadb33SDmitri Tikhonov                                                uint8_t *buf, size_t *len);
21950aadb33SDmitri Tikhonovint handle_chlo_reply(lsquic_enc_session_t *enc_session, const uint8_t *data,
22050aadb33SDmitri Tikhonov                      int len);
22150aadb33SDmitri Tikhonov
22250aadb33SDmitri Tikhonovint is_hs_done(lsquic_enc_session_t *enc_session);
22350aadb33SDmitri Tikhonov
22450aadb33SDmitri Tikhonov/**
22550aadb33SDmitri Tikhonov * The belows are global functions
22650aadb33SDmitri Tikhonov */
22750aadb33SDmitri Tikhonov
22850aadb33SDmitri Tikhonovint lsquic_enc(lsquic_enc_session_t *enc_session, enum lsquic_version,
22950aadb33SDmitri Tikhonov               uint8_t path_id, uint64_t pack_num,
23050aadb33SDmitri Tikhonov               const unsigned char *header, size_t header_len,
23150aadb33SDmitri Tikhonov               const unsigned char *data, size_t data_len,
23250aadb33SDmitri Tikhonov               unsigned char *buf_out, size_t max_out_len, size_t *out_len,
23350aadb33SDmitri Tikhonov               int is_hello);
23450aadb33SDmitri Tikhonov
23550aadb33SDmitri Tikhonovint lsquic_dec(lsquic_enc_session_t *enc_session, enum lsquic_version,
23650aadb33SDmitri Tikhonov               uint8_t path_id, uint64_t pack_num,
23750aadb33SDmitri Tikhonov               unsigned char *buf, size_t *header_len, size_t data_len,
23850aadb33SDmitri Tikhonov               unsigned char *diversification_nonce,
23950aadb33SDmitri Tikhonov               unsigned char *buf_out, size_t max_out_len, size_t *out_len);
24050aadb33SDmitri Tikhonov
24150aadb33SDmitri Tikhonovint
24250aadb33SDmitri Tikhonovget_peer_setting (const lsquic_enc_session_t *, uint32_t tag, uint32_t *val);
24350aadb33SDmitri Tikhonov
24450aadb33SDmitri Tikhonovint
24550aadb33SDmitri Tikhonovget_peer_option (const lsquic_enc_session_t *enc_session, uint32_t tag);
24650aadb33SDmitri Tikhonov
24750aadb33SDmitri Tikhonov#ifdef NDEBUG
24850aadb33SDmitri Tikhonov#define lsquic_enc_session_have_key_gt_one(e) ((e) && (e)->have_key > 1)
24950aadb33SDmitri Tikhonov#else
25050aadb33SDmitri Tikhonovint
25150aadb33SDmitri Tikhonovlsquic_enc_session_have_key_gt_one (const lsquic_enc_session_t *enc_session);
25250aadb33SDmitri Tikhonov#endif
25350aadb33SDmitri Tikhonov
25450aadb33SDmitri Tikhonov#endif
255