Release 2.16.2

- [BUGFIX] ID-28: do not use TLS middlebox compatibility mode in
  ClientHello.  This change requires using a newer version of BoringSSL.
- [BUGFIX] Free connections in Advisory Tick Time Queue in engine dtor.
- [BUGFIX] IETF QUIC client: narrow migration check to a single path.
- [BUGFIX] NULL dereference: set function pointers for alarm for path
  challenges 2 and 3.
- [BUGFIX] HTTP/3 headers may be followed immediately by trailers.
- [BUGFIX] Log messages when SCID changes.
This commit is contained in:
Dmitri Tikhonov 2020-06-12 08:04:42 -04:00
parent 8ae5ecb45e
commit f913a2972b
11 changed files with 155 additions and 126 deletions

View File

@ -8,7 +8,7 @@ task:
- cd boringssl
# This is so that both GQUIC and IETF branches build. Just picking
# a known good revision:
- git checkout bfe527fa35735e8e045cbfb42b012e13ca68f9cf
- git checkout 251b5169fd44345f455438312ec4e18ae07fd58c
- cmake .
- make
- cd -

View File

@ -31,7 +31,7 @@ before_script:
- cd boringssl
# This is so that both GQUIC and IETF branches build. Just picking
# a known good revision:
- git checkout bfe527fa35735e8e045cbfb42b012e13ca68f9cf
- git checkout 251b5169fd44345f455438312ec4e18ae07fd58c
- cmake .
- make
- cd -

View File

@ -1,3 +1,14 @@
2020-06-12
- 2.16.2
- [BUGFIX] ID-28: do not use TLS middlebox compatibility mode in
ClientHello. This change requires using a newer version of BoringSSL.
- [BUGFIX] Free connections in Advisory Tick Time Queue in engine dtor.
- [BUGFIX] IETF QUIC client: narrow migration check to a single path.
- [BUGFIX] NULL dereference: set function pointers for alarm for path
challenges 2 and 3.
- [BUGFIX] HTTP/3 headers may be followed immediately by trailers.
- [BUGFIX] Log messages when SCID changes.
2020-06-09
- 2.16.1
- [FEATURE] Use "no-progress timeout" after which connection is closed.

View File

@ -50,7 +50,7 @@ You may need to install pre-requisites like zlib and libevent.
2. Use specific BoringSSL version
```
git checkout bfe527fa35735e8e045cbfb42b012e13ca68f9cf
git checkout 251b5169fd44345f455438312ec4e18ae07fd58c
```
3. Compile the library

View File

@ -30,7 +30,7 @@ build_script:
cd boringssl
git checkout bfe527fa35735e8e045cbfb42b012e13ca68f9cf
git checkout 251b5169fd44345f455438312ec4e18ae07fd58c
cmake -DCMAKE_GENERATOR_PLATFORM=x64 --config Debug -DBUILD_SHARED_LIBS=OFF -DOPENSSL_NO_ASM=1 .

View File

@ -26,7 +26,7 @@ author = u'LiteSpeed Technologies'
# The short X.Y version
version = u'2.16'
# The full version, including alpha/beta/rc tags
release = u'2.16.1'
release = u'2.16.2'
# -- General configuration ---------------------------------------------------

View File

@ -25,7 +25,7 @@ extern "C" {
#define LSQUIC_MAJOR_VERSION 2
#define LSQUIC_MINOR_VERSION 16
#define LSQUIC_PATCH_VERSION 1
#define LSQUIC_PATCH_VERSION 2
/**
* Engine flags:

View File

@ -106,7 +106,7 @@ no_sess_ticket (enum alarm_id alarm_id, void *ctx,
typedef void (*gen_hp_mask_f)(struct enc_sess_iquic *,
const struct header_prot *, unsigned cliser,
const struct header_prot *, unsigned rw,
const unsigned char *sample, unsigned char mask[16]);
@ -243,8 +243,6 @@ struct enc_sess_iquic
ESI_ISCID = 1 << 15,
ESI_RETRY = 1 << 16, /* Connection was retried */
} esi_flags;
enum evp_aead_direction_t
esi_dir[2]; /* client, server */
enum enc_level esi_last_w;
unsigned esi_trasec_sz;
char *esi_hostname;
@ -278,14 +276,14 @@ struct enc_sess_iquic
static void
gen_hp_mask_aes (struct enc_sess_iquic *enc_sess,
const struct header_prot *hp, unsigned cliser,
const struct header_prot *hp, unsigned rw,
const unsigned char *sample, unsigned char mask[EVP_MAX_BLOCK_LENGTH])
{
EVP_CIPHER_CTX hp_ctx;
int out_len;
EVP_CIPHER_CTX_init(&hp_ctx);
if (EVP_EncryptInit_ex(&hp_ctx, hp->hp_cipher, NULL, hp->hp_buf[cliser], 0)
if (EVP_EncryptInit_ex(&hp_ctx, hp->hp_cipher, NULL, hp->hp_buf[rw], 0)
&& EVP_EncryptUpdate(&hp_ctx, mask, &out_len, sample, 16))
{
assert(out_len >= 5);
@ -304,7 +302,7 @@ gen_hp_mask_aes (struct enc_sess_iquic *enc_sess,
static void
gen_hp_mask_chacha20 (struct enc_sess_iquic *enc_sess,
const struct header_prot *hp, unsigned cliser,
const struct header_prot *hp, unsigned rw,
const unsigned char *sample, unsigned char mask[EVP_MAX_BLOCK_LENGTH])
{
const uint8_t *nonce;
@ -317,19 +315,19 @@ gen_hp_mask_chacha20 (struct enc_sess_iquic *enc_sess,
#endif
nonce = sample + sizeof(counter);
CRYPTO_chacha_20(mask, (unsigned char [5]) { 0, 0, 0, 0, 0, }, 5,
hp->hp_buf[cliser], nonce, counter);
hp->hp_buf[rw], nonce, counter);
}
static void
apply_hp (struct enc_sess_iquic *enc_sess,
const struct header_prot *hp, unsigned cliser,
const struct header_prot *hp,
unsigned char *dst, unsigned packno_off, unsigned packno_len)
{
unsigned char mask[EVP_MAX_BLOCK_LENGTH];
char mask_str[5 * 2 + 1];
hp->hp_gen_mask(enc_sess, hp, cliser, dst + packno_off + 4, mask);
hp->hp_gen_mask(enc_sess, hp, 1, dst + packno_off + 4, mask);
LSQ_DEBUG("apply header protection using mask %s",
HEXSTR(mask, 5, mask_str));
if (enc_sess->esi_flags & ESI_SEND_QL_BITS)
@ -380,7 +378,7 @@ decode_packno (lsquic_packno_t max_packno, lsquic_packno_t packno,
static lsquic_packno_t
strip_hp (struct enc_sess_iquic *enc_sess,
const struct header_prot *hp, unsigned cliser,
const struct header_prot *hp,
const unsigned char *iv, unsigned char *dst, unsigned packno_off,
unsigned *packno_len)
{
@ -390,7 +388,7 @@ strip_hp (struct enc_sess_iquic *enc_sess,
unsigned char mask[EVP_MAX_BLOCK_LENGTH];
char mask_str[5 * 2 + 1];
hp->hp_gen_mask(enc_sess, hp, cliser, iv, mask);
hp->hp_gen_mask(enc_sess, hp, 0, iv, mask);
LSQ_DEBUG("strip header protection using mask %s",
HEXSTR(mask, 5, mask_str));
if (enc_sess->esi_flags & ESI_RECV_QL_BITS)
@ -739,9 +737,6 @@ iquic_esfi_create_client (const char *hostname,
enc_sess->esi_conn = lconn;
enc_sess->esi_ver_neg = ver_neg;
enc_sess->esi_dir[0] = evp_aead_seal;
enc_sess->esi_dir[1] = evp_aead_open;
enc_sess->esi_odcid = *dcid;
enc_sess->esi_flags |= ESI_ODCID;
@ -831,9 +826,6 @@ iquic_esfi_create_server (struct lsquic_engine_public *enpub,
enc_sess->esi_enpub = enpub;
enc_sess->esi_conn = lconn;
enc_sess->esi_dir[0] = evp_aead_open;
enc_sess->esi_dir[1] = evp_aead_seal;
if (odcid)
{
enc_sess->esi_odcid = *odcid;
@ -868,23 +860,31 @@ iquic_esfi_create_server (struct lsquic_engine_public *enpub,
}
static const char *const rw2str[] = { "read", "write", };
typedef char evp_aead_enum_has_expected_values[
(int) evp_aead_open == 0 && (int) evp_aead_seal == 1 ? 1 : -1];
#define rw2dir(rw_) ((enum evp_aead_direction_t) (rw_))
static void
log_crypto_ctx (const struct enc_sess_iquic *enc_sess,
const struct crypto_ctx *ctx, const char *name, int rw)
{
char hexbuf[EVP_MAX_MD_SIZE * 2 + 1];
LSQ_DEBUG("%s %s key: %s", name, rw2str[rw],
HEXSTR(ctx->yk_key_buf, ctx->yk_key_sz, hexbuf));
LSQ_DEBUG("%s %s iv: %s", name, rw2str[rw],
HEXSTR(ctx->yk_iv_buf, ctx->yk_iv_sz, hexbuf));
}
static void
log_crypto_pair (const struct enc_sess_iquic *enc_sess,
const struct crypto_ctx_pair *pair, const char *name)
{
char hexbuf[EVP_MAX_MD_SIZE * 2 + 1];
LSQ_DEBUG("client %s key: %s", name,
HEXSTR(pair->ykp_ctx[0].yk_key_buf, pair->ykp_ctx[0].yk_key_sz,
hexbuf));
LSQ_DEBUG("client %s iv: %s", name,
HEXSTR(pair->ykp_ctx[0].yk_iv_buf, pair->ykp_ctx[0].yk_iv_sz,
hexbuf));
LSQ_DEBUG("server %s key: %s", name,
HEXSTR(pair->ykp_ctx[1].yk_key_buf, pair->ykp_ctx[1].yk_key_sz,
hexbuf));
LSQ_DEBUG("server %s iv: %s", name,
HEXSTR(pair->ykp_ctx[1].yk_iv_buf, pair->ykp_ctx[1].yk_iv_sz,
hexbuf));
log_crypto_ctx(enc_sess, &pair->ykp_ctx[0], name, 0);
log_crypto_ctx(enc_sess, &pair->ykp_ctx[1], name, 1);
}
@ -893,9 +893,9 @@ log_hp (const struct enc_sess_iquic *enc_sess,
const struct header_prot *hp, const char *name)
{
char hexbuf[EVP_MAX_MD_SIZE * 2 + 1];
LSQ_DEBUG("client %s hp: %s", name,
LSQ_DEBUG("read %s hp: %s", name,
HEXSTR(hp->hp_buf[0], hp->hp_sz, hexbuf));
LSQ_DEBUG("server %s hp: %s", name,
LSQ_DEBUG("write %s hp: %s", name,
HEXSTR(hp->hp_buf[1], hp->hp_sz, hexbuf));
}
@ -909,6 +909,7 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid)
struct crypto_ctx_pair *pair;
struct header_prot *hp;
size_t hsk_secret_sz;
unsigned cliser;
unsigned char hsk_secret[EVP_MAX_MD_SIZE];
unsigned char secret[2][SHA256_DIGEST_LENGTH]; /* client, server */
char hexbuf[EVP_MAX_MD_SIZE * 2 + 1];
@ -941,17 +942,22 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid)
lsquic_qhkdf_expand(md, hsk_secret, hsk_secret_sz, CLIENT_LABEL,
CLIENT_LABEL_SZ, secret[0], sizeof(secret[0]));
LSQ_DEBUG("client handshake secret: %s",
HEXSTR(secret[0], sizeof(secret[0]), hexbuf));
if (0 != init_crypto_ctx(&pair->ykp_ctx[0], md, aead, secret[0],
sizeof(secret[0]), enc_sess->esi_dir[0]))
goto err;
lsquic_qhkdf_expand(md, hsk_secret, hsk_secret_sz, SERVER_LABEL,
SERVER_LABEL_SZ, secret[1], sizeof(secret[1]));
LSQ_DEBUG("server handshake secret: %s",
HEXSTR(secret[1], sizeof(secret[1]), hexbuf));
if (0 != init_crypto_ctx(&pair->ykp_ctx[1], md, aead, secret[1],
sizeof(secret[1]), enc_sess->esi_dir[1]))
if (enc_sess->esi_flags & ESI_LOG_SECRETS)
{
LSQ_DEBUG("client handshake secret: %s",
HEXSTR(secret[0], sizeof(secret[0]), hexbuf));
LSQ_DEBUG("server handshake secret: %s",
HEXSTR(secret[1], sizeof(secret[1]), hexbuf));
}
cliser = !!(enc_sess->esi_flags & ESI_SERVER);
if (0 != init_crypto_ctx(&pair->ykp_ctx[!cliser], md, aead, secret[0],
sizeof(secret[0]), rw2dir(!cliser)))
goto err;
if (0 != init_crypto_ctx(&pair->ykp_ctx[cliser], md, aead, secret[1],
sizeof(secret[1]), rw2dir(cliser)))
goto err;
/* [draft-ietf-quic-tls-12] Section 5.6.1: AEAD_AES_128_GCM implies
@ -960,7 +966,7 @@ setup_handshake_keys (struct enc_sess_iquic *enc_sess, const lsquic_cid_t *cid)
hp->hp_cipher = EVP_aes_128_ecb();
hp->hp_gen_mask = gen_hp_mask_aes;
hp->hp_enc_level = ENC_LEV_CLEAR;
derive_hp_secrets(hp, md, aead, sizeof(secret[0]), secret[0], secret[1]);
derive_hp_secrets(hp, md, aead, sizeof(secret[0]), secret[!cliser], secret[cliser]);
if (enc_sess->esi_flags & ESI_LOG_SECRETS)
{
@ -1419,13 +1425,11 @@ struct crypto_params
static int
get_crypto_params (const struct enc_sess_iquic *enc_sess,
struct crypto_params *params)
const SSL_CIPHER *cipher, struct crypto_params *params)
{
const SSL_CIPHER *cipher;
unsigned key_sz, iv_sz;
uint32_t id;
cipher = SSL_get_current_cipher(enc_sess->esi_ssl);
id = SSL_CIPHER_get_id(cipher);
LSQ_DEBUG("Negotiated cipher ID is 0x%"PRIX32, id);
@ -1475,6 +1479,9 @@ get_crypto_params (const struct enc_sess_iquic *enc_sess,
return -1;
}
/* FIXME: figure out why this duplicate check is here and either fix it
* or get rid of it.
*/
if (key_sz > EVP_MAX_KEY_LENGTH)
{
LSQ_DEBUG("PN size %u is too large", key_sz);
@ -1802,7 +1809,7 @@ iquic_esf_encrypt_packet (enc_session_t *enc_session_p,
size_t out_sz, dst_sz;
int header_sz;
int ipv6;
unsigned packno_off, packno_len, cliser;
unsigned packno_off, packno_len;
enum packnum_space pns;
char errbuf[ERR_ERROR_STRING_BUF_LEN];
@ -1810,17 +1817,16 @@ iquic_esf_encrypt_packet (enc_session_t *enc_session_p,
/* TODO Obviously, will need more logic for 0-RTT */
enc_level = pns2enc_level[ pns ];
cliser = !!(enc_sess->esi_flags & ESI_SERVER);
if (enc_level == ENC_LEV_FORW)
{
pair = &enc_sess->esi_pairs[ enc_sess->esi_key_phase ];
crypto_ctx = &pair->ykp_ctx[ cliser ];
crypto_ctx = &pair->ykp_ctx[ 1 ];
hp = &enc_sess->esi_hp;
}
else if (enc_sess->esi_hsk_pairs)
{
pair = &enc_sess->esi_hsk_pairs[ enc_level ];
crypto_ctx = &pair->ykp_ctx[ cliser ];
crypto_ctx = &pair->ykp_ctx[ 1 ];
hp = &enc_sess->esi_hsk_hps[ enc_level ];
}
else
@ -1909,7 +1915,7 @@ iquic_esf_encrypt_packet (enc_session_t *enc_session_p,
const unsigned sample_off = packno_off + 4;
assert(sample_off + IQUIC_TAG_LEN <= dst_sz);
#endif
apply_hp(enc_sess, hp, cliser, dst, packno_off, packno_len);
apply_hp(enc_sess, hp, dst, packno_off, packno_len);
packet_out->po_enc_data = dst;
packet_out->po_enc_data_sz = dst_sz;
@ -1952,7 +1958,7 @@ iquic_esf_decrypt_packet (enc_session_t *enc_session_p,
struct crypto_ctx *crypto_ctx = NULL;
unsigned char nonce_buf[ sizeof(crypto_ctx->yk_iv_buf) + 8 ];
unsigned char *nonce, *begin_xor;
unsigned sample_off, packno_len, cliser, key_phase;
unsigned sample_off, packno_len, key_phase;
enum enc_level enc_level;
enum packnum_space pns;
lsquic_packno_t packno;
@ -2000,10 +2006,9 @@ iquic_esf_decrypt_packet (enc_session_t *enc_session_p,
dec_packin = DECPI_TOO_SHORT;
goto err;
}
cliser = !(enc_sess->esi_flags & ESI_SERVER);
memcpy(dst, packet_in->pi_data, sample_off);
packet_in->pi_packno =
packno = strip_hp(enc_sess, hp, cliser,
packno = strip_hp(enc_sess, hp,
packet_in->pi_data + sample_off,
dst, packet_in->pi_header_sz, &packno_len);
@ -2012,7 +2017,7 @@ iquic_esf_decrypt_packet (enc_session_t *enc_session_p,
key_phase = (dst[0] & 0x04) > 0;
pair = &enc_sess->esi_pairs[ key_phase ];
if (key_phase == enc_sess->esi_key_phase)
crypto_ctx = &pair->ykp_ctx[ cliser ];
crypto_ctx = &pair->ykp_ctx[ 0 ];
else if (!is_valid_packno(
enc_sess->esi_pairs[enc_sess->esi_key_phase].ykp_thresh)
|| packet_in->pi_packno
@ -2020,7 +2025,7 @@ iquic_esf_decrypt_packet (enc_session_t *enc_session_p,
{
const struct ku_label kl = select_ku_label(enc_sess);
lsquic_qhkdf_expand(enc_sess->esi_md,
enc_sess->esi_traffic_secrets[cliser], enc_sess->esi_trasec_sz,
enc_sess->esi_traffic_secrets[0], enc_sess->esi_trasec_sz,
kl.str, kl.len, new_secret, enc_sess->esi_trasec_sz);
if (enc_sess->esi_flags & ESI_LOG_SECRETS)
LSQ_DEBUG("key phase changed to %u, will try decrypting using "
@ -2043,7 +2048,7 @@ iquic_esf_decrypt_packet (enc_session_t *enc_session_p,
}
else
{
crypto_ctx = &pair->ykp_ctx[ cliser ];
crypto_ctx = &pair->ykp_ctx[ 0 ];
if (UNLIKELY(0 == (crypto_ctx->yk_flags & YK_INITED)))
{
LSQ_DEBUG("supposedly older context is not initialized (key "
@ -2058,7 +2063,7 @@ iquic_esf_decrypt_packet (enc_session_t *enc_session_p,
key_phase = 0;
assert(enc_sess->esi_hsk_pairs);
pair = &enc_sess->esi_hsk_pairs[ enc_level ];
crypto_ctx = &pair->ykp_ctx[ cliser ];
crypto_ctx = &pair->ykp_ctx[ 0 ];
if (UNLIKELY(0 == (crypto_ctx->yk_flags & YK_INITED)))
{
LSQ_WARN("decrypt crypto context at level %s not initialized",
@ -2128,21 +2133,21 @@ iquic_esf_decrypt_packet (enc_session_t *enc_session_p,
"keys", key_phase);
const struct ku_label kl = select_ku_label(enc_sess);
pair->ykp_thresh = packet_in->pi_packno;
pair->ykp_ctx[ cliser ] = crypto_ctx_buf;
memcpy(enc_sess->esi_traffic_secrets[ cliser ], new_secret,
pair->ykp_ctx[ 0 ] = crypto_ctx_buf;
memcpy(enc_sess->esi_traffic_secrets[ 0 ], new_secret,
enc_sess->esi_trasec_sz);
lsquic_qhkdf_expand(enc_sess->esi_md,
enc_sess->esi_traffic_secrets[!cliser], enc_sess->esi_trasec_sz,
enc_sess->esi_traffic_secrets[1], enc_sess->esi_trasec_sz,
kl.str, kl.len, new_secret, enc_sess->esi_trasec_sz);
memcpy(enc_sess->esi_traffic_secrets[ !cliser ], new_secret,
memcpy(enc_sess->esi_traffic_secrets[1], new_secret,
enc_sess->esi_trasec_sz);
s = init_crypto_ctx(&pair->ykp_ctx[ !cliser ], enc_sess->esi_md,
s = init_crypto_ctx(&pair->ykp_ctx[1], enc_sess->esi_md,
enc_sess->esi_aead, new_secret, enc_sess->esi_trasec_sz,
evp_aead_seal);
if (s != 0)
{
LSQ_ERROR("could not init seal crypto ctx (key phase)");
cleanup_crypto_ctx(&pair->ykp_ctx[ !cliser ]);
cleanup_crypto_ctx(&pair->ykp_ctx[1]);
/* This is a severe error, abort connection */
enc_sess->esi_conn->cn_if->ci_internal_error(enc_sess->esi_conn,
"crypto ctx failure during key phase shift");
@ -2522,20 +2527,17 @@ typedef char enums_have_the_same_value[
(int) ssl_encryption_application == (int) ENC_LEV_FORW ? 1 : -1];
static int
cry_sm_set_encryption_secret (SSL *ssl, enum ssl_encryption_level_t level,
const uint8_t *read_secret, const uint8_t *write_secret,
size_t secret_len)
set_secret (SSL *ssl, enum ssl_encryption_level_t level,
const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len, int rw)
{
struct enc_sess_iquic *enc_sess;
struct crypto_ctx_pair *pair;
struct header_prot *hp;
struct crypto_params crypa;
int i;
int have_alpn;
const unsigned char *alpn;
unsigned alpn_len;
const enum enc_level enc_level = (enum enc_level) level;
const uint8_t *secrets[2];
char errbuf[ERR_ERROR_STRING_BUF_LEN];
#define hexbuf errbuf
@ -2560,13 +2562,15 @@ cry_sm_set_encryption_secret (SSL *ssl, enum ssl_encryption_level_t level,
}
}
if (0 != get_crypto_params(enc_sess, &crypa))
if (0 != get_crypto_params(enc_sess, cipher, &crypa))
return 0;
/*
if (enc_sess->esi_flags & ESI_SERVER)
secrets[0] = read_secret, secrets[1] = write_secret;
else
secrets[0] = write_secret, secrets[1] = read_secret;
*/
if (enc_level < ENC_LEV_FORW)
{
@ -2579,39 +2583,45 @@ cry_sm_set_encryption_secret (SSL *ssl, enum ssl_encryption_level_t level,
pair = &enc_sess->esi_pairs[0];
hp = &enc_sess->esi_hp;
enc_sess->esi_trasec_sz = secret_len;
memcpy(enc_sess->esi_traffic_secrets[0], secrets[0], secret_len);
memcpy(enc_sess->esi_traffic_secrets[1], secrets[1], secret_len);
memcpy(enc_sess->esi_traffic_secrets[rw], secret, secret_len);
enc_sess->esi_md = crypa.md;
enc_sess->esi_aead = crypa.aead;
}
pair->ykp_thresh = IQUIC_INVALID_PACKNO;
LSQ_DEBUG("set encryption for level %u", enc_level);
for (i = 1; i >= 0; --i)
{
if (secrets[i])
{
if (enc_sess->esi_flags & ESI_LOG_SECRETS)
LSQ_DEBUG("new %s secret: %s", i ? "server" : "client",
HEXSTR(secrets[i], secret_len, hexbuf));
if (0 != init_crypto_ctx(&pair->ykp_ctx[i], crypa.md,
crypa.aead, secrets[i], secret_len, enc_sess->esi_dir[i]))
goto err;
}
else
assert(level == ssl_encryption_early_data);
}
if (enc_sess->esi_flags & ESI_LOG_SECRETS)
LSQ_DEBUG("set %s secret for level %u: %s", rw2str[rw], enc_level,
HEXSTR(secret, secret_len, hexbuf));
else
LSQ_DEBUG("set %s for level %u", rw2str[rw], enc_level);
hp->hp_enc_level = enc_level;
hp->hp_cipher = crypa.hp;
hp->hp_gen_mask = crypa.gen_hp_mask;
derive_hp_secrets(hp, crypa.md, crypa.aead, secret_len, secrets[0],
secrets[1]);
if (0 != init_crypto_ctx(&pair->ykp_ctx[rw], crypa.md,
crypa.aead, secret, secret_len, rw2dir(rw)))
goto err;
if (pair->ykp_ctx[!rw].yk_flags & YK_INITED)
{
/* Sanity check that the two sides end up with the same header
* protection logic, as they should.
*/
assert(hp->hp_cipher == crypa.hp);
assert(hp->hp_gen_mask == crypa.gen_hp_mask);
}
else
{
hp->hp_enc_level = enc_level;
hp->hp_cipher = crypa.hp;
hp->hp_gen_mask = crypa.gen_hp_mask;
hp->hp_sz = EVP_AEAD_key_length(crypa.aead);
}
lsquic_qhkdf_expand(crypa.md, secret, secret_len, PN_LABEL, PN_LABEL_SZ,
hp->hp_buf[rw], hp->hp_sz);
if (enc_sess->esi_flags & ESI_LOG_SECRETS)
{
log_crypto_pair(enc_sess, pair, "new");
log_hp(enc_sess, hp, "new");
log_crypto_ctx(enc_sess, &pair->ykp_ctx[rw], "new", rw);
LSQ_DEBUG("%s hp: %s", rw2str[rw],
HEXSTR(hp->hp_buf[rw], hp->hp_sz, hexbuf));
}
return 1;
@ -2624,6 +2634,22 @@ cry_sm_set_encryption_secret (SSL *ssl, enum ssl_encryption_level_t level,
}
static int
cry_sm_set_read_secret (SSL *ssl, enum ssl_encryption_level_t level,
const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len)
{
return set_secret(ssl, level, cipher, secret, secret_len, 0);
}
static int
cry_sm_set_write_secret (SSL *ssl, enum ssl_encryption_level_t level,
const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len)
{
return set_secret(ssl, level, cipher, secret, secret_len, 1);
}
static int
cry_sm_write_message (SSL *ssl, enum ssl_encryption_level_t level,
const uint8_t *data, size_t len)
@ -2721,7 +2747,8 @@ cry_sm_send_alert (SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert)
static const SSL_QUIC_METHOD cry_quic_method =
{
.set_encryption_secrets = cry_sm_set_encryption_secret,
.set_read_secret = cry_sm_set_read_secret,
.set_write_secret = cry_sm_set_write_secret,
.add_handshake_data = cry_sm_write_message,
.flush_flight = cry_sm_flush_flight,
.send_alert = cry_sm_send_alert,

View File

@ -1447,6 +1447,9 @@ lsquic_engine_destroy (lsquic_engine_t *engine)
}
lsquic_hash_destroy(engine->conns_hash);
while ((conn = lsquic_attq_pop(engine->attq, UINT64_MAX)))
(void) engine_decref_conn(engine, conn, LSCONN_ATTQ);
assert(0 == engine->n_conns);
assert(0 == engine->mini_conns_count);
if (engine->pr_queue)

View File

@ -591,9 +591,10 @@ wipe_path (struct ietf_full_conn *conn, unsigned path_id)
static void
path_chal_alarm_expired (enum alarm_id al_id, void *ctx,
lsquic_time_t expiry, lsquic_time_t now, unsigned path_id)
lsquic_time_t expiry, lsquic_time_t now)
{
struct ietf_full_conn *const conn = (struct ietf_full_conn *) ctx;
const unsigned path_id = al_id - AL_PATH_CHAL;
struct conn_path *const copath = &conn->ifc_paths[path_id];
if (copath->cop_n_chals < sizeof(copath->cop_path_chals)
@ -614,22 +615,6 @@ path_chal_alarm_expired (enum alarm_id al_id, void *ctx,
}
static void
path_chal_0_alarm_expired (enum alarm_id al_id, void *ctx,
lsquic_time_t expiry, lsquic_time_t now)
{
path_chal_alarm_expired(al_id, ctx, expiry, now, 0);
}
static void
path_chal_1_alarm_expired (enum alarm_id al_id, void *ctx,
lsquic_time_t expiry, lsquic_time_t now)
{
path_chal_alarm_expired(al_id, ctx, expiry, now, 1);
}
/* Sending DATA_BLOCKED and STREAM_DATA_BLOCKED frames is a way to elicit
* incoming packets from peer when it is too slow to read data. This is
* recommended by [draft-ietf-quic-transport-25] Section 4.1.
@ -670,10 +655,10 @@ blocked_ka_alarm_expired (enum alarm_id al_id, void *ctx,
static int
migra_is_on (const struct ietf_full_conn *conn)
migra_is_on (const struct ietf_full_conn *conn, unsigned path_id)
{
return (conn->ifc_send_flags & SF_SEND_PATH_CHAL_ALL)
|| lsquic_alarmset_are_set(&conn->ifc_alset, ALBIT_PATH_CHAL_0|ALBIT_PATH_CHAL_1);
return (conn->ifc_send_flags & (SF_SEND_PATH_CHAL << path_id))
|| lsquic_alarmset_is_set(&conn->ifc_alset, AL_PATH_CHAL + path_id);
}
@ -682,7 +667,7 @@ migra_begin (struct ietf_full_conn *conn, struct conn_path *copath,
struct dcid_elem *dce, const struct sockaddr *dest_sa,
const struct transport_params *params)
{
assert(!(migra_is_on(conn)));
assert(!(migra_is_on(conn, copath - conn->ifc_paths)));
dce->de_flags |= DE_ASSIGNED;
copath->cop_flags |= COP_INITIALIZED;
@ -1126,8 +1111,10 @@ ietf_full_conn_init (struct ietf_full_conn *conn,
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PING, ping_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_HANDSHAKE, handshake_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_CID_THROT, cid_throt_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PATH_CHAL_0, path_chal_0_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PATH_CHAL_1, path_chal_1_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PATH_CHAL_0, path_chal_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PATH_CHAL_1, path_chal_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PATH_CHAL_2, path_chal_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PATH_CHAL_3, path_chal_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_BLOCKED_KA, blocked_ka_alarm_expired, conn);
lsquic_rechist_init(&conn->ifc_rechist[PNS_INIT], &conn->ifc_conn, 1);
lsquic_rechist_init(&conn->ifc_rechist[PNS_HSK], &conn->ifc_conn, 1);
@ -5461,11 +5448,11 @@ process_retire_connection_id_frame (struct ietf_full_conn *conn,
cce = find_cce_by_cid(conn, &packet_in->pi_dcid);
if (cce)
{
cce->cce_flags |= CCE_USED;
lconn->cn_cur_cce_idx = cce - lconn->cn_cces;
LSQ_DEBUGC("current SCID was retired; set current SCID to "
"%"CID_FMT" based on DCID in incoming packet",
CID_BITS(&packet_in->pi_dcid));
cce->cce_flags |= CCE_USED;
lconn->cn_cur_cce_idx = cce - lconn->cn_cces;
}
else
LSQ_WARN("current SCID was retired; no new SCID candidate");
@ -6310,7 +6297,7 @@ process_regular_packet (struct ietf_full_conn *conn,
if (packet_in->pi_path_id != conn->ifc_cur_path_id
&& 0 == (conn->ifc_flags & IFC_SERVER)
&& !(packet_in->pi_path_id == conn->ifc_mig_path_id
&& migra_is_on(conn)))
&& migra_is_on(conn, conn->ifc_mig_path_id)))
{
/* The "known server address" is recorded in the current path. */
switch ((NP_IS_IPv6(CUR_NPATH(conn)) << 1) |

View File

@ -4140,6 +4140,7 @@ update_type_hist_and_check (const struct lsquic_stream *stream,
0123, /* HD+ */
012, /* HD */
01, /* H */
013, /* H+ */ /* Really HH, but we don't record it like this */
01231, /* HD+H */
0121, /* HDH */
};