diff --git a/src/transport/xqc_cid.c b/src/transport/xqc_cid.c index bfa44702..61913d1d 100644 --- a/src/transport/xqc_cid.c +++ b/src/transport/xqc_cid.c @@ -82,10 +82,12 @@ xqc_cid_set(xqc_cid_t *cid, const unsigned char *data, uint8_t len) } } +static unsigned char g_token_buf[XQC_MAX_TOKEN_LEN]; static unsigned char g_scid_buf[XQC_MAX_CID_LEN * 2 + 1]; static unsigned char g_dcid_buf[XQC_MAX_CID_LEN * 2 + 1]; static unsigned char g_sr_token_buf[XQC_STATELESS_RESET_TOKENLEN * 2 + 1]; + unsigned char * xqc_dcid_str(const xqc_cid_t *dcid) { @@ -110,6 +112,13 @@ xqc_sr_token_str(const char *sr_token) return g_sr_token_buf; } +unsigned char * +xqc_token_str(const char *token, size_t token_len) { + xqc_hex_dump(g_token_buf, token, token_len); + g_token_buf[token_len] = '\0'; + return g_token_buf; +} + unsigned char * xqc_dcid_str_by_scid(xqc_engine_t *engine, const xqc_cid_t *scid) { diff --git a/src/transport/xqc_cid.h b/src/transport/xqc_cid.h index dd57594d..1f715513 100644 --- a/src/transport/xqc_cid.h +++ b/src/transport/xqc_cid.h @@ -74,6 +74,7 @@ xqc_int_t xqc_get_unused_cid(xqc_cid_set_t *cid_set, xqc_cid_t *cid); xqc_bool_t xqc_validate_retire_cid_frame(xqc_cid_set_t *cid_set, xqc_cid_inner_t *cid); unsigned char *xqc_sr_token_str(const char *sr_token); +unsigned char *xqc_token_str(const char *token, size_t token_len); #endif /* _XQC_CID_H_INCLUDED_ */ diff --git a/src/transport/xqc_conn.c b/src/transport/xqc_conn.c index a4d15b21..fab9e043 100644 --- a/src/transport/xqc_conn.c +++ b/src/transport/xqc_conn.c @@ -508,6 +508,36 @@ xqc_conn_set_default_sched_params(xqc_conn_settings_t *settings) } } +static void +xqc_conn_gen_secret(const xqc_engine_t *engine, xqc_connection_t *conn, + const xqc_cid_t *scid) +{ + /* initialization of secret for token */ + uint8_t iv_length = strlen(engine->init_vector); + uint8_t iterator; + uint8_t remainder = iv_length % scid->cid_len; + uint8_t steps = iv_length / scid->cid_len; + uint8_t tmp_array[iv_length]; + + uint8_t *pointer = tmp_array; + + for (iterator = 0; iterator < steps; ++iterator) { + xqc_memcpy(pointer, scid->cid_buf, scid->cid_len); + pointer += scid->cid_len; + } + for (iterator = 0; iterator < remainder; ++iterator) { + *pointer++ = scid->cid_buf[iterator % scid->cid_len]; + } + assert((pointer - tmp_array) == iv_length); + + /* saving connection's secret */ + for (iterator = 0; iterator < iv_length; ++iterator) { + conn->conn_secret[iterator] = engine->init_vector[iterator] ^ + tmp_array[iterator]; + } + conn->conn_secret_len = iv_length; +} + xqc_connection_t * xqc_conn_create(xqc_engine_t *engine, xqc_cid_t *dcid, xqc_cid_t *scid, const xqc_conn_settings_t *settings, void *user_data, xqc_conn_type_t type) @@ -806,6 +836,8 @@ xqc_conn_create(xqc_engine_t *engine, xqc_cid_t *dcid, xqc_cid_t *scid, xqc_init_list_head(&xc->dgram_0rtt_buffer_list); xqc_init_list_head(&xc->ping_notification_list); + xqc_conn_gen_secret(engine, xc, &xc->scid_set.user_scid); + xqc_log(xc->log, XQC_LOG_DEBUG, "|success|scid:%s|dcid:%s|conn:%p|", xqc_scid_str(&xc->scid_set.user_scid), xqc_dcid_str(&xc->dcid_set.current_dcid), xc); xqc_log_event(xc->log, TRA_PARAMETERS_SET, xc, XQC_LOG_LOCAL_EVENT); @@ -3277,9 +3309,8 @@ xqc_conn_get_lastest_rtt(xqc_engine_t *engine, const xqc_cid_t *cid) return path->path_send_ctl->ctl_latest_rtt; } - xqc_int_t -xqc_conn_check_token(xqc_connection_t *conn, const unsigned char *token, unsigned token_len) +xqc_conn_check_token(xqc_connection_t *conn, const unsigned char *enc_token, unsigned token_len) { if (token_len > XQC_MAX_TOKEN_LEN) { xqc_log(conn->log, XQC_LOG_ERROR, "|%ud exceed XQC_MAX_TOKEN_LEN|", token_len); @@ -3291,8 +3322,17 @@ xqc_conn_check_token(xqc_connection_t *conn, const unsigned char *token, unsigne } struct sockaddr *sa = (struct sockaddr *)conn->peer_addr; + unsigned char token[token_len]; + + for (unsigned i = 0; i < token_len; ++i) { + token[i] = (enc_token[i] ^ conn->engine->init_vector[i]) ^ + conn->conn_secret[i]; + } + const unsigned char *pos = token; - if (*pos++ & 0x80) { + if (*pos == 0x80) { + ++pos; + struct in6_addr *in6 = (struct in6_addr *)pos; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; if (token_len != 21) { @@ -3305,7 +3345,9 @@ xqc_conn_check_token(xqc_connection_t *conn, const unsigned char *token, unsigne } pos += sizeof(struct in6_addr); - } else { + } else if (*pos == 0x00) { + ++pos; + struct in_addr *in4 = (struct in_addr *)pos; struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; if (token_len != 9) { @@ -3319,6 +3361,9 @@ xqc_conn_check_token(xqc_connection_t *conn, const unsigned char *token, unsigne return XQC_ERROR; } pos += sizeof(struct in_addr); + } else { + xqc_log(conn->log, XQC_LOG_ERROR, "|invalid version|"); + return XQC_ERROR; } /* check token lifetime */ @@ -3352,28 +3397,40 @@ xqc_conn_check_token(xqc_connection_t *conn, const unsigned char *token, unsigne void xqc_conn_gen_token(xqc_connection_t *conn, unsigned char *token, unsigned *token_len) { + unsigned char *saved_pointer_on_token = token; struct sockaddr *sa = (struct sockaddr *)conn->peer_addr; + if (sa->sa_family == AF_INET) { *token++ = 0x00; struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; memcpy(token, &sa4->sin_addr, sizeof(struct in_addr)); token += sizeof(struct in_addr); - - *token_len = 9; - + /* "+ 1" - version byte */ + *token_len = sizeof(struct in_addr) + 1; } else { *token++ = 0x80; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; memcpy(token, &sa6->sin6_addr, sizeof(struct in6_addr)); token += sizeof(struct in6_addr); - - *token_len = 21; + /* "+ 1" - version byte */ + *token_len = sizeof(struct in6_addr) + 1; } uint32_t expire = xqc_monotonic_timestamp() / 1000000 + XQC_TOKEN_EXPIRE_DELTA; xqc_log(conn->log, XQC_LOG_DEBUG, "|expire:%ud|", expire); expire = htonl(expire); + memcpy(token, &expire, sizeof(expire)); + *token_len += sizeof(uint32_t); + + token = saved_pointer_on_token; + + for (unsigned i = 0; i < *token_len; ++i) { + token[i] = (token[i] ^ conn->conn_secret[i]) ^ + conn->engine->init_vector[i]; + } + + xqc_log(conn->log, XQC_LOG_DEBUG, "|token:%s|", xqc_token_str(token, *token_len)); } void diff --git a/src/transport/xqc_conn.h b/src/transport/xqc_conn.h index bcea5917..b0e92a30 100644 --- a/src/transport/xqc_conn.h +++ b/src/transport/xqc_conn.h @@ -428,6 +428,9 @@ struct xqc_connection_s { uint32_t cli_bidi_streams; uint32_t svr_bidi_streams; + uint8_t conn_secret_len; + uint8_t conn_secret[XQC_MAX_TOKEN_LEN]; + /* receved pkts stats */ struct { xqc_pkt_type_t pkt_types[3]; @@ -494,7 +497,7 @@ xqc_int_t xqc_conn_immediate_close(xqc_connection_t *conn); xqc_int_t xqc_conn_send_retry(xqc_connection_t *conn, unsigned char *token, unsigned token_len); xqc_int_t xqc_conn_version_check(xqc_connection_t *c, uint32_t version); xqc_int_t xqc_conn_send_version_negotiation(xqc_connection_t *c); -xqc_int_t xqc_conn_check_token(xqc_connection_t *conn, const unsigned char *token, unsigned token_len); +xqc_int_t xqc_conn_check_token(xqc_connection_t *conn, const unsigned char *enc_token, unsigned token_len); void xqc_conn_gen_token(xqc_connection_t *conn, unsigned char *token, unsigned *token_len); xqc_int_t xqc_conn_early_data_reject(xqc_connection_t *conn); xqc_int_t xqc_conn_early_data_accept(xqc_connection_t *conn); diff --git a/src/transport/xqc_engine.c b/src/transport/xqc_engine.c index f5a27a15..da2c0245 100644 --- a/src/transport/xqc_engine.c +++ b/src/transport/xqc_engine.c @@ -500,6 +500,19 @@ xqc_engine_create(xqc_engine_type_t engine_type, goto fail; } + srand(time(NULL)); + + uint8_t tmp = 0; + uint8_t length_iv = (rand() % (XQC_MAX_LEN_IV - XQC_MIN_BLOCK_LEN)) + + XQC_MIN_BLOCK_LEN; + for (uint8_t i = 0; i < length_iv; ++i) { + /* range of symbols: [33, 127) */ + engine->init_vector[i] = (rand() % (XQC_ASCII_UPPER_BOUND - + XQC_ASCII_LOWER_BOUND) + + XQC_ASCII_LOWER_BOUND); + } + engine->init_vector[length_iv] = '\0'; + return engine; fail: diff --git a/src/transport/xqc_engine.h b/src/transport/xqc_engine.h index 6f1a6b97..9db8307a 100644 --- a/src/transport/xqc_engine.h +++ b/src/transport/xqc_engine.h @@ -12,6 +12,14 @@ #include "src/tls/xqc_tls.h" #include "src/common/xqc_list.h" +/* follow "XQC_MAX_TOKEN_LEN" from xqc_defs.h */ +#define XQC_MAX_LEN_IV (256) +/* follow "XQC_MAX_CID_LEN" xquic_typedef.h */ +#define XQC_MIN_BLOCK_LEN (XQC_MAX_CID_LEN + 1) + +#define XQC_ASCII_LOWER_BOUND (33) +#define XQC_ASCII_UPPER_BOUND (127) + #define XQC_RESET_CNT_ARRAY_LEN 16384 @@ -68,6 +76,9 @@ typedef struct xqc_engine_s { /* list of xqc_alpn_registration_t */ xqc_list_head_t alpn_reg_list; + /* engine initialization vector for token encryption */ + uint8_t init_vector[XQC_MAX_LEN_IV]; + } xqc_engine_t;