mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Latest changes
- Hide handshake implementation behind a set of function pointers - Use monotonically increasing clock - Make sure that retx delay is not larger than the max of 60 seconds
This commit is contained in:
parent
0fb9ea94ae
commit
83287402d5
13 changed files with 343 additions and 247 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2017-10-09
|
||||||
|
|
||||||
|
- Hide handshake implementation behind a set of function pointers
|
||||||
|
- Use monotonically increasing clock
|
||||||
|
- Make sure that retx delay is not larger than the max of 60 seconds
|
||||||
|
|
||||||
2017-09-29
|
2017-09-29
|
||||||
|
|
||||||
- A few fixes to code and README
|
- A few fixes to code and README
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "lsquic_int_types.h"
|
#include "lsquic_int_types.h"
|
||||||
#include "lsquic.h"
|
#include "lsquic.h"
|
||||||
|
|
||||||
|
#include "lsquic_str.h"
|
||||||
#include "lsquic_handshake.h"
|
#include "lsquic_handshake.h"
|
||||||
#include "lsquic_chsk_stream.h"
|
#include "lsquic_chsk_stream.h"
|
||||||
#include "lsquic_ver_neg.h"
|
#include "lsquic_ver_neg.h"
|
||||||
|
@ -78,9 +79,9 @@ hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
|
||||||
}
|
}
|
||||||
c_hsk->buf_off += nread;
|
c_hsk->buf_off += nread;
|
||||||
|
|
||||||
s = handle_chlo_reply(c_hsk->lconn->cn_enc_session,
|
s = c_hsk->lconn->cn_esf->esf_handle_chlo_reply(c_hsk->lconn->cn_enc_session,
|
||||||
c_hsk->buf_in, c_hsk->buf_off);
|
c_hsk->buf_in, c_hsk->buf_off);
|
||||||
LSQ_DEBUG("handle_chlo_reply returned %d", s);
|
LSQ_DEBUG("lsquic_enc_session_handle_chlo_reply returned %d", s);
|
||||||
switch (s)
|
switch (s)
|
||||||
{
|
{
|
||||||
case DATA_NOT_ENOUGH:
|
case DATA_NOT_ENOUGH:
|
||||||
|
@ -101,7 +102,7 @@ hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
|
||||||
lsquic_mm_put_16k(c_hsk->mm, c_hsk->buf_in);
|
lsquic_mm_put_16k(c_hsk->mm, c_hsk->buf_in);
|
||||||
c_hsk->buf_in = NULL;
|
c_hsk->buf_in = NULL;
|
||||||
lsquic_stream_wantread(stream, 0);
|
lsquic_stream_wantread(stream, 0);
|
||||||
if (is_hs_done(c_hsk->lconn->cn_enc_session))
|
if (c_hsk->lconn->cn_esf->esf_is_hsk_done(c_hsk->lconn->cn_enc_session))
|
||||||
{
|
{
|
||||||
LSQ_DEBUG("handshake is complete, inform connection");
|
LSQ_DEBUG("handshake is complete, inform connection");
|
||||||
c_hsk->lconn->cn_if->ci_handshake_done(c_hsk->lconn);
|
c_hsk->lconn->cn_if->ci_handshake_done(c_hsk->lconn);
|
||||||
|
@ -114,9 +115,9 @@ hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LSQ_WARN("handle_chlo_reply returned unknown value %d", s);
|
LSQ_WARN("lsquic_enc_session_handle_chlo_reply returned unknown value %d", s);
|
||||||
case DATA_FORMAT_ERROR:
|
case DATA_FORMAT_ERROR:
|
||||||
LSQ_INFO("handle_chlo_reply returned an error");
|
LSQ_INFO("lsquic_enc_session_handle_chlo_reply returned an error");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,8 +145,8 @@ hsk_client_on_write (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
|
||||||
}
|
}
|
||||||
len = 4 * 1024;
|
len = 4 * 1024;
|
||||||
|
|
||||||
if (0 != gen_chlo(c_hsk->lconn->cn_enc_session, c_hsk->ver_neg->vn_ver,
|
if (0 != c_hsk->lconn->cn_esf->esf_gen_chlo(c_hsk->lconn->cn_enc_session,
|
||||||
buf, &len))
|
c_hsk->ver_neg->vn_ver, buf, &len))
|
||||||
{
|
{
|
||||||
LSQ_WARN("cannot create CHLO message");
|
LSQ_WARN("cannot create CHLO message");
|
||||||
lsquic_mm_put_4k(c_hsk->mm, buf);
|
lsquic_mm_put_4k(c_hsk->mm, buf);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "lsquic_conn.h"
|
#include "lsquic_conn.h"
|
||||||
#include "lsquic_packet_common.h"
|
#include "lsquic_packet_common.h"
|
||||||
#include "lsquic_packet_in.h"
|
#include "lsquic_packet_in.h"
|
||||||
|
#include "lsquic_str.h"
|
||||||
#include "lsquic_handshake.h"
|
#include "lsquic_handshake.h"
|
||||||
#include "lsquic_mm.h"
|
#include "lsquic_mm.h"
|
||||||
#include "lsquic_engine_public.h"
|
#include "lsquic_engine_public.h"
|
||||||
|
@ -119,7 +120,8 @@ lsquic_conn_decrypt_packet (lsquic_conn_t *lconn,
|
||||||
|
|
||||||
header_len = packet_in->pi_header_sz;
|
header_len = packet_in->pi_header_sz;
|
||||||
data_len = packet_in->pi_data_sz - packet_in->pi_header_sz;
|
data_len = packet_in->pi_data_sz - packet_in->pi_header_sz;
|
||||||
if (0 == lsquic_dec(lconn->cn_enc_session, lconn->cn_version, 0,
|
if (0 == lconn->cn_esf->esf_decrypt(lconn->cn_enc_session,
|
||||||
|
lconn->cn_version, 0,
|
||||||
packet_in->pi_packno, packet_in->pi_data,
|
packet_in->pi_packno, packet_in->pi_data,
|
||||||
&header_len, data_len,
|
&header_len, data_len,
|
||||||
lsquic_packet_in_nonce(packet_in),
|
lsquic_packet_in_nonce(packet_in),
|
||||||
|
|
|
@ -88,6 +88,8 @@ struct lsquic_conn
|
||||||
{
|
{
|
||||||
void *cn_peer_ctx;
|
void *cn_peer_ctx;
|
||||||
struct lsquic_enc_session *cn_enc_session;
|
struct lsquic_enc_session *cn_enc_session;
|
||||||
|
const struct enc_session_funcs
|
||||||
|
*cn_esf;
|
||||||
lsquic_cid_t cn_cid;
|
lsquic_cid_t cn_cid;
|
||||||
STAILQ_ENTRY(lsquic_conn) cn_next_closed_conn;
|
STAILQ_ENTRY(lsquic_conn) cn_next_closed_conn;
|
||||||
TAILQ_ENTRY(lsquic_conn) cn_next_all,
|
TAILQ_ENTRY(lsquic_conn) cn_next_all,
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "lsquic_full_conn.h"
|
#include "lsquic_full_conn.h"
|
||||||
#include "lsquic_util.h"
|
#include "lsquic_util.h"
|
||||||
#include "lsquic_qtags.h"
|
#include "lsquic_qtags.h"
|
||||||
|
#include "lsquic_str.h"
|
||||||
#include "lsquic_handshake.h"
|
#include "lsquic_handshake.h"
|
||||||
#include "lsquic_mm.h"
|
#include "lsquic_mm.h"
|
||||||
#include "lsquic_conn_hash.h"
|
#include "lsquic_conn_hash.h"
|
||||||
|
@ -1072,7 +1073,7 @@ really_encrypt_packet (const lsquic_conn_t *conn,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
is_hello_packet = !!(packet_out->po_flags & PO_HELLO);
|
is_hello_packet = !!(packet_out->po_flags & PO_HELLO);
|
||||||
enc = lsquic_enc(conn->cn_enc_session, conn->cn_version, 0,
|
enc = conn->cn_esf->esf_encrypt(conn->cn_enc_session, conn->cn_version, 0,
|
||||||
packet_out->po_packno, header_buf, header_sz,
|
packet_out->po_packno, header_buf, header_sz,
|
||||||
packet_out->po_data, packet_out->po_data_sz,
|
packet_out->po_data, packet_out->po_data_sz,
|
||||||
buf, bufsz, &packet_sz, is_hello_packet);
|
buf, bufsz, &packet_sz, is_hello_packet);
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include "lsquic_set.h"
|
#include "lsquic_set.h"
|
||||||
#include "lsquic_malo.h"
|
#include "lsquic_malo.h"
|
||||||
#include "lsquic_chsk_stream.h"
|
#include "lsquic_chsk_stream.h"
|
||||||
|
#include "lsquic_str.h"
|
||||||
|
#include "lsquic_qtags.h"
|
||||||
#include "lsquic_handshake.h"
|
#include "lsquic_handshake.h"
|
||||||
#include "lsquic_headers_stream.h"
|
#include "lsquic_headers_stream.h"
|
||||||
#include "lsquic_frame_common.h"
|
#include "lsquic_frame_common.h"
|
||||||
|
@ -325,7 +327,8 @@ send_smhl (const struct full_conn *conn)
|
||||||
uint32_t smhl;
|
uint32_t smhl;
|
||||||
return conn->fc_conn.cn_enc_session
|
return conn->fc_conn.cn_enc_session
|
||||||
&& (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|
&& (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|
||||||
&& 0 == get_peer_setting(conn->fc_conn.cn_enc_session, QTAG_SMHL, &smhl)
|
&& 0 == conn->fc_conn.cn_esf->esf_get_peer_setting(
|
||||||
|
conn->fc_conn.cn_enc_session, QTAG_SMHL, &smhl)
|
||||||
&& 1 == smhl;
|
&& 1 == smhl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,8 +390,8 @@ apply_peer_settings (struct full_conn *conn)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (n = 0; n < sizeof(tags) / sizeof(tags[0]); ++n)
|
for (n = 0; n < sizeof(tags) / sizeof(tags[0]); ++n)
|
||||||
if (0 != get_peer_setting(conn->fc_conn.cn_enc_session,
|
if (0 != conn->fc_conn.cn_esf->esf_get_peer_setting(
|
||||||
tags[n].tag, tags[n].val))
|
conn->fc_conn.cn_enc_session, tags[n].tag, tags[n].val))
|
||||||
{
|
{
|
||||||
LSQ_INFO("peer did not supply value for %s", tags[n].tag_str);
|
LSQ_INFO("peer did not supply value for %s", tags[n].tag_str);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -521,15 +524,20 @@ full_conn_client_new (struct lsquic_engine_public *enpub,
|
||||||
const char *hostname, unsigned short max_packet_size)
|
const char *hostname, unsigned short max_packet_size)
|
||||||
{
|
{
|
||||||
struct full_conn *conn;
|
struct full_conn *conn;
|
||||||
|
enum lsquic_version version;
|
||||||
lsquic_cid_t cid;
|
lsquic_cid_t cid;
|
||||||
|
const struct enc_session_funcs *esf;
|
||||||
|
|
||||||
cid = generate_cid();
|
version = highest_bit_set(enpub->enp_settings.es_versions);
|
||||||
|
esf = select_esf_by_ver(version);
|
||||||
|
cid = esf->esf_generate_cid();
|
||||||
conn = new_conn_common(cid, enpub, stream_if, stream_if_ctx, flags,
|
conn = new_conn_common(cid, enpub, stream_if, stream_if_ctx, flags,
|
||||||
max_packet_size);
|
max_packet_size);
|
||||||
if (!conn)
|
if (!conn)
|
||||||
return NULL;
|
return NULL;
|
||||||
conn->fc_conn.cn_enc_session = new_enc_session_c(hostname, cid,
|
conn->fc_conn.cn_esf = esf;
|
||||||
conn->fc_enpub);
|
conn->fc_conn.cn_enc_session =
|
||||||
|
conn->fc_conn.cn_esf->esf_create_client(hostname, cid, conn->fc_enpub);
|
||||||
if (!conn->fc_conn.cn_enc_session)
|
if (!conn->fc_conn.cn_enc_session)
|
||||||
{
|
{
|
||||||
LSQ_WARN("could not create enc session: %s", strerror(errno));
|
LSQ_WARN("could not create enc session: %s", strerror(errno));
|
||||||
|
@ -547,7 +555,6 @@ full_conn_client_new (struct lsquic_engine_public *enpub,
|
||||||
conn->fc_stream_ifs[STREAM_IF_HSK]
|
conn->fc_stream_ifs[STREAM_IF_HSK]
|
||||||
.stream_if = &lsquic_client_hsk_stream_if;
|
.stream_if = &lsquic_client_hsk_stream_if;
|
||||||
conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.client;
|
conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.client;
|
||||||
/* TODO the client does not know how to perform version negotiation */
|
|
||||||
init_ver_neg(conn, conn->fc_settings->es_versions);
|
init_ver_neg(conn, conn->fc_settings->es_versions);
|
||||||
conn->fc_conn.cn_pf = select_pf_by_ver(conn->fc_ver_neg.vn_ver);
|
conn->fc_conn.cn_pf = select_pf_by_ver(conn->fc_ver_neg.vn_ver);
|
||||||
if (conn->fc_settings->es_handshake_to)
|
if (conn->fc_settings->es_handshake_to)
|
||||||
|
@ -628,7 +635,7 @@ full_conn_ci_destroy (lsquic_conn_t *lconn)
|
||||||
lsquic_send_ctl_cleanup(&conn->fc_send_ctl);
|
lsquic_send_ctl_cleanup(&conn->fc_send_ctl);
|
||||||
lsquic_rechist_cleanup(&conn->fc_rechist);
|
lsquic_rechist_cleanup(&conn->fc_rechist);
|
||||||
if (conn->fc_conn.cn_enc_session)
|
if (conn->fc_conn.cn_enc_session)
|
||||||
free_enc_session(conn->fc_conn.cn_enc_session);
|
conn->fc_conn.cn_esf->esf_destroy(conn->fc_conn.cn_enc_session);
|
||||||
lsquic_malo_destroy(conn->fc_pub.packet_out_malo);
|
lsquic_malo_destroy(conn->fc_pub.packet_out_malo);
|
||||||
#if FULL_CONN_STATS
|
#if FULL_CONN_STATS
|
||||||
LSQ_NOTICE("received %u packets, of which %u were not decryptable, %u were "
|
LSQ_NOTICE("received %u packets, of which %u were not decryptable, %u were "
|
||||||
|
|
|
@ -3,20 +3,24 @@
|
||||||
* Global state
|
* Global state
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "lsquic_int_types.h"
|
||||||
#include "lsquic_types.h"
|
#include "lsquic_types.h"
|
||||||
#include "lsquic.h"
|
#include "lsquic.h"
|
||||||
|
#include "lsquic_str.h"
|
||||||
#include "lsquic_handshake.h"
|
#include "lsquic_handshake.h"
|
||||||
|
#include "lsquic_util.h"
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
lsquic_global_init (int flags)
|
lsquic_global_init (int flags)
|
||||||
{
|
{
|
||||||
return handshake_init(flags);
|
lsquic_init_timers();
|
||||||
|
return lsquic_enc_session_gquic_1.esf_global_init(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
lsquic_global_cleanup (void)
|
lsquic_global_cleanup (void)
|
||||||
{
|
{
|
||||||
handshake_cleanup();
|
lsquic_enc_session_gquic_1.esf_global_cleanup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "lsquic.h"
|
#include "lsquic.h"
|
||||||
#include "lsquic_types.h"
|
#include "lsquic_types.h"
|
||||||
#include "lsquic_crypto.h"
|
#include "lsquic_crypto.h"
|
||||||
|
#include "lsquic_str.h"
|
||||||
#include "lsquic_handshake.h"
|
#include "lsquic_handshake.h"
|
||||||
#include "lsquic_parse.h"
|
#include "lsquic_parse.h"
|
||||||
#include "lsquic_crt_compress.h"
|
#include "lsquic_crt_compress.h"
|
||||||
|
@ -25,9 +26,9 @@
|
||||||
#include "lsquic_version.h"
|
#include "lsquic_version.h"
|
||||||
#include "lsquic_mm.h"
|
#include "lsquic_mm.h"
|
||||||
#include "lsquic_engine_public.h"
|
#include "lsquic_engine_public.h"
|
||||||
#include "lsquic_str.h"
|
|
||||||
#include "lsquic_hash.h"
|
#include "lsquic_hash.h"
|
||||||
#include "lsquic_buf.h"
|
#include "lsquic_buf.h"
|
||||||
|
#include "lsquic_qtags.h"
|
||||||
|
|
||||||
#include "fiu-local.h"
|
#include "fiu-local.h"
|
||||||
|
|
||||||
|
@ -38,6 +39,114 @@
|
||||||
#define LSQUIC_LOGGER_MODULE LSQLM_HANDSHAKE
|
#define LSQUIC_LOGGER_MODULE LSQLM_HANDSHAKE
|
||||||
#include "lsquic_logger.h"
|
#include "lsquic_logger.h"
|
||||||
|
|
||||||
|
enum handshake_state
|
||||||
|
{
|
||||||
|
HSK_CHLO_REJ = 0,
|
||||||
|
HSK_SHLO,
|
||||||
|
HSK_COMPLETED,
|
||||||
|
N_HSK_STATES
|
||||||
|
};
|
||||||
|
|
||||||
|
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
||||||
|
typedef unsigned char eshist_idx_t;
|
||||||
|
|
||||||
|
enum enc_sess_history_event
|
||||||
|
{
|
||||||
|
ESHE_EMPTY = '\0',
|
||||||
|
ESHE_SET_SNI = 'I',
|
||||||
|
ESHE_SET_SNO = 'O',
|
||||||
|
ESHE_SET_STK = 'K',
|
||||||
|
ESHE_SET_SCID = 'D',
|
||||||
|
ESHE_SET_PROF = 'P',
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct hs_ctx_st
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
HSET_TCID = (1 << 0), /* tcid is set */
|
||||||
|
HSET_SMHL = (1 << 1), /* smhl is set */
|
||||||
|
HSET_SCID = (1 << 2),
|
||||||
|
} set;
|
||||||
|
enum {
|
||||||
|
HOPT_NSTP = (1 << 0), /* NSTP option present in COPT */
|
||||||
|
HOPT_SREJ = (1 << 1), /* SREJ option present in COPT */
|
||||||
|
} opts;
|
||||||
|
uint32_t pdmd;
|
||||||
|
uint32_t aead;
|
||||||
|
uint32_t kexs;
|
||||||
|
|
||||||
|
uint32_t mids;
|
||||||
|
uint32_t scls;
|
||||||
|
uint32_t cfcw;
|
||||||
|
uint32_t sfcw;
|
||||||
|
uint32_t srbf;
|
||||||
|
uint32_t icsl;
|
||||||
|
|
||||||
|
uint32_t irtt;
|
||||||
|
uint64_t rcid;
|
||||||
|
uint32_t tcid;
|
||||||
|
uint32_t smhl;
|
||||||
|
uint64_t ctim; /* any usage? */
|
||||||
|
uint64_t sttl;
|
||||||
|
unsigned char scid[SCID_LENGTH];
|
||||||
|
//unsigned char chlo_hash[32]; //SHA256 HASH of CHLO
|
||||||
|
unsigned char nonc[DNONC_LENGTH]; /* 4 tm, 8 orbit ---> REJ, 20 rand */
|
||||||
|
unsigned char pubs[32];
|
||||||
|
|
||||||
|
uint32_t rrej;
|
||||||
|
struct lsquic_str ccs;
|
||||||
|
struct lsquic_str sni; /* 0 rtt */
|
||||||
|
struct lsquic_str ccrt;
|
||||||
|
struct lsquic_str stk;
|
||||||
|
struct lsquic_str sno;
|
||||||
|
struct lsquic_str prof;
|
||||||
|
|
||||||
|
struct lsquic_str csct;
|
||||||
|
struct lsquic_str crt; /* compressed certs buffer */
|
||||||
|
} hs_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct lsquic_enc_session
|
||||||
|
{
|
||||||
|
enum handshake_state hsk_state;
|
||||||
|
|
||||||
|
uint8_t have_key; /* 0, no 1, I, 2, D, 3, F */
|
||||||
|
uint8_t peer_have_final_key;
|
||||||
|
uint8_t server_start_use_final_key;
|
||||||
|
|
||||||
|
lsquic_cid_t cid;
|
||||||
|
unsigned char priv_key[32];
|
||||||
|
EVP_AEAD_CTX *enc_ctx_i;
|
||||||
|
EVP_AEAD_CTX *dec_ctx_i;
|
||||||
|
|
||||||
|
/* Have to save the initial key for diversification need */
|
||||||
|
unsigned char enc_key_i[aes128_key_len];
|
||||||
|
unsigned char dec_key_i[aes128_key_len];
|
||||||
|
unsigned char enc_key_nonce_i[aes128_iv_len];
|
||||||
|
unsigned char dec_key_nonce_i[aes128_iv_len];
|
||||||
|
|
||||||
|
EVP_AEAD_CTX *enc_ctx_f;
|
||||||
|
EVP_AEAD_CTX *dec_ctx_f;
|
||||||
|
unsigned char enc_key_nonce_f[aes128_iv_len];
|
||||||
|
unsigned char dec_key_nonce_f[aes128_iv_len];
|
||||||
|
|
||||||
|
hs_ctx_t hs_ctx;
|
||||||
|
lsquic_session_cache_info_t *info;
|
||||||
|
SSL_CTX * ssl_ctx;
|
||||||
|
const struct lsquic_engine_public *enpub;
|
||||||
|
struct lsquic_str * cert_ptr; /* pointer to the leaf cert of the server, not real copy */
|
||||||
|
struct lsquic_str chlo; /* real copy of CHLO message */
|
||||||
|
struct lsquic_str sstk;
|
||||||
|
struct lsquic_str ssno;
|
||||||
|
|
||||||
|
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
||||||
|
eshist_idx_t es_hist_idx;
|
||||||
|
unsigned char es_hist_buf[1 << ESHIST_BITS];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* client side, it will store the domain/certs as cache cert
|
* client side, it will store the domain/certs as cache cert
|
||||||
|
@ -49,6 +158,15 @@ static struct lsquic_hash *s_cached_client_certs;
|
||||||
*/
|
*/
|
||||||
static struct lsquic_hash *s_cached_client_session_infos;
|
static struct lsquic_hash *s_cached_client_session_infos;
|
||||||
|
|
||||||
|
/* save to hash table */
|
||||||
|
static lsquic_session_cache_info_t *retrieve_session_info_entry(const char *key);
|
||||||
|
static void remove_expire_session_info_entry();
|
||||||
|
static void remove_session_info_entry(struct lsquic_str *key);
|
||||||
|
|
||||||
|
static void free_info (lsquic_session_cache_info_t *);
|
||||||
|
|
||||||
|
static void c_free_cert_hash_item (cert_hash_item_t *item);
|
||||||
|
static void c_free_cert_hash_item(cert_hash_item_t *item);
|
||||||
|
|
||||||
|
|
||||||
static int get_tag_val_u32 (unsigned char *v, int len, uint32_t *val);
|
static int get_tag_val_u32 (unsigned char *v, int len, uint32_t *val);
|
||||||
|
@ -74,8 +192,8 @@ eshist_append (lsquic_enc_session_t *enc_session,
|
||||||
# define ESHIST_APPEND(sess, event) do { } while (0)
|
# define ESHIST_APPEND(sess, event) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
static int
|
||||||
handshake_init(int flags)
|
lsquic_handshake_init(int flags)
|
||||||
{
|
{
|
||||||
crypto_init();
|
crypto_init();
|
||||||
return init_hs_hash_tables(flags);
|
return init_hs_hash_tables(flags);
|
||||||
|
@ -114,8 +232,8 @@ cleanup_hs_hash_tables (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
handshake_cleanup (void)
|
lsquic_handshake_cleanup (void)
|
||||||
{
|
{
|
||||||
cleanup_hs_hash_tables();
|
cleanup_hs_hash_tables();
|
||||||
lsquic_crt_cleanup();
|
lsquic_crt_cleanup();
|
||||||
|
@ -141,7 +259,8 @@ static int init_hs_hash_tables(int flags)
|
||||||
|
|
||||||
|
|
||||||
/* client */
|
/* client */
|
||||||
cert_hash_item_t* c_find_certs(lsquic_str_t *domain)
|
cert_hash_item_t *
|
||||||
|
c_find_certs (const lsquic_str_t *domain)
|
||||||
{
|
{
|
||||||
struct lsquic_hash_elem *el;
|
struct lsquic_hash_elem *el;
|
||||||
|
|
||||||
|
@ -159,7 +278,8 @@ cert_hash_item_t* c_find_certs(lsquic_str_t *domain)
|
||||||
|
|
||||||
/* client */
|
/* client */
|
||||||
/* certs is an array of lsquic_str_t * */
|
/* certs is an array of lsquic_str_t * */
|
||||||
cert_hash_item_t *make_cert_hash_item(lsquic_str_t *domain, lsquic_str_t **certs, int count)
|
static cert_hash_item_t *
|
||||||
|
make_cert_hash_item (lsquic_str_t *domain, lsquic_str_t **certs, int count)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint64_t hash;
|
uint64_t hash;
|
||||||
|
@ -180,7 +300,8 @@ cert_hash_item_t *make_cert_hash_item(lsquic_str_t *domain, lsquic_str_t **certs
|
||||||
|
|
||||||
|
|
||||||
/* client */
|
/* client */
|
||||||
void c_free_cert_hash_item(cert_hash_item_t *item)
|
void
|
||||||
|
c_free_cert_hash_item (cert_hash_item_t *item)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (item)
|
if (item)
|
||||||
|
@ -196,7 +317,8 @@ void c_free_cert_hash_item(cert_hash_item_t *item)
|
||||||
|
|
||||||
|
|
||||||
/* client */
|
/* client */
|
||||||
int c_insert_certs(cert_hash_item_t *item)
|
static int
|
||||||
|
c_insert_certs (cert_hash_item_t *item)
|
||||||
{
|
{
|
||||||
if (lsquic_hash_insert(s_cached_client_certs,
|
if (lsquic_hash_insert(s_cached_client_certs,
|
||||||
lsquic_str_cstr(item->domain),
|
lsquic_str_cstr(item->domain),
|
||||||
|
@ -223,7 +345,8 @@ static int save_session_info_entry(lsquic_str_t *key, lsquic_session_cache_info_
|
||||||
|
|
||||||
|
|
||||||
/* If entry updated and need to remove cached entry */
|
/* If entry updated and need to remove cached entry */
|
||||||
void remove_session_info_entry(lsquic_str_t *key)
|
static void
|
||||||
|
remove_session_info_entry (lsquic_str_t *key)
|
||||||
{
|
{
|
||||||
lsquic_session_cache_info_t *entry;
|
lsquic_session_cache_info_t *entry;
|
||||||
struct lsquic_hash_elem *el;
|
struct lsquic_hash_elem *el;
|
||||||
|
@ -239,7 +362,7 @@ void remove_session_info_entry(lsquic_str_t *key)
|
||||||
|
|
||||||
|
|
||||||
/* client */
|
/* client */
|
||||||
lsquic_session_cache_info_t *
|
static lsquic_session_cache_info_t *
|
||||||
retrieve_session_info_entry (const char *key)
|
retrieve_session_info_entry (const char *key)
|
||||||
{
|
{
|
||||||
lsquic_session_cache_info_t *entry;
|
lsquic_session_cache_info_t *entry;
|
||||||
|
@ -262,7 +385,11 @@ retrieve_session_info_entry (const char *key)
|
||||||
|
|
||||||
|
|
||||||
/* call it in timer() */
|
/* call it in timer() */
|
||||||
void remove_expire_session_info_entry()
|
#if __GNUC__
|
||||||
|
__attribute__((unused))
|
||||||
|
#endif
|
||||||
|
static void
|
||||||
|
remove_expire_session_info_entry (void)
|
||||||
{
|
{
|
||||||
time_t tm = time(NULL);
|
time_t tm = time(NULL);
|
||||||
struct lsquic_hash_elem *el;
|
struct lsquic_hash_elem *el;
|
||||||
|
@ -280,8 +407,9 @@ void remove_expire_session_info_entry()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lsquic_enc_session_t *new_enc_session_c(const char *domain, lsquic_cid_t cid,
|
static lsquic_enc_session_t *
|
||||||
const struct lsquic_engine_public *enpub)
|
lsquic_enc_session_create_client (const char *domain, lsquic_cid_t cid,
|
||||||
|
const struct lsquic_engine_public *enpub)
|
||||||
{
|
{
|
||||||
lsquic_session_cache_info_t *info;
|
lsquic_session_cache_info_t *info;
|
||||||
lsquic_enc_session_t *enc_session;
|
lsquic_enc_session_t *enc_session;
|
||||||
|
@ -318,7 +446,8 @@ lsquic_enc_session_t *new_enc_session_c(const char *domain, lsquic_cid_t cid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void free_enc_session(lsquic_enc_session_t *enc_session)
|
static void
|
||||||
|
lsquic_enc_session_destroy (lsquic_enc_session_t *enc_session)
|
||||||
{
|
{
|
||||||
if (!enc_session)
|
if (!enc_session)
|
||||||
return ;
|
return ;
|
||||||
|
@ -360,7 +489,8 @@ void free_enc_session(lsquic_enc_session_t *enc_session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void free_info(lsquic_session_cache_info_t *info)
|
static void
|
||||||
|
free_info (lsquic_session_cache_info_t *info)
|
||||||
{
|
{
|
||||||
lsquic_str_d(&info->sstk);
|
lsquic_str_d(&info->sstk);
|
||||||
lsquic_str_d(&info->scfg);
|
lsquic_str_d(&info->scfg);
|
||||||
|
@ -376,7 +506,8 @@ static int get_hs_state(lsquic_enc_session_t *enc_session)
|
||||||
|
|
||||||
|
|
||||||
/* make sure have more room for encrypt */
|
/* make sure have more room for encrypt */
|
||||||
int is_hs_done(lsquic_enc_session_t *enc_session)
|
static int
|
||||||
|
lsquic_enc_session_is_hsk_done (lsquic_enc_session_t *enc_session)
|
||||||
{
|
{
|
||||||
return (get_hs_state(enc_session) == HSK_COMPLETED);
|
return (get_hs_state(enc_session) == HSK_COMPLETED);
|
||||||
}
|
}
|
||||||
|
@ -672,7 +803,8 @@ generate_cid_buf (void *buf, size_t bufsz)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lsquic_cid_t generate_cid(void)
|
static lsquic_cid_t
|
||||||
|
lsquic_generate_cid (void)
|
||||||
{
|
{
|
||||||
lsquic_cid_t cid;
|
lsquic_cid_t cid;
|
||||||
generate_cid_buf(&cid, sizeof(cid));
|
generate_cid_buf(&cid, sizeof(cid));
|
||||||
|
@ -783,9 +915,9 @@ struct message_writer
|
||||||
#define MSG_LEN_VAL(len) (+(len))
|
#define MSG_LEN_VAL(len) (+(len))
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
gen_chlo (lsquic_enc_session_t *enc_session, enum lsquic_version version,
|
lsquic_enc_session_gen_chlo (lsquic_enc_session_t *enc_session,
|
||||||
uint8_t *buf, size_t *len)
|
enum lsquic_version version, uint8_t *buf, size_t *len)
|
||||||
{
|
{
|
||||||
int ret, include_pad;
|
int ret, include_pad;
|
||||||
const lsquic_str_t *const ccs = get_common_certs_hash();
|
const lsquic_str_t *const ccs = get_common_certs_hash();
|
||||||
|
@ -944,7 +1076,7 @@ gen_chlo (lsquic_enc_session_t *enc_session, enum lsquic_version version,
|
||||||
else
|
else
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
LSQ_DEBUG("gen_chlo called, return %d, buf_len %zd.", ret, *len);
|
LSQ_DEBUG("lsquic_enc_session_gen_chlo called, return %d, buf_len %zd.", ret, *len);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1000,7 +1132,8 @@ void setup_aead_ctx(EVP_AEAD_CTX **ctx, unsigned char key[], int key_len,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int determine_diversification_key(lsquic_enc_session_t *enc_session,
|
static int
|
||||||
|
determine_diversification_key (lsquic_enc_session_t *enc_session,
|
||||||
uint8_t *diversification_nonce
|
uint8_t *diversification_nonce
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -1177,8 +1310,9 @@ he2str (enum handshake_error he)
|
||||||
* DATA_NOT_ENOUGH(-2) for not enough data,
|
* DATA_NOT_ENOUGH(-2) for not enough data,
|
||||||
* DATA_FORMAT_ERROR(-1) all other errors
|
* DATA_FORMAT_ERROR(-1) all other errors
|
||||||
*/
|
*/
|
||||||
int handle_chlo_reply(lsquic_enc_session_t *enc_session, const uint8_t *data,
|
static int
|
||||||
int len)
|
lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
|
||||||
|
const uint8_t *data, int len)
|
||||||
{
|
{
|
||||||
uint32_t head_tag;
|
uint32_t head_tag;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1278,7 +1412,7 @@ int handle_chlo_reply(lsquic_enc_session_t *enc_session, const uint8_t *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
LSQ_DEBUG("handle_chlo_reply called, buf in %d, return %d.", len, ret);
|
LSQ_DEBUG("lsquic_enc_session_handle_chlo_reply called, buf in %d, return %d.", len, ret);
|
||||||
EV_LOG_CONN_EVENT(enc_session->cid, "%s returning %s", __func__,
|
EV_LOG_CONN_EVENT(enc_session->cid, "%s returning %s", __func__,
|
||||||
he2str(ret));
|
he2str(ret));
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1413,28 +1547,20 @@ decrypt_packet (lsquic_enc_session_t *enc_session, uint8_t path_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
static int
|
||||||
/* In debug builds, we need to be able to override this function for testing */
|
|
||||||
__attribute__((weak))
|
|
||||||
int
|
|
||||||
lsquic_enc_session_have_key_gt_one (const lsquic_enc_session_t *enc_session)
|
lsquic_enc_session_have_key_gt_one (const lsquic_enc_session_t *enc_session)
|
||||||
{
|
{
|
||||||
return enc_session && enc_session->have_key > 1;
|
return enc_session && enc_session->have_key > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
/* Use weak linkage so that tests can override this function */
|
|
||||||
__attribute__((weak))
|
|
||||||
#endif
|
|
||||||
/* The size of `buf' is *header_len plus data_len. The two parts of the
|
/* The size of `buf' is *header_len plus data_len. The two parts of the
|
||||||
* buffer correspond to the header and the payload of incoming QUIC packet.
|
* buffer correspond to the header and the payload of incoming QUIC packet.
|
||||||
*/
|
*/
|
||||||
/* 0 for OK, otherwise nonezero */
|
/* 0 for OK, otherwise nonezero */
|
||||||
int lsquic_dec(lsquic_enc_session_t *enc_session, enum lsquic_version version,
|
static int
|
||||||
|
lsquic_enc_session_decrypt (lsquic_enc_session_t *enc_session,
|
||||||
|
enum lsquic_version version,
|
||||||
uint8_t path_id, uint64_t pack_num,
|
uint8_t path_id, uint64_t pack_num,
|
||||||
unsigned char *buf, size_t *header_len, size_t data_len,
|
unsigned char *buf, size_t *header_len, size_t data_len,
|
||||||
unsigned char *diversification_nonce,
|
unsigned char *diversification_nonce,
|
||||||
|
@ -1456,7 +1582,9 @@ int lsquic_dec(lsquic_enc_session_t *enc_session, enum lsquic_version version,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int lsquic_enc(lsquic_enc_session_t *enc_session, enum lsquic_version version,
|
static int
|
||||||
|
lsquic_enc_session_encrypt (lsquic_enc_session_t *enc_session,
|
||||||
|
enum lsquic_version version,
|
||||||
uint8_t path_id, uint64_t pack_num,
|
uint8_t path_id, uint64_t pack_num,
|
||||||
const unsigned char *header, size_t header_len,
|
const unsigned char *header, size_t header_len,
|
||||||
const unsigned char *data, size_t data_len,
|
const unsigned char *data, size_t data_len,
|
||||||
|
@ -1507,7 +1635,7 @@ int lsquic_enc(lsquic_enc_session_t *enc_session, enum lsquic_version version,
|
||||||
((IS_SERVER(enc_session)) &&
|
((IS_SERVER(enc_session)) &&
|
||||||
enc_session->server_start_use_final_key == 0))
|
enc_session->server_start_use_final_key == 0))
|
||||||
{
|
{
|
||||||
LSQ_DEBUG("lsquic_enc using 'I' key...");
|
LSQ_DEBUG("lsquic_enc_session_encrypt using 'I' key...");
|
||||||
key = enc_session->enc_ctx_i;
|
key = enc_session->enc_ctx_i;
|
||||||
memcpy(nonce, enc_session->enc_key_nonce_i, 4);
|
memcpy(nonce, enc_session->enc_key_nonce_i, 4);
|
||||||
if (is_shlo && enc_session->have_key == 3)
|
if (is_shlo && enc_session->have_key == 3)
|
||||||
|
@ -1517,7 +1645,7 @@ int lsquic_enc(lsquic_enc_session_t *enc_session, enum lsquic_version version,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LSQ_DEBUG("lsquic_enc using 'F' key...");
|
LSQ_DEBUG("lsquic_enc_session_encrypt using 'F' key...");
|
||||||
key = enc_session->enc_ctx_f;
|
key = enc_session->enc_ctx_f;
|
||||||
memcpy(nonce, enc_session->enc_key_nonce_f, 4);
|
memcpy(nonce, enc_session->enc_key_nonce_f, 4);
|
||||||
}
|
}
|
||||||
|
@ -1536,8 +1664,9 @@ int lsquic_enc(lsquic_enc_session_t *enc_session, enum lsquic_version version,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
get_peer_option (const lsquic_enc_session_t *enc_session, uint32_t tag)
|
lsquic_enc_session_get_peer_option (const lsquic_enc_session_t *enc_session,
|
||||||
|
uint32_t tag)
|
||||||
{
|
{
|
||||||
switch (tag)
|
switch (tag)
|
||||||
{
|
{
|
||||||
|
@ -1555,9 +1684,9 @@ get_peer_option (const lsquic_enc_session_t *enc_session, uint32_t tag)
|
||||||
/* Query a several parameters sent by the peer that are required by
|
/* Query a several parameters sent by the peer that are required by
|
||||||
* connection.
|
* connection.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
get_peer_setting (const lsquic_enc_session_t *enc_session, uint32_t tag,
|
lsquic_enc_session_get_peer_setting (const lsquic_enc_session_t *enc_session,
|
||||||
uint32_t *val)
|
uint32_t tag, uint32_t *val)
|
||||||
{
|
{
|
||||||
switch (tag)
|
switch (tag)
|
||||||
{
|
{
|
||||||
|
@ -1616,7 +1745,7 @@ get_peer_setting (const lsquic_enc_session_t *enc_session, uint32_t tag,
|
||||||
|
|
||||||
|
|
||||||
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
||||||
void
|
static void
|
||||||
lsquic_get_enc_hist (const lsquic_enc_session_t *enc_session,
|
lsquic_get_enc_hist (const lsquic_enc_session_t *enc_session,
|
||||||
char buf[(1 << ESHIST_BITS) + 1])
|
char buf[(1 << ESHIST_BITS) + 1])
|
||||||
{
|
{
|
||||||
|
@ -1635,3 +1764,25 @@ lsquic_get_enc_hist (const lsquic_enc_session_t *enc_session,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
const
|
||||||
|
#endif
|
||||||
|
struct enc_session_funcs lsquic_enc_session_gquic_1 =
|
||||||
|
{
|
||||||
|
.esf_global_init = lsquic_handshake_init,
|
||||||
|
.esf_global_cleanup = lsquic_handshake_cleanup,
|
||||||
|
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
||||||
|
.esf_get_hist = lsquic_get_enc_hist,
|
||||||
|
#endif
|
||||||
|
.esf_destroy = lsquic_enc_session_destroy,
|
||||||
|
.esf_is_hsk_done = lsquic_enc_session_is_hsk_done,
|
||||||
|
.esf_encrypt = lsquic_enc_session_encrypt,
|
||||||
|
.esf_decrypt = lsquic_enc_session_decrypt,
|
||||||
|
.esf_get_peer_setting = lsquic_enc_session_get_peer_setting,
|
||||||
|
.esf_get_peer_option = lsquic_enc_session_get_peer_option,
|
||||||
|
.esf_create_client = lsquic_enc_session_create_client,
|
||||||
|
.esf_generate_cid = lsquic_generate_cid,
|
||||||
|
.esf_gen_chlo = lsquic_enc_session_gen_chlo,
|
||||||
|
.esf_handle_chlo_reply = lsquic_enc_session_handle_chlo_reply,
|
||||||
|
};
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */
|
/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */
|
||||||
#ifndef LSQUIC_HANDSHAKE_H
|
#ifndef LSQUIC_HANDSHAKE_SERVER_H
|
||||||
#define LSQUIC_HANDSHAKE_H
|
#define LSQUIC_HANDSHAKE_SERVER_H
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <openssl/base.h>
|
|
||||||
#include <openssl/aead.h>
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include "lsquic_str.h"
|
|
||||||
|
|
||||||
struct lsquic_engine_public;
|
struct lsquic_engine_public;
|
||||||
struct sockaddr;
|
struct lsquic_enc_session;
|
||||||
|
|
||||||
#include "lsquic_qtags.h"
|
typedef struct lsquic_enc_session lsquic_enc_session_t;
|
||||||
|
|
||||||
#define STK_LENGTH 60
|
#define STK_LENGTH 60
|
||||||
#define SNO_LENGTH 56
|
#define SNO_LENGTH 56
|
||||||
|
@ -21,16 +14,6 @@ struct sockaddr;
|
||||||
#define aes128_key_len 16
|
#define aes128_key_len 16
|
||||||
#define aes128_iv_len 4
|
#define aes128_iv_len 4
|
||||||
|
|
||||||
/* client side, certs and hashs
|
|
||||||
*/
|
|
||||||
typedef struct cert_hash_item_st
|
|
||||||
{
|
|
||||||
struct lsquic_str* domain; /*with port, such as "xyz.com:8088" as the key */
|
|
||||||
struct lsquic_str* crts;
|
|
||||||
struct lsquic_str* hashs;
|
|
||||||
int count;
|
|
||||||
} cert_hash_item_t;
|
|
||||||
|
|
||||||
enum handshake_error /* TODO: rename this enum */
|
enum handshake_error /* TODO: rename this enum */
|
||||||
{
|
{
|
||||||
DATA_NOT_ENOUGH = -2,
|
DATA_NOT_ENOUGH = -2,
|
||||||
|
@ -42,66 +25,6 @@ enum handshake_error /* TODO: rename this enum */
|
||||||
HS_2RTT = 2,
|
HS_2RTT = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum handshake_state
|
|
||||||
{
|
|
||||||
HSK_CHLO_REJ = 0,
|
|
||||||
HSK_SHLO,
|
|
||||||
HSK_COMPLETED,
|
|
||||||
N_HSK_STATES
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct tag_value_st
|
|
||||||
{
|
|
||||||
uint32_t tag;
|
|
||||||
const char * value;
|
|
||||||
int len;
|
|
||||||
} tag_value_t;
|
|
||||||
|
|
||||||
typedef struct hs_ctx_st
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
HSET_TCID = (1 << 0), /* tcid is set */
|
|
||||||
HSET_SMHL = (1 << 1), /* smhl is set */
|
|
||||||
HSET_SCID = (1 << 2),
|
|
||||||
} set;
|
|
||||||
enum {
|
|
||||||
HOPT_NSTP = (1 << 0), /* NSTP option present in COPT */
|
|
||||||
HOPT_SREJ = (1 << 1), /* SREJ option present in COPT */
|
|
||||||
} opts;
|
|
||||||
uint32_t pdmd;
|
|
||||||
uint32_t aead;
|
|
||||||
uint32_t kexs;
|
|
||||||
|
|
||||||
uint32_t mids;
|
|
||||||
uint32_t scls;
|
|
||||||
uint32_t cfcw;
|
|
||||||
uint32_t sfcw;
|
|
||||||
uint32_t srbf;
|
|
||||||
uint32_t icsl;
|
|
||||||
|
|
||||||
uint32_t irtt;
|
|
||||||
uint64_t rcid;
|
|
||||||
uint32_t tcid;
|
|
||||||
uint32_t smhl;
|
|
||||||
uint64_t ctim; /* any usage? */
|
|
||||||
uint64_t sttl;
|
|
||||||
unsigned char scid[SCID_LENGTH];
|
|
||||||
//unsigned char chlo_hash[32]; //SHA256 HASH of CHLO
|
|
||||||
unsigned char nonc[DNONC_LENGTH]; /* 4 tm, 8 orbit ---> REJ, 20 rand */
|
|
||||||
unsigned char pubs[32];
|
|
||||||
|
|
||||||
uint32_t rrej;
|
|
||||||
struct lsquic_str ccs;
|
|
||||||
struct lsquic_str sni; /* 0 rtt */
|
|
||||||
struct lsquic_str ccrt;
|
|
||||||
struct lsquic_str stk;
|
|
||||||
struct lsquic_str sno;
|
|
||||||
struct lsquic_str prof;
|
|
||||||
|
|
||||||
struct lsquic_str csct;
|
|
||||||
struct lsquic_str crt; /* compressed certs buffer */
|
|
||||||
} hs_ctx_t;
|
|
||||||
|
|
||||||
/* client side need to store 0rtt info per STK */
|
/* client side need to store 0rtt info per STK */
|
||||||
typedef struct lsquic_session_cache_info_st
|
typedef struct lsquic_session_cache_info_st
|
||||||
{
|
{
|
||||||
|
@ -129,126 +52,89 @@ typedef struct lsquic_session_cache_info_st
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
||||||
|
|
||||||
#define ESHIST_BITS 7
|
#define ESHIST_BITS 7
|
||||||
#define ESHIST_MASK ((1 << ESHIST_BITS) - 1)
|
#define ESHIST_MASK ((1 << ESHIST_BITS) - 1)
|
||||||
#define ESHIST_STR_SIZE ((1 << ESHIST_BITS) + 1)
|
#define ESHIST_STR_SIZE ((1 << ESHIST_BITS) + 1)
|
||||||
typedef unsigned char eshist_idx_t;
|
|
||||||
|
|
||||||
enum enc_sess_history_event
|
|
||||||
{
|
|
||||||
ESHE_EMPTY = '\0',
|
|
||||||
ESHE_SET_SNI = 'I',
|
|
||||||
ESHE_SET_SNO = 'O',
|
|
||||||
ESHE_SET_STK = 'K',
|
|
||||||
ESHE_SET_SCID = 'D',
|
|
||||||
ESHE_SET_PROF = 'P',
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct lsquic_enc_session
|
struct enc_session_funcs
|
||||||
{
|
{
|
||||||
enum handshake_state hsk_state;
|
/* Global initialization: call once per implementation */
|
||||||
|
int (*esf_global_init)(int flags);
|
||||||
uint8_t have_key; /* 0, no 1, I, 2, D, 3, F */
|
|
||||||
uint8_t peer_have_final_key;
|
|
||||||
uint8_t server_start_use_final_key;
|
|
||||||
|
|
||||||
lsquic_cid_t cid;
|
/* Global cleanup: call once per implementation */
|
||||||
unsigned char priv_key[32];
|
void (*esf_global_cleanup) (void);
|
||||||
EVP_AEAD_CTX *enc_ctx_i;
|
|
||||||
EVP_AEAD_CTX *dec_ctx_i;
|
|
||||||
|
|
||||||
/* Have to save the initial key for diversification need */
|
|
||||||
unsigned char enc_key_i[aes128_key_len];
|
|
||||||
unsigned char dec_key_i[aes128_key_len];
|
|
||||||
unsigned char enc_key_nonce_i[aes128_iv_len];
|
|
||||||
unsigned char dec_key_nonce_i[aes128_iv_len];
|
|
||||||
|
|
||||||
EVP_AEAD_CTX *enc_ctx_f;
|
|
||||||
EVP_AEAD_CTX *dec_ctx_f;
|
|
||||||
unsigned char enc_key_nonce_f[aes128_iv_len];
|
|
||||||
unsigned char dec_key_nonce_f[aes128_iv_len];
|
|
||||||
|
|
||||||
hs_ctx_t hs_ctx;
|
|
||||||
lsquic_session_cache_info_t *info;
|
|
||||||
SSL_CTX * ssl_ctx;
|
|
||||||
const struct lsquic_engine_public *enpub;
|
|
||||||
struct lsquic_str * cert_ptr; /* pointer to the leaf cert of the server, not real copy */
|
|
||||||
struct lsquic_str chlo; /* real copy of CHLO message */
|
|
||||||
struct lsquic_str sstk;
|
|
||||||
struct lsquic_str ssno;
|
|
||||||
|
|
||||||
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
||||||
eshist_idx_t es_hist_idx;
|
/* Grab encryption session history */
|
||||||
unsigned char es_hist_buf[1 << ESHIST_BITS];
|
void (*esf_get_hist) (const lsquic_enc_session_t *,
|
||||||
#endif
|
char buf[ESHIST_STR_SIZE]);
|
||||||
} lsquic_enc_session_t;
|
|
||||||
|
|
||||||
#if LSQUIC_KEEP_ENC_SESS_HISTORY
|
|
||||||
void
|
|
||||||
lsquic_get_enc_hist (const lsquic_enc_session_t *, char buf[ESHIST_STR_SIZE]);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int handshake_init(int flags);
|
/* Destroy enc session */
|
||||||
void handshake_cleanup();
|
void (*esf_destroy)(lsquic_enc_session_t *enc_session);
|
||||||
|
|
||||||
lsquic_enc_session_t *
|
/* Return true if handshake has been completed */
|
||||||
new_enc_session_c(const char *domain, lsquic_cid_t cid,
|
int (*esf_is_hsk_done)(lsquic_enc_session_t *enc_session);
|
||||||
const struct lsquic_engine_public *);
|
|
||||||
|
|
||||||
void free_enc_session(lsquic_enc_session_t *enc_session);
|
/* Encrypt buffer */
|
||||||
void free_info(lsquic_session_cache_info_t *info);
|
int (*esf_encrypt)(lsquic_enc_session_t *enc_session, enum lsquic_version,
|
||||||
|
|
||||||
lsquic_cid_t generate_cid(void);
|
|
||||||
|
|
||||||
/* save to hash table */
|
|
||||||
lsquic_session_cache_info_t *retrieve_session_info_entry(const char *key);
|
|
||||||
void remove_expire_session_info_entry();
|
|
||||||
void remove_session_info_entry(struct lsquic_str *key);
|
|
||||||
|
|
||||||
cert_hash_item_t *make_cert_hash_item(struct lsquic_str *domain, struct lsquic_str **certs, int count);
|
|
||||||
void c_free_cert_hash_item(cert_hash_item_t *item);
|
|
||||||
cert_hash_item_t* c_find_certs(struct lsquic_str *domain);
|
|
||||||
int c_insert_certs(cert_hash_item_t *item);
|
|
||||||
|
|
||||||
/* -1 error, 0, OK, response in `buf' */
|
|
||||||
int gen_chlo(lsquic_enc_session_t *enc_session, enum lsquic_version,
|
|
||||||
uint8_t *buf, size_t *len);
|
|
||||||
int handle_chlo_reply(lsquic_enc_session_t *enc_session, const uint8_t *data,
|
|
||||||
int len);
|
|
||||||
|
|
||||||
int is_hs_done(lsquic_enc_session_t *enc_session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The belows are global functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
int lsquic_enc(lsquic_enc_session_t *enc_session, enum lsquic_version,
|
|
||||||
uint8_t path_id, uint64_t pack_num,
|
uint8_t path_id, uint64_t pack_num,
|
||||||
const unsigned char *header, size_t header_len,
|
const unsigned char *header, size_t header_len,
|
||||||
const unsigned char *data, size_t data_len,
|
const unsigned char *data, size_t data_len,
|
||||||
unsigned char *buf_out, size_t max_out_len, size_t *out_len,
|
unsigned char *buf_out, size_t max_out_len, size_t *out_len,
|
||||||
int is_hello);
|
int is_hello);
|
||||||
|
|
||||||
int lsquic_dec(lsquic_enc_session_t *enc_session, enum lsquic_version,
|
/* Decrypt buffer */
|
||||||
uint8_t path_id, uint64_t pack_num,
|
int (*esf_decrypt)(lsquic_enc_session_t *enc_session, enum lsquic_version,
|
||||||
unsigned char *buf, size_t *header_len, size_t data_len,
|
uint8_t path_id, uint64_t pack_num,
|
||||||
unsigned char *diversification_nonce,
|
unsigned char *buf, size_t *header_len, size_t data_len,
|
||||||
unsigned char *buf_out, size_t max_out_len, size_t *out_len);
|
unsigned char *diversification_nonce,
|
||||||
|
unsigned char *buf_out, size_t max_out_len, size_t *out_len);
|
||||||
|
|
||||||
int
|
/* Get value of setting specified by `tag' */
|
||||||
get_peer_setting (const lsquic_enc_session_t *, uint32_t tag, uint32_t *val);
|
int (*esf_get_peer_setting) (const lsquic_enc_session_t *, uint32_t tag,
|
||||||
|
uint32_t *val);
|
||||||
|
|
||||||
int
|
/* Get value of peer option (that from COPT array) */
|
||||||
get_peer_option (const lsquic_enc_session_t *enc_session, uint32_t tag);
|
int (*esf_get_peer_option) (const lsquic_enc_session_t *enc_session,
|
||||||
|
uint32_t tag);
|
||||||
|
|
||||||
|
/* Create client session */
|
||||||
|
lsquic_enc_session_t *
|
||||||
|
(*esf_create_client) (const char *domain, lsquic_cid_t cid,
|
||||||
|
const struct lsquic_engine_public *);
|
||||||
|
|
||||||
|
/* Generate connection ID */
|
||||||
|
lsquic_cid_t (*esf_generate_cid) (void);
|
||||||
|
|
||||||
|
/* -1 error, 0, OK, response in `buf' */
|
||||||
|
int
|
||||||
|
(*esf_gen_chlo) (lsquic_enc_session_t *, enum lsquic_version,
|
||||||
|
uint8_t *buf, size_t *len);
|
||||||
|
|
||||||
|
int
|
||||||
|
(*esf_handle_chlo_reply) (lsquic_enc_session_t *,
|
||||||
|
const uint8_t *data, int len);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
#define lsquic_enc_session_have_key_gt_one(e) ((e) && (e)->have_key > 1)
|
const
|
||||||
#else
|
|
||||||
int
|
|
||||||
lsquic_enc_session_have_key_gt_one (const lsquic_enc_session_t *enc_session);
|
|
||||||
#endif
|
#endif
|
||||||
|
struct enc_session_funcs lsquic_enc_session_gquic_1;
|
||||||
|
|
||||||
|
#define select_esf_by_ver(ver) \
|
||||||
|
(ver ? &lsquic_enc_session_gquic_1 : &lsquic_enc_session_gquic_1)
|
||||||
|
|
||||||
|
/* client side, certs and hashs
|
||||||
|
*/
|
||||||
|
typedef struct cert_hash_item_st
|
||||||
|
{
|
||||||
|
struct lsquic_str* domain; /*with port, such as "xyz.com:8088" as the key */
|
||||||
|
struct lsquic_str* crts;
|
||||||
|
struct lsquic_str* hashs;
|
||||||
|
int count;
|
||||||
|
} cert_hash_item_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef uint64_t lsquic_time_t; /* Microseconds since the epoch */
|
typedef uint64_t lsquic_time_t; /* Microseconds since some time */
|
||||||
typedef uint64_t lsquic_packno_t;
|
typedef uint64_t lsquic_packno_t;
|
||||||
typedef uint32_t lsquic_ver_tag_t; /* Opaque 4-byte value */
|
typedef uint32_t lsquic_ver_tag_t; /* Opaque 4-byte value */
|
||||||
|
|
||||||
|
|
|
@ -235,8 +235,6 @@ calculate_packet_rto (lsquic_send_ctl_t *ctl)
|
||||||
exp = MAX_RTO_BACKOFFS;
|
exp = MAX_RTO_BACKOFFS;
|
||||||
|
|
||||||
delay = delay * (1 << exp);
|
delay = delay * (1 << exp);
|
||||||
if (delay > MAX_RTO_DELAY)
|
|
||||||
delay = MAX_RTO_DELAY;
|
|
||||||
|
|
||||||
return delay;
|
return delay;
|
||||||
}
|
}
|
||||||
|
@ -306,6 +304,9 @@ set_retx_alarm (lsquic_send_ctl_t *ctl)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (delay > MAX_RTO_DELAY)
|
||||||
|
delay = MAX_RTO_DELAY;
|
||||||
|
|
||||||
LSQ_DEBUG("set retx alarm to %"PRIu64", which is %"PRIu64
|
LSQ_DEBUG("set retx alarm to %"PRIu64", which is %"PRIu64
|
||||||
" usec from now, mode %s", now + delay, delay, retx2str[rm]);
|
" usec from now, mode %s", now + delay, delay, retx2str[rm]);
|
||||||
lsquic_alarmset_set(ctl->sc_alset, AL_RETX, now + delay);
|
lsquic_alarmset_set(ctl->sc_alset, AL_RETX, now + delay);
|
||||||
|
|
|
@ -8,17 +8,49 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(__APPLE__)
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "lsquic_int_types.h"
|
#include "lsquic_int_types.h"
|
||||||
#include "lsquic_util.h"
|
#include "lsquic_util.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
static mach_timebase_info_data_t timebase;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
lsquic_init_timers (void)
|
||||||
|
{
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
mach_timebase_info(&timebase);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
lsquic_time_t
|
lsquic_time_t
|
||||||
lsquic_time_now (void)
|
lsquic_time_now (void)
|
||||||
{
|
{
|
||||||
|
#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
|
||||||
|
struct timespec ts;
|
||||||
|
(void) clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
return (lsquic_time_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
lsquic_time_t t = mach_absolute_time();
|
||||||
|
t *= timebase.numer;
|
||||||
|
t /= timebase.denom;
|
||||||
|
t /= 1000;
|
||||||
|
return t;
|
||||||
|
#else
|
||||||
|
# warn Monotonically increasing clock is not available on this platform
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
(void) gettimeofday(&tv, NULL);
|
(void) gettimeofday(&tv, NULL);
|
||||||
return (lsquic_time_t) tv.tv_sec * 1000000 + tv.tv_usec;
|
return (lsquic_time_t) tv.tv_sec * 1000000 + tv.tv_usec;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,9 @@ extern "C" {
|
||||||
lsquic_time_t
|
lsquic_time_t
|
||||||
lsquic_time_now (void);
|
lsquic_time_now (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
lsquic_init_timers (void);
|
||||||
|
|
||||||
/* Returns 1 if `buf' contains only zero bytes, 0 otherwise.
|
/* Returns 1 if `buf' contains only zero bytes, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue