"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/liblsquic/lsquic_enc_sess_ietf.c" between
lsquic-2.22.1.tar.gz and lsquic-2.23.1.tar.gz

About: LSQUIC is LiteSpeed’s QUIC and HTTP/3 Library. A hint: HTTP/3 uses QUIC as the underlying transport protocol instead of TCP.

lsquic_enc_sess_ietf.c  (lsquic-2.22.1):lsquic_enc_sess_ietf.c  (lsquic-2.23.1)
skipping to change at line 110 skipping to change at line 110
static struct stack_st_X509 * static struct stack_st_X509 *
iquic_esf_get_server_cert_chain (enc_session_t *); iquic_esf_get_server_cert_chain (enc_session_t *);
static void static void
maybe_drop_SSL (struct enc_sess_iquic *); maybe_drop_SSL (struct enc_sess_iquic *);
static void static void
no_sess_ticket (enum alarm_id alarm_id, void *ctx, no_sess_ticket (enum alarm_id alarm_id, void *ctx,
lsquic_time_t expiry, lsquic_time_t now); lsquic_time_t expiry, lsquic_time_t now);
static int
iquic_new_session_cb (SSL *, SSL_SESSION *);
static void
keylog_callback (const SSL *, const char *);
static enum ssl_verify_result_t
verify_server_cert_callback (SSL *, uint8_t *out_alert);
static void
maybe_setup_key_logging (struct enc_sess_iquic *);
static void
iquic_esfi_destroy (enc_session_t *);
#define SAMPLE_SZ 16 #define SAMPLE_SZ 16
typedef void (*gen_hp_mask_f)(struct enc_sess_iquic *, typedef void (*gen_hp_mask_f)(struct enc_sess_iquic *,
struct header_prot *, unsigned rw, struct header_prot *, unsigned rw,
const unsigned char *sample, unsigned char *mask, size_t sz); const unsigned char *sample, unsigned char *mask, size_t sz);
#define CHACHA20_KEY_LENGTH 32 #define CHACHA20_KEY_LENGTH 32
struct header_prot struct header_prot
{ {
skipping to change at line 220 skipping to change at line 235
*/ */
struct crypto_ctx_pair * struct crypto_ctx_pair *
esi_hsk_pairs; esi_hsk_pairs;
struct header_prot *esi_hsk_hps; struct header_prot *esi_hsk_hps;
lsquic_packno_t esi_max_packno[N_PNS]; lsquic_packno_t esi_max_packno[N_PNS];
lsquic_cid_t esi_odcid; lsquic_cid_t esi_odcid;
lsquic_cid_t esi_rscid; /* Retry SCID */ lsquic_cid_t esi_rscid; /* Retry SCID */
lsquic_cid_t esi_iscid; /* Initial SCID */ lsquic_cid_t esi_iscid; /* Initial SCID */
unsigned esi_key_phase; unsigned esi_key_phase;
enum { enum {
ESI_INITIALIZED = 1 << 0, ESI_UNUSED0 = 1 << 0,
ESI_LOG_SECRETS = 1 << 1, ESI_LOG_SECRETS = 1 << 1,
ESI_HANDSHAKE_OK = 1 << 2, ESI_HANDSHAKE_OK = 1 << 2,
ESI_ODCID = 1 << 3, ESI_ODCID = 1 << 3,
ESI_ON_WRITE = 1 << 4, ESI_ON_WRITE = 1 << 4,
ESI_SERVER = 1 << 5, ESI_SERVER = 1 << 5,
ESI_USE_SSL_TICKET = 1 << 6, ESI_USE_SSL_TICKET = 1 << 6,
ESI_HAVE_PEER_TP = 1 << 7, ESI_HAVE_PEER_TP = 1 << 7,
ESI_ALPN_CHECKED = 1 << 8, ESI_ALPN_CHECKED = 1 << 8,
ESI_CACHED_INFO = 1 << 9, ESI_CACHED_INFO = 1 << 9,
ESI_HSK_CONFIRMED= 1 << 10, ESI_HSK_CONFIRMED= 1 << 10,
ESI_WANT_TICKET = 1 << 11, ESI_WANT_TICKET = 1 << 11,
ESI_RECV_QL_BITS = 1 << 12, ESI_RECV_QL_BITS = 1 << 12,
ESI_SEND_QL_BITS = 1 << 13, ESI_SEND_QL_BITS = 1 << 13,
ESI_RSCID = 1 << 14, ESI_RSCID = 1 << 14,
ESI_ISCID = 1 << 15, ESI_ISCID = 1 << 15,
ESI_RETRY = 1 << 16, /* Connection was retried */ ESI_RETRY = 1 << 16, /* Connection was retried */
ESI_MAX_PACKNO_INIT = 1 << 17, ESI_MAX_PACKNO_INIT = 1 << 17,
ESI_MAX_PACKNO_HSK = ESI_MAX_PACKNO_INIT << PNS_HSK, ESI_MAX_PACKNO_HSK = ESI_MAX_PACKNO_INIT << PNS_HSK,
ESI_MAX_PACKNO_APP = ESI_MAX_PACKNO_INIT << PNS_APP, ESI_MAX_PACKNO_APP = ESI_MAX_PACKNO_INIT << PNS_APP,
ESI_HAVE_0RTT_TP = 1 << 20,
} esi_flags; } esi_flags;
enum enc_level esi_last_w; enum enc_level esi_last_w;
unsigned esi_trasec_sz; unsigned esi_trasec_sz;
char *esi_hostname;
void *esi_keylog_handle; void *esi_keylog_handle;
#ifndef NDEBUG #ifndef NDEBUG
char *esi_sni_bypass; char *esi_sni_bypass;
#endif #endif
const unsigned char *esi_alpn; const unsigned char *esi_alpn;
unsigned char *esi_sess_resume_buf;
size_t esi_sess_resume_sz;
/* Need MD and AEAD for key rotation */ /* Need MD and AEAD for key rotation */
const EVP_MD *esi_md; const EVP_MD *esi_md;
const EVP_AEAD *esi_aead; const EVP_AEAD *esi_aead;
struct { struct {
const char *cipher_name; const char *cipher_name;
int alg_bits; int alg_bits;
} esi_cached_info; } esi_cached_info;
/* Secrets are kept for key rotation */ /* Secrets are kept for key rotation */
unsigned char esi_traffic_secrets[2][EVP_MAX_KEY_LENGTH]; unsigned char esi_traffic_secrets[2][EVP_MAX_KEY_LENGTH];
/* We never use the first two levels, so it seems we could reduce the /* We never use the first two levels, so it seems we could reduce the
skipping to change at line 276 skipping to change at line 289
struct lsquic_alarmset struct lsquic_alarmset
*esi_alset; *esi_alset;
unsigned esi_max_streams_uni; unsigned esi_max_streams_uni;
unsigned esi_hp_batch_idx; unsigned esi_hp_batch_idx;
unsigned esi_hp_batch_packno_len[HP_BATCH_SIZE]; unsigned esi_hp_batch_packno_len[HP_BATCH_SIZE];
unsigned esi_hp_batch_packno_off[HP_BATCH_SIZE]; unsigned esi_hp_batch_packno_off[HP_BATCH_SIZE];
struct lsquic_packet_out * struct lsquic_packet_out *
esi_hp_batch_packets[HP_BATCH_SIZE]; esi_hp_batch_packets[HP_BATCH_SIZE];
unsigned char esi_hp_batch_samples[HP_BATCH_SIZE][SAMPLE_SZ]; unsigned char esi_hp_batch_samples[HP_BATCH_SIZE][SAMPLE_SZ];
unsigned char esi_grease; unsigned char esi_grease;
signed char esi_have_forw;
}; };
static void static void
gen_hp_mask_aes (struct enc_sess_iquic *enc_sess, gen_hp_mask_aes (struct enc_sess_iquic *enc_sess,
struct header_prot *hp, unsigned rw, struct header_prot *hp, unsigned rw,
const unsigned char *sample, unsigned char *mask, size_t sz) const unsigned char *sample, unsigned char *mask, size_t sz)
{ {
int out_len; int out_len;
if (EVP_EncryptUpdate(&hp->hp_u.cipher_ctx[rw], mask, &out_len, sample, sz)) if (EVP_EncryptUpdate(&hp->hp_u.cipher_ctx[rw], mask, &out_len, sample, sz))
skipping to change at line 683 skipping to change at line 697
} while (0) } while (0)
#else #else
#define READ_NUM(var_, ptr_) do { \ #define READ_NUM(var_, ptr_) do { \
memcpy(&var_, ptr_, sizeof(var_)); \ memcpy(&var_, ptr_, sizeof(var_)); \
ptr_ += sizeof(var_); \ ptr_ += sizeof(var_); \
} while (0) } while (0)
#endif #endif
static SSL_SESSION * static SSL_SESSION *
maybe_create_SSL_SESSION (struct enc_sess_iquic *enc_sess, maybe_create_SSL_SESSION (struct enc_sess_iquic *enc_sess,
const SSL_CTX *ssl_ctx) const SSL_CTX *ssl_ctx, const unsigned char *sess_resume,
size_t sess_resume_sz)
{ {
SSL_SESSION *ssl_session; SSL_SESSION *ssl_session;
lsquic_ver_tag_t ver_tag; lsquic_ver_tag_t ver_tag;
enum lsquic_version quic_ver; enum lsquic_version quic_ver;
uint32_t rtt_ver, ticket_sz, trapa_sz; uint32_t rtt_ver, ticket_sz, trapa_sz;
const unsigned char *ticket_buf, *trapa_buf, *p; const unsigned char *ticket_buf, *trapa_buf, *p;
const unsigned char *const end const unsigned char *const end = sess_resume + sess_resume_sz;
= enc_sess->esi_sess_resume_buf + enc_sess->esi_sess_resume_
sz;
if (enc_sess->esi_sess_resume_sz if (sess_resume_sz < sizeof(ver_tag) + sizeof(rtt_ver) + sizeof(ticket_sz))
< sizeof(ver_tag) + sizeof(rtt_ver) + sizeof(ticket_sz))
{ {
LSQ_DEBUG("rtt buf too short"); LSQ_DEBUG("rtt buf too short");
return NULL; return NULL;
} }
p = enc_sess->esi_sess_resume_buf; p = sess_resume;
memcpy(&ver_tag, p, sizeof(ver_tag)); memcpy(&ver_tag, p, sizeof(ver_tag));
p += sizeof(ver_tag); p += sizeof(ver_tag);
quic_ver = lsquic_tag2ver(ver_tag); quic_ver = lsquic_tag2ver(ver_tag);
if (quic_ver != enc_sess->esi_ver_neg->vn_ver) if (quic_ver != enc_sess->esi_ver_neg->vn_ver)
{ {
LSQ_DEBUG("negotiated version %s does not match that in the session " LSQ_DEBUG("negotiated version %s does not match that in the session "
"resumption nfo buffer", "resumption nfo buffer",
lsquic_ver2str[enc_sess->esi_ver_neg->vn_ver]); lsquic_ver2str[enc_sess->esi_ver_neg->vn_ver]);
return NULL; return NULL;
} }
skipping to change at line 747 skipping to change at line 760
READ_NUM(trapa_sz, p); READ_NUM(trapa_sz, p);
if (p + trapa_sz > end) if (p + trapa_sz > end)
{ {
LSQ_WARN("truncated trapa buffer"); LSQ_WARN("truncated trapa buffer");
return NULL; return NULL;
} }
trapa_buf = p; trapa_buf = p;
p += trapa_sz; p += trapa_sz;
assert(p == end); assert(p == end);
(void) /* TODO */ trapa_buf;
ssl_session = SSL_SESSION_from_bytes(ticket_buf, ticket_sz, ssl_ctx); ssl_session = SSL_SESSION_from_bytes(ticket_buf, ticket_sz, ssl_ctx);
if (!ssl_session) if (!ssl_session)
{ {
LSQ_WARN("SSL_SESSION could not be parsed out"); LSQ_WARN("SSL_SESSION could not be parsed out");
return NULL; return NULL;
} }
if (SSL_SESSION_early_data_capable(ssl_session))
{
if (0 > (quic_ver == LSQVER_ID27 ? lsquic_tp_decode_27
: lsquic_tp_decode)(trapa_buf, trapa_sz, 1,
&enc_sess->esi_peer_tp))
{
SSL_SESSION_free(ssl_session);
LSQ_WARN("cannot parse stored transport parameters");
return NULL;
}
LSQ_DEBUG("early data capable, will try 0-RTT");
enc_sess->esi_flags |= ESI_HAVE_0RTT_TP;
}
else
LSQ_DEBUG("early data not capable -- not trying 0-RTT");
LSQ_INFO("instantiated SSL_SESSION from serialized buffer"); LSQ_INFO("instantiated SSL_SESSION from serialized buffer");
return ssl_session; return ssl_session;
} }
static void static void
init_frals (struct enc_sess_iquic *enc_sess) init_frals (struct enc_sess_iquic *enc_sess)
{ {
struct frab_list *fral; struct frab_list *fral;
for (fral = enc_sess->esi_frals; fral < enc_sess->esi_frals for (fral = enc_sess->esi_frals; fral < enc_sess->esi_frals
skipping to change at line 780 skipping to change at line 807
static enc_session_t * static enc_session_t *
iquic_esfi_create_client (const char *hostname, iquic_esfi_create_client (const char *hostname,
struct lsquic_engine_public *enpub, struct lsquic_conn *lconn, struct lsquic_engine_public *enpub, struct lsquic_conn *lconn,
const lsquic_cid_t *dcid, const struct ver_neg *ver_neg, const lsquic_cid_t *dcid, const struct ver_neg *ver_neg,
void *crypto_streams[4], const struct crypto_stream_if *cryst_if, void *crypto_streams[4], const struct crypto_stream_if *cryst_if,
const unsigned char *sess_resume, size_t sess_resume_sz, const unsigned char *sess_resume, size_t sess_resume_sz,
struct lsquic_alarmset *alset, unsigned max_streams_uni) struct lsquic_alarmset *alset, unsigned max_streams_uni)
{ {
struct enc_sess_iquic *enc_sess; struct enc_sess_iquic *enc_sess;
SSL_CTX *ssl_ctx = NULL;
SSL_SESSION *ssl_session;
const struct alpn_map *am;
int transpa_len;
char errbuf[ERR_ERROR_STRING_BUF_LEN];
unsigned char trans_params[0x80
#if LSQUIC_TEST_QUANTUM_READINESS
+ 4 + lsquic_tp_get_quantum_sz()
#endif
];
fiu_return_on("enc_sess_ietf/create_client", NULL); fiu_return_on("enc_sess_ietf/create_client", NULL);
enc_sess = calloc(1, sizeof(*enc_sess)); enc_sess = calloc(1, sizeof(*enc_sess));
if (!enc_sess) if (!enc_sess)
return NULL; return NULL;
if (hostname)
{
enc_sess->esi_hostname = strdup(hostname);
if (!enc_sess->esi_hostname)
{
free(enc_sess);
return NULL;
}
}
else
enc_sess->esi_hostname = NULL;
enc_sess->esi_enpub = enpub; enc_sess->esi_enpub = enpub;
enc_sess->esi_streams = crypto_streams; enc_sess->esi_streams = crypto_streams;
enc_sess->esi_cryst_if = cryst_if; enc_sess->esi_cryst_if = cryst_if;
enc_sess->esi_conn = lconn; enc_sess->esi_conn = lconn;
enc_sess->esi_ver_neg = ver_neg; enc_sess->esi_ver_neg = ver_neg;
enc_sess->esi_odcid = *dcid; enc_sess->esi_odcid = *dcid;
enc_sess->esi_flags |= ESI_ODCID; enc_sess->esi_flags |= ESI_ODCID;
enc_sess->esi_grease = 0xFF; enc_sess->esi_grease = 0xFF;
skipping to change at line 829 skipping to change at line 854
} }
init_frals(enc_sess); init_frals(enc_sess);
if (0 != setup_handshake_keys(enc_sess, dcid)) if (0 != setup_handshake_keys(enc_sess, dcid))
{ {
free(enc_sess); free(enc_sess);
return NULL; return NULL;
} }
/* Have to wait until the call to init_client() -- this is when the enc_sess->esi_max_streams_uni = max_streams_uni;
* result of version negotiation is known.
*/ if (enc_sess->esi_enpub->enp_alpn)
enc_sess->esi_alpn = enc_sess->esi_enpub->enp_alpn;
else if (enc_sess->esi_enpub->enp_flags & ENPUB_HTTP)
{
for (am = s_h3_alpns; am < s_h3_alpns + sizeof(s_h3_alpns)
/ sizeof(s_h3_alpns[0]); ++am)
if (am->version == enc_sess->esi_ver_neg->vn_ver)
goto alpn_selected;
LSQ_ERROR("version %s has no matching ALPN",
lsquic_ver2str[enc_sess->esi_ver_neg->vn_ver]);
goto err;
alpn_selected:
enc_sess->esi_alpn = am->alpn;
}
LSQ_DEBUG("Create new SSL_CTX");
ssl_ctx = SSL_CTX_new(TLS_method());
if (!ssl_ctx)
{
LSQ_ERROR("cannot create SSL context: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
SSL_CTX_set_default_verify_paths(ssl_ctx);
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_CLIENT);
if (enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info)
SSL_CTX_sess_set_new_cb(ssl_ctx, iquic_new_session_cb);
if (enc_sess->esi_enpub->enp_kli)
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
if (enc_sess->esi_enpub->enp_verify_cert
|| LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)
|| LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG))
SSL_CTX_set_custom_verify(ssl_ctx, SSL_VERIFY_PEER,
verify_server_cert_callback);
SSL_CTX_set_early_data_enabled(ssl_ctx, 1);
enc_sess->esi_ssl = SSL_new(ssl_ctx);
if (!enc_sess->esi_ssl)
{
LSQ_ERROR("cannot create SSL object: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
transpa_len = gen_trans_params(enc_sess, trans_params,
sizeof(trans_params));
if (transpa_len < 0)
{
goto err;
}
if (1 != SSL_set_quic_transport_params(enc_sess->esi_ssl, trans_params,
transpa_len))
{
LSQ_ERROR("cannot set QUIC transport params: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
if (!(SSL_set_quic_method(enc_sess->esi_ssl, &cry_quic_method)))
{
LSQ_INFO("could not set stream method");
goto err;
}
maybe_setup_key_logging(enc_sess);
if (enc_sess->esi_alpn &&
0 != SSL_set_alpn_protos(enc_sess->esi_ssl, enc_sess->esi_alpn,
enc_sess->esi_alpn[0] + 1))
{
LSQ_ERROR("cannot set ALPN: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
if (1 != SSL_set_tlsext_host_name(enc_sess->esi_ssl, hostname))
{
LSQ_ERROR("cannot set hostname: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
if (sess_resume && sess_resume_sz) if (sess_resume && sess_resume_sz)
{ {
enc_sess->esi_sess_resume_buf = malloc(sess_resume_sz); ssl_session = maybe_create_SSL_SESSION(enc_sess, ssl_ctx,
if (enc_sess->esi_sess_resume_buf) sess_resume, sess_resume_sz);
if (ssl_session)
{ {
memcpy(enc_sess->esi_sess_resume_buf, sess_resume, sess_resume_sz); (void) /* This only ever returns 1: */
enc_sess->esi_sess_resume_sz = sess_resume_sz; SSL_set_session(enc_sess->esi_ssl, ssl_session);
SSL_SESSION_free(ssl_session);
ssl_session = NULL;
enc_sess->esi_flags |= ESI_USE_SSL_TICKET;
} }
else
enc_sess->esi_sess_resume_sz = 0;
}
else
{
enc_sess->esi_sess_resume_buf = NULL;
enc_sess->esi_sess_resume_sz = 0;
} }
SSL_set_ex_data(enc_sess->esi_ssl, s_idx, enc_sess);
SSL_set_connect_state(enc_sess->esi_ssl);
if (enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info) if (enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info)
enc_sess->esi_flags |= ESI_WANT_TICKET; enc_sess->esi_flags |= ESI_WANT_TICKET;
enc_sess->esi_alset = alset; enc_sess->esi_alset = alset;
lsquic_alarmset_init_alarm(enc_sess->esi_alset, AL_SESS_TICKET, lsquic_alarmset_init_alarm(enc_sess->esi_alset, AL_SESS_TICKET,
no_sess_ticket, enc_sess); no_sess_ticket, enc_sess);
enc_sess->esi_max_streams_uni = max_streams_uni; SSL_CTX_free(ssl_ctx);
return enc_sess; return enc_sess;
err:
if (enc_sess)
iquic_esfi_destroy(enc_sess);
if (ssl_ctx)
SSL_CTX_free(ssl_ctx);
return NULL;
} }
static void static void
iquic_esfi_set_streams (enc_session_t *enc_session_p, iquic_esfi_set_streams (enc_session_t *enc_session_p,
void *(crypto_streams)[4], const struct crypto_stream_if *cryst_if) void *(crypto_streams)[4], const struct crypto_stream_if *cryst_if)
{ {
struct enc_sess_iquic *const enc_sess = enc_session_p; struct enc_sess_iquic *const enc_sess = enc_session_p;
enc_sess->esi_streams = crypto_streams; enc_sess->esi_streams = crypto_streams;
enc_sess->esi_cryst_if = cryst_if; enc_sess->esi_cryst_if = cryst_if;
} }
skipping to change at line 1212 skipping to change at line 1325
struct enc_sess_iquic *const enc_sess = enc_session_p; struct enc_sess_iquic *const enc_sess = enc_session_p;
enc_sess->esi_conn = lconn; enc_sess->esi_conn = lconn;
LSQ_DEBUG("updated conn reference"); LSQ_DEBUG("updated conn reference");
} }
static int static int
iquic_esfi_init_server (enc_session_t *enc_session_p) iquic_esfi_init_server (enc_session_t *enc_session_p)
{ {
struct enc_sess_iquic *const enc_sess = enc_session_p; struct enc_sess_iquic *const enc_sess = enc_session_p;
const struct alpn_map *am; const struct alpn_map *am;
unsigned quic_ctx_idx;
int transpa_len; int transpa_len;
SSL_CTX *ssl_ctx = NULL; SSL_CTX *ssl_ctx = NULL;
union { union {
char errbuf[ERR_ERROR_STRING_BUF_LEN]; char errbuf[ERR_ERROR_STRING_BUF_LEN];
unsigned char trans_params[sizeof(struct transport_params) unsigned char trans_params[sizeof(struct transport_params)
#if LSQUIC_TEST_QUANTUM_READINESS #if LSQUIC_TEST_QUANTUM_READINESS
+ 4 + lsquic_tp_get_quantum_sz() + 4 + lsquic_tp_get_quantum_sz()
#endif #endif
]; ];
} u; } u;
skipping to change at line 1257 skipping to change at line 1371
{ {
LSQ_ERROR("cannot create SSL object: %s", LSQ_ERROR("cannot create SSL object: %s",
ERR_error_string(ERR_get_error(), u.errbuf)); ERR_error_string(ERR_get_error(), u.errbuf));
return -1; return -1;
} }
if (!(SSL_set_quic_method(enc_sess->esi_ssl, &cry_quic_method))) if (!(SSL_set_quic_method(enc_sess->esi_ssl, &cry_quic_method)))
{ {
LSQ_INFO("could not set stream method"); LSQ_INFO("could not set stream method");
return -1; return -1;
} }
/* TODO: set to transport parameter string instead of the constant string */ quic_ctx_idx = enc_sess->esi_conn->cn_version == LSQVER_ID27 ? 0 : 1;
if (!SSL_set_quic_early_data_context(enc_sess->esi_ssl, if (!SSL_set_quic_early_data_context(enc_sess->esi_ssl,
(unsigned char *) "lsquic", 6)) enc_sess->esi_enpub->enp_quic_ctx_buf[quic_ctx_idx],
enc_sess->esi_enpub->enp_quic_ctx_sz[quic_ctx_idx]))
{ {
LSQ_INFO("could not set early data context"); LSQ_INFO("could not set early data context");
return -1; return -1;
} }
maybe_setup_key_logging(enc_sess); maybe_setup_key_logging(enc_sess);
if (!enc_sess->esi_enpub->enp_lookup_cert && enc_sess->esi_keylog_handle) if (!enc_sess->esi_enpub->enp_lookup_cert && enc_sess->esi_keylog_handle)
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback); SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
transpa_len = gen_trans_params(enc_sess, u.trans_params, transpa_len = gen_trans_params(enc_sess, u.trans_params,
sizeof(u.trans_params)); sizeof(u.trans_params));
skipping to change at line 1287 skipping to change at line 1402
ERR_error_string(ERR_get_error(), u.errbuf)); ERR_error_string(ERR_get_error(), u.errbuf));
return -1; return -1;
} }
SSL_clear_options(enc_sess->esi_ssl, SSL_OP_NO_TLSv1_3); SSL_clear_options(enc_sess->esi_ssl, SSL_OP_NO_TLSv1_3);
if (enc_sess->esi_enpub->enp_lookup_cert) if (enc_sess->esi_enpub->enp_lookup_cert)
SSL_set_cert_cb(enc_sess->esi_ssl, iquic_lookup_cert, enc_sess); SSL_set_cert_cb(enc_sess->esi_ssl, iquic_lookup_cert, enc_sess);
SSL_set_ex_data(enc_sess->esi_ssl, s_idx, enc_sess); SSL_set_ex_data(enc_sess->esi_ssl, s_idx, enc_sess);
SSL_set_accept_state(enc_sess->esi_ssl); SSL_set_accept_state(enc_sess->esi_ssl);
LSQ_DEBUG("initialized server enc session"); LSQ_DEBUG("initialized server enc session");
enc_sess->esi_flags |= ESI_INITIALIZED;
return 0; return 0;
} }
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
#define WRITE_NUM(var_, val_, ptr_) do { \ #define WRITE_NUM(var_, val_, ptr_) do { \
var_ = (val_); \ var_ = (val_); \
var_ = bswap_32(var_); \ var_ = bswap_32(var_); \
memcpy((ptr_), &var_, sizeof(var_)); \ memcpy((ptr_), &var_, sizeof(var_)); \
ptr_ += sizeof(var_); \ ptr_ += sizeof(var_); \
} while (0) } while (0)
skipping to change at line 1383 skipping to change at line 1497
LSQ_DEBUG("generated %zu bytes of session resumption buffer", buf_sz); LSQ_DEBUG("generated %zu bytes of session resumption buffer", buf_sz);
enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info(enc_sess->esi_conn, enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info(enc_sess->esi_conn,
buf, buf_sz); buf, buf_sz);
free(buf); free(buf);
enc_sess->esi_flags &= ~ESI_WANT_TICKET; enc_sess->esi_flags &= ~ESI_WANT_TICKET;
lsquic_alarmset_unset(enc_sess->esi_alset, AL_SESS_TICKET); lsquic_alarmset_unset(enc_sess->esi_alset, AL_SESS_TICKET);
return 0; return 0;
} }
static int
init_client (struct enc_sess_iquic *const enc_sess)
{
SSL_CTX *ssl_ctx;
SSL_SESSION *ssl_session;
const struct alpn_map *am;
int transpa_len;
char errbuf[ERR_ERROR_STRING_BUF_LEN];
#define hexbuf errbuf /* This is a dual-purpose buffer */
unsigned char trans_params[0x80
#if LSQUIC_TEST_QUANTUM_READINESS
+ 4 + lsquic_tp_get_quantum_sz()
#endif
];
if (enc_sess->esi_enpub->enp_alpn)
enc_sess->esi_alpn = enc_sess->esi_enpub->enp_alpn;
else if (enc_sess->esi_enpub->enp_flags & ENPUB_HTTP)
{
for (am = s_h3_alpns; am < s_h3_alpns + sizeof(s_h3_alpns)
/ sizeof(s_h3_alpns[0]); ++am)
if (am->version == enc_sess->esi_ver_neg->vn_ver)
goto ok;
LSQ_ERROR("version %s has no matching ALPN",
lsquic_ver2str[enc_sess->esi_ver_neg->vn_ver]);
return -1;
ok: enc_sess->esi_alpn = am->alpn;
}
LSQ_DEBUG("Create new SSL_CTX");
ssl_ctx = SSL_CTX_new(TLS_method());
if (!ssl_ctx)
{
LSQ_ERROR("cannot create SSL context: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
SSL_CTX_set_default_verify_paths(ssl_ctx);
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_CLIENT);
if (enc_sess->esi_enpub->enp_stream_if->on_sess_resume_info)
SSL_CTX_sess_set_new_cb(ssl_ctx, iquic_new_session_cb);
if (enc_sess->esi_enpub->enp_kli)
SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
if (enc_sess->esi_enpub->enp_verify_cert
|| LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)
|| LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG))
SSL_CTX_set_custom_verify(ssl_ctx, SSL_VERIFY_PEER,
verify_server_cert_callback);
SSL_CTX_set_early_data_enabled(ssl_ctx, 1);
transpa_len = gen_trans_params(enc_sess, trans_params,
sizeof(trans_params));
if (transpa_len < 0)
{
goto err;
}
enc_sess->esi_ssl = SSL_new(ssl_ctx);
if (!enc_sess->esi_ssl)
{
LSQ_ERROR("cannot create SSL object: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
if (!(SSL_set_quic_method(enc_sess->esi_ssl, &cry_quic_method)))
{
LSQ_INFO("could not set stream method");
goto err;
}
maybe_setup_key_logging(enc_sess);
if (1 != SSL_set_quic_transport_params(enc_sess->esi_ssl, trans_params,
transpa_len))
{
LSQ_ERROR("cannot set QUIC transport params: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
if (enc_sess->esi_alpn &&
0 != SSL_set_alpn_protos(enc_sess->esi_ssl, enc_sess->esi_alpn,
enc_sess->esi_alpn[0] + 1))
{
LSQ_ERROR("cannot set ALPN: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
if (1 != SSL_set_tlsext_host_name(enc_sess->esi_ssl,
enc_sess->esi_hostname))
{
LSQ_ERROR("cannot set hostname: %s",
ERR_error_string(ERR_get_error(), errbuf));
goto err;
}
free(enc_sess->esi_hostname);
enc_sess->esi_hostname = NULL;
if (enc_sess->esi_sess_resume_buf)
{
ssl_session = maybe_create_SSL_SESSION(enc_sess, ssl_ctx);
if (ssl_session)
{
if (SSL_set_session(enc_sess->esi_ssl, ssl_session))
enc_sess->esi_flags |= ESI_USE_SSL_TICKET;
else
LSQ_WARN("cannot set session");
}
}
SSL_set_ex_data(enc_sess->esi_ssl, s_idx, enc_sess);
SSL_set_connect_state(enc_sess->esi_ssl);
SSL_CTX_free(ssl_ctx);
LSQ_DEBUG("initialized client enc session");
enc_sess->esi_flags |= ESI_INITIALIZED;
return 0;
err:
if (ssl_ctx)
SSL_CTX_free(ssl_ctx);
return -1;
#undef hexbuf
}
struct crypto_params struct crypto_params
{ {
const EVP_AEAD *aead; const EVP_AEAD *aead;
const EVP_MD *md; const EVP_MD *md;
const EVP_CIPHER *hp; const EVP_CIPHER *hp;
gen_hp_mask_f gen_hp_mask; gen_hp_mask_f gen_hp_mask;
}; };
static int static int
get_crypto_params (const struct enc_sess_iquic *enc_sess, get_crypto_params (const struct enc_sess_iquic *enc_sess,
skipping to change at line 1572 skipping to change at line 1564
iv_sz = 8; /* [draft-ietf-quic-tls-11], Section 5.3 */ iv_sz = 8; /* [draft-ietf-quic-tls-11], Section 5.3 */
if (iv_sz > EVP_MAX_IV_LENGTH) if (iv_sz > EVP_MAX_IV_LENGTH)
{ {
LSQ_DEBUG("iv size %u is too large", iv_sz); LSQ_DEBUG("iv size %u is too large", iv_sz);
return -1; return -1;
} }
return 0; return 0;
} }
/* [draft-ietf-quic-transport-31] Section 7.4.1:
" If 0-RTT data is accepted by the server, the server MUST NOT reduce
" any limits or alter any values that might be violated by the client
" with its 0-RTT data. In particular, a server that accepts 0-RTT data
" MUST NOT set values for the following parameters (Section 18.2) that
" are smaller than the remembered value of the parameters.
"
" * active_connection_id_limit
"
" * initial_max_data
"
" * initial_max_stream_data_bidi_local
"
" * initial_max_stream_data_bidi_remote
"
" * initial_max_stream_data_uni
"
" * initial_max_streams_bidi
"
" * initial_max_streams_uni
*/
#define REDUCTION_PROHIBITED_TPS (0 \
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT) \
| (1 << TPI_INIT_MAX_DATA) \
| (1 << TPI_INIT_MAX_STREAMS_UNI) \
| (1 << TPI_INIT_MAX_STREAMS_BIDI) \
| (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL) \
| (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE) \
| (1 << TPI_INIT_MAX_STREAM_DATA_UNI) \
)
static int
check_server_tps_for_violations (const struct enc_sess_iquic *enc_sess,
const struct transport_params *params_0rtt,
const struct transport_params *new_params)
{
enum transport_param_id tpi;
for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi)
if ((1 << tpi) & REDUCTION_PROHIBITED_TPS)
if (new_params->tp_numerics[tpi] > params_0rtt->tp_numerics[tpi])
{
LSQ_INFO("server's new TP %s increased in value from %"PRIu64
" to %"PRIu64, lsquic_tpi2str[tpi],
params_0rtt->tp_numerics[tpi],
new_params->tp_numerics[tpi]);
return -1;
}
LSQ_DEBUG("server's new transport parameters do not violate save 0-RTT "
"parameters");
return 0;
}
static int static int
get_peer_transport_params (struct enc_sess_iquic *enc_sess) get_peer_transport_params (struct enc_sess_iquic *enc_sess)
{ {
struct transport_params *const trans_params = &enc_sess->esi_peer_tp; struct transport_params *const trans_params = &enc_sess->esi_peer_tp;
struct transport_params params_0rtt;
const uint8_t *params_buf; const uint8_t *params_buf;
size_t bufsz; size_t bufsz;
char *params_str; char *params_str;
const enum lsquic_version version = enc_sess->esi_conn->cn_version; const enum lsquic_version version = enc_sess->esi_conn->cn_version;
int have_0rtt_tp;
SSL_get_peer_quic_transport_params(enc_sess->esi_ssl, &params_buf, &bufsz); SSL_get_peer_quic_transport_params(enc_sess->esi_ssl, &params_buf, &bufsz);
if (!params_buf) if (!params_buf)
{ {
LSQ_DEBUG("no peer transport parameters"); LSQ_DEBUG("no peer transport parameters");
return -1; return -1;
} }
have_0rtt_tp = !!(enc_sess->esi_flags & ESI_HAVE_0RTT_TP);
if (have_0rtt_tp)
{
params_0rtt = enc_sess->esi_peer_tp;
enc_sess->esi_flags &= ~ESI_HAVE_0RTT_TP;
}
LSQ_DEBUG("have peer transport parameters (%zu bytes)", bufsz); LSQ_DEBUG("have peer transport parameters (%zu bytes)", bufsz);
if (0 > (version == LSQVER_ID27 ? lsquic_tp_decode_27 if (0 > (version == LSQVER_ID27 ? lsquic_tp_decode_27
: lsquic_tp_decode)(params_buf, bufsz, : lsquic_tp_decode)(params_buf, bufsz,
!(enc_sess->esi_flags & ESI_SERVER), !(enc_sess->esi_flags & ESI_SERVER),
trans_params)) trans_params))
{ {
if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG)) if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
{ {
params_str = lsquic_mm_get_4k(&enc_sess->esi_enpub->enp_mm); params_str = lsquic_mm_get_4k(&enc_sess->esi_enpub->enp_mm);
if (params_str) if (params_str)
skipping to change at line 1611 skipping to change at line 1666
"(%zd bytes):\n%s", bufsz, params_str); "(%zd bytes):\n%s", bufsz, params_str);
lsquic_mm_put_4k(&enc_sess->esi_enpub->enp_mm, params_str); lsquic_mm_put_4k(&enc_sess->esi_enpub->enp_mm, params_str);
} }
else else
LSQ_DEBUG("could not parse peer transport parameters " LSQ_DEBUG("could not parse peer transport parameters "
"(%zd bytes)", bufsz); "(%zd bytes)", bufsz);
} }
return -1; return -1;
} }
if (have_0rtt_tp && 0 != check_server_tps_for_violations(enc_sess,
&params_0rtt, trans_params))
return -1;
const lsquic_cid_t *const cids[LAST_TPI + 1] = { const lsquic_cid_t *const cids[LAST_TPI + 1] = {
[TP_CID_IDX(TPI_ORIGINAL_DEST_CID)] = enc_sess->esi_flags & ESI_ODCID ? &enc_sess->esi_odcid : NULL, [TP_CID_IDX(TPI_ORIGINAL_DEST_CID)] = enc_sess->esi_flags & ESI_ODCID ? &enc_sess->esi_odcid : NULL,
[TP_CID_IDX(TPI_RETRY_SOURCE_CID)] = enc_sess->esi_flags & ESI_RSCID ? &enc_sess->esi_rscid : NULL, [TP_CID_IDX(TPI_RETRY_SOURCE_CID)] = enc_sess->esi_flags & ESI_RSCID ? &enc_sess->esi_rscid : NULL,
[TP_CID_IDX(TPI_INITIAL_SOURCE_CID)] = enc_sess->esi_flags & ESI_ISCID ? &enc_sess->esi_iscid : NULL, [TP_CID_IDX(TPI_INITIAL_SOURCE_CID)] = enc_sess->esi_flags & ESI_ISCID ? &enc_sess->esi_iscid : NULL,
}; };
unsigned must_have, must_not_have = 0; unsigned must_have, must_not_have = 0;
if (version > LSQVER_ID27) if (version > LSQVER_ID27)
{ {
must_have = 1 << TPI_INITIAL_SOURCE_CID; must_have = 1 << TPI_INITIAL_SOURCE_CID;
skipping to change at line 1734 skipping to change at line 1793
if (enc_sess->esi_flags & ESI_HAVE_PEER_TP) if (enc_sess->esi_flags & ESI_HAVE_PEER_TP)
return 0; return 0;
s = get_peer_transport_params(enc_sess); s = get_peer_transport_params(enc_sess);
if (s == 0) if (s == 0)
enc_sess->esi_flags |= ESI_HAVE_PEER_TP; enc_sess->esi_flags |= ESI_HAVE_PEER_TP;
return s; return s;
} }
enum iquic_handshake_status {
IHS_WANT_READ,
IHS_WANT_WRITE,
IHS_WANT_RW,
IHS_STOP,
};
static enum iquic_handshake_status static enum iquic_handshake_status
iquic_esfi_handshake (struct enc_sess_iquic *enc_sess) iquic_esfi_handshake (struct enc_sess_iquic *enc_sess)
{ {
int s, err; int s, err;
enum lsquic_hsk_status hsk_status; enum lsquic_hsk_status hsk_status;
char errbuf[ERR_ERROR_STRING_BUF_LEN]; char errbuf[ERR_ERROR_STRING_BUF_LEN];
s = SSL_do_handshake(enc_sess->esi_ssl); s = SSL_do_handshake(enc_sess->esi_ssl);
if (s <= 0) if (s <= 0)
{ {
err = SSL_get_error(enc_sess->esi_ssl, s); err = SSL_get_error(enc_sess->esi_ssl, s);
switch (err) switch (err)
{ {
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
LSQ_DEBUG("retry read"); LSQ_DEBUG("retry read");
return IHS_WANT_READ; return IHS_WANT_READ;
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
LSQ_DEBUG("retry write"); LSQ_DEBUG("retry write");
return IHS_WANT_WRITE; return IHS_WANT_WRITE;
case SSL_ERROR_EARLY_DATA_REJECTED: case SSL_ERROR_EARLY_DATA_REJECTED:
LSQ_DEBUG("early data rejected"); LSQ_DEBUG("early data rejected: reset");
hsk_status = LSQ_HSK_RESUMED_FAIL; SSL_reset_early_data_reject(enc_sess->esi_ssl);
goto err; if (enc_sess->esi_conn->cn_if->ci_early_data_failed)
enc_sess->esi_conn->cn_if->ci_early_data_failed(
enc_sess->esi_conn);
return IHS_WANT_RW;
/* fall through */ /* fall through */
default: default:
LSQ_DEBUG("handshake: %s", ERR_error_string(err, errbuf)); LSQ_DEBUG("handshake: %s", ERR_error_string(err, errbuf));
hsk_status = LSQ_HSK_FAIL; hsk_status = LSQ_HSK_FAIL;
goto err; goto err;
} }
} }
if (SSL_in_early_data(enc_sess->esi_ssl)) if (SSL_in_early_data(enc_sess->esi_ssl))
{ {
skipping to change at line 1826 skipping to change at line 1895
"post-handshake error, code %d", s); "post-handshake error, code %d", s);
return IHS_STOP; return IHS_STOP;
} }
} }
static struct transport_params * static struct transport_params *
iquic_esfi_get_peer_transport_params (enc_session_t *enc_session_p) iquic_esfi_get_peer_transport_params (enc_session_t *enc_session_p)
{ {
struct enc_sess_iquic *const enc_sess = enc_session_p; struct enc_sess_iquic *const enc_sess = enc_session_p;
if (0 == maybe_get_peer_transport_params(enc_sess)) if (enc_sess->esi_flags & ESI_HAVE_0RTT_TP)
return &enc_sess->esi_peer_tp;
else if (0 == maybe_get_peer_transport_params(enc_sess))
return &enc_sess->esi_peer_tp; return &enc_sess->esi_peer_tp;
else else
return NULL; return NULL;
} }
static void static void
iquic_esfi_destroy (enc_session_t *enc_session_p) iquic_esfi_destroy (enc_session_t *enc_session_p)
{ {
struct enc_sess_iquic *const enc_sess = enc_session_p; struct enc_sess_iquic *const enc_sess = enc_session_p;
struct frab_list *fral; struct frab_list *fral;
skipping to change at line 1851 skipping to change at line 1922
++fral) ++fral)
lsquic_frab_list_cleanup(fral); lsquic_frab_list_cleanup(fral);
if (enc_sess->esi_keylog_handle) if (enc_sess->esi_keylog_handle)
enc_sess->esi_enpub->enp_kli->kli_close(enc_sess->esi_keylog_handle); enc_sess->esi_enpub->enp_kli->kli_close(enc_sess->esi_keylog_handle);
if (enc_sess->esi_ssl) if (enc_sess->esi_ssl)
SSL_free(enc_sess->esi_ssl); SSL_free(enc_sess->esi_ssl);
free_handshake_keys(enc_sess); free_handshake_keys(enc_sess);
cleanup_hp(&enc_sess->esi_hp); cleanup_hp(&enc_sess->esi_hp);
free(enc_sess->esi_sess_resume_buf);
free(enc_sess->esi_hostname);
free(enc_sess); free(enc_sess);
} }
/* See [draft-ietf-quic-tls-14], Section 4 */ /* See [draft-ietf-quic-tls-14], Section 4 */
static const enum enc_level hety2el[] = static const enum enc_level hety2el[] =
{ {
[HETY_NOT_SET] = ENC_LEV_FORW, [HETY_NOT_SET] = ENC_LEV_FORW,
[HETY_VERNEG] = 0, [HETY_VERNEG] = 0,
[HETY_INITIAL] = ENC_LEV_CLEAR, [HETY_INITIAL] = ENC_LEV_CLEAR,
[HETY_RETRY] = 0, [HETY_RETRY] = 0,
[HETY_HANDSHAKE] = ENC_LEV_INIT, [HETY_HANDSHAKE] = ENC_LEV_INIT,
[HETY_0RTT] = ENC_LEV_EARLY, [HETY_0RTT] = ENC_LEV_EARLY,
}; };
static const enum enc_level pns2enc_level[] = static const enum enc_level pns2enc_level[2][N_PNS] =
{ {
[PNS_INIT] = ENC_LEV_CLEAR, [0] = {
[PNS_HSK] = ENC_LEV_INIT, [PNS_INIT] = ENC_LEV_CLEAR,
[PNS_APP] = ENC_LEV_FORW, [PNS_HSK] = ENC_LEV_INIT,
[PNS_APP] = ENC_LEV_EARLY,
},
[1] = {
[PNS_INIT] = ENC_LEV_CLEAR,
[PNS_HSK] = ENC_LEV_INIT,
[PNS_APP] = ENC_LEV_FORW,
},
}; };
static enum enc_packout static enum enc_packout
iquic_esf_encrypt_packet (enc_session_t *enc_session_p, iquic_esf_encrypt_packet (enc_session_t *enc_session_p,
const struct lsquic_engine_public *enpub, struct lsquic_conn *lconn_UNUSED, const struct lsquic_engine_public *enpub, struct lsquic_conn *lconn_UNUSED,
struct lsquic_packet_out *packet_out) struct lsquic_packet_out *packet_out)
{ {
struct enc_sess_iquic *const enc_sess = enc_session_p; struct enc_sess_iquic *const enc_sess = enc_session_p;
struct lsquic_conn *const lconn = enc_sess->esi_conn; struct lsquic_conn *const lconn = enc_sess->esi_conn;
unsigned char *dst; unsigned char *dst;
skipping to change at line 1897 skipping to change at line 1973
unsigned char *nonce, *begin_xor; unsigned char *nonce, *begin_xor;
lsquic_packno_t packno; lsquic_packno_t packno;
size_t out_sz, dst_sz; size_t out_sz, dst_sz;
int header_sz; int header_sz;
int ipv6; int ipv6;
unsigned packno_off, packno_len; unsigned packno_off, packno_len;
enum packnum_space pns; enum packnum_space pns;
char errbuf[ERR_ERROR_STRING_BUF_LEN]; char errbuf[ERR_ERROR_STRING_BUF_LEN];
pns = lsquic_packet_out_pns(packet_out); pns = lsquic_packet_out_pns(packet_out);
/* TODO Obviously, will need more logic for 0-RTT */ enc_level = pns2enc_level[ enc_sess->esi_have_forw ][ pns ];
enc_level = pns2enc_level[ pns ];
if (enc_level == ENC_LEV_FORW) if (enc_level == ENC_LEV_FORW)
{ {
pair = &enc_sess->esi_pairs[ enc_sess->esi_key_phase ]; pair = &enc_sess->esi_pairs[ enc_sess->esi_key_phase ];
crypto_ctx = &pair->ykp_ctx[ 1 ]; crypto_ctx = &pair->ykp_ctx[ 1 ];
hp = &enc_sess->esi_hp; hp = &enc_sess->esi_hp;
} }
else if (enc_sess->esi_hsk_pairs) else if (enc_sess->esi_hsk_pairs)
{ {
pair = &enc_sess->esi_hsk_pairs[ enc_level ]; pair = &enc_sess->esi_hsk_pairs[ enc_level ];
skipping to change at line 2402 skipping to change at line 2477
iquic_esf_alg_keysize (enc_session_t *enc_session_p) iquic_esf_alg_keysize (enc_session_t *enc_session_p)
{ {
/* Modeled on SslConnection::getEnv() */ /* Modeled on SslConnection::getEnv() */
return iquic_esf_keysize(enc_session_p); return iquic_esf_keysize(enc_session_p);
} }
static int static int
iquic_esf_sess_resume_enabled (enc_session_t *enc_session_p) iquic_esf_sess_resume_enabled (enc_session_t *enc_session_p)
{ {
struct enc_sess_iquic *const enc_sess = enc_session_p; struct enc_sess_iquic *const enc_sess = enc_session_p;
return enc_sess->esi_sess_resume_buf != NULL; return !!(enc_sess->esi_flags & ESI_USE_SSL_TICKET);
} }
static void static void
iquic_esfi_set_iscid (enc_session_t *enc_session_p, iquic_esfi_set_iscid (enc_session_t *enc_session_p,
const struct lsquic_packet_in *packet_in) const struct lsquic_packet_in *packet_in)
{ {
struct enc_sess_iquic *const enc_sess = enc_session_p; struct enc_sess_iquic *const enc_sess = enc_session_p;
if (!(enc_sess->esi_flags & ESI_ISCID)) if (!(enc_sess->esi_flags & ESI_ISCID))
{ {
skipping to change at line 2747 skipping to change at line 2822
hp->hp_flags |= 1 << rw; hp->hp_flags |= 1 << rw;
if (enc_sess->esi_flags & ESI_LOG_SECRETS) if (enc_sess->esi_flags & ESI_LOG_SECRETS)
{ {
log_crypto_ctx(enc_sess, &pair->ykp_ctx[rw], "new", rw); log_crypto_ctx(enc_sess, &pair->ykp_ctx[rw], "new", rw);
LSQ_DEBUG("%s hp: %s", rw2str[rw], LSQ_DEBUG("%s hp: %s", rw2str[rw],
HEXSTR(hp->hp_gen_mask == gen_hp_mask_aes ? key : hp->hp_u.buf[rw], HEXSTR(hp->hp_gen_mask == gen_hp_mask_aes ? key : hp->hp_u.buf[rw],
key_len, hexbuf)); key_len, hexbuf));
} }
if (rw && enc_level == ENC_LEV_FORW)
enc_sess->esi_have_forw = 1;
return 1; return 1;
err: err:
cleanup_crypto_ctx(&pair->ykp_ctx[0]); cleanup_crypto_ctx(&pair->ykp_ctx[0]);
cleanup_crypto_ctx(&pair->ykp_ctx[1]); cleanup_crypto_ctx(&pair->ykp_ctx[1]);
return 0; return 0;
#undef hexbuf #undef hexbuf
} }
static int static int
skipping to change at line 2878 skipping to change at line 2956
.send_alert = cry_sm_send_alert, .send_alert = cry_sm_send_alert,
}; };
static lsquic_stream_ctx_t * static lsquic_stream_ctx_t *
chsk_ietf_on_new_stream (void *stream_if_ctx, struct lsquic_stream *stream) chsk_ietf_on_new_stream (void *stream_if_ctx, struct lsquic_stream *stream)
{ {
struct enc_sess_iquic *const enc_sess = stream_if_ctx; struct enc_sess_iquic *const enc_sess = stream_if_ctx;
enum enc_level enc_level; enum enc_level enc_level;
enc_level = enc_sess->esi_cryst_if->csi_enc_level(stream); enc_level = enc_sess->esi_cryst_if->csi_enc_level(stream);
if (enc_level != ENC_LEV_CLEAR) if (enc_level == ENC_LEV_CLEAR)
{ enc_sess->esi_cryst_if->csi_wantwrite(stream, 1);
LSQ_DEBUG("skip initialization of stream at level %u", enc_level);
goto end;
}
if (
(enc_sess->esi_flags & ESI_SERVER) == 0 &&
0 != init_client(enc_sess))
{
LSQ_WARN("enc session could not be initialized");
return NULL;
}
enc_sess->esi_cryst_if->csi_wantwrite(stream, 1);
LSQ_DEBUG("handshake stream created successfully"); LSQ_DEBUG("handshake stream created successfully");
end:
return stream_if_ctx; return stream_if_ctx;
} }
static lsquic_stream_ctx_t * static lsquic_stream_ctx_t *
shsk_ietf_on_new_stream (void *stream_if_ctx, struct lsquic_stream *stream) shsk_ietf_on_new_stream (void *stream_if_ctx, struct lsquic_stream *stream)
{ {
struct enc_sess_iquic *const enc_sess = stream_if_ctx; struct enc_sess_iquic *const enc_sess = stream_if_ctx;
enum enc_level enc_level; enum enc_level enc_level;
enc_level = enc_sess->esi_cryst_if->csi_enc_level(stream); enc_level = enc_sess->esi_cryst_if->csi_enc_level(stream);
skipping to change at line 2926 skipping to change at line 2990
{ {
struct enc_sess_iquic *const enc_sess = (struct enc_sess_iquic *) ctx; struct enc_sess_iquic *const enc_sess = (struct enc_sess_iquic *) ctx;
if (enc_sess && enc_sess->esi_cryst_if) if (enc_sess && enc_sess->esi_cryst_if)
LSQ_DEBUG("crypto stream level %u is closed", LSQ_DEBUG("crypto stream level %u is closed",
(unsigned) enc_sess->esi_cryst_if->csi_enc_level(stream)); (unsigned) enc_sess->esi_cryst_if->csi_enc_level(stream));
} }
static const char *const ihs2str[] = { static const char *const ihs2str[] = {
[IHS_WANT_READ] = "want read", [IHS_WANT_READ] = "want read",
[IHS_WANT_WRITE] = "want write", [IHS_WANT_WRITE] = "want write",
[IHS_WANT_RW] = "want rw",
[IHS_STOP] = "stop", [IHS_STOP] = "stop",
}; };
static void static void
iquic_esfi_shake_stream (enc_session_t *sess, iquic_esfi_shake_stream (enc_session_t *sess,
struct lsquic_stream *stream, const char *what) struct lsquic_stream *stream, const char *what)
{ {
struct enc_sess_iquic *enc_sess = (struct enc_sess_iquic *)sess; struct enc_sess_iquic *enc_sess = (struct enc_sess_iquic *)sess;
enum iquic_handshake_status st; enum iquic_handshake_status st;
enum enc_level enc_level; enum enc_level enc_level;
skipping to change at line 2955 skipping to change at line 3020
{ {
case IHS_WANT_READ: case IHS_WANT_READ:
write = !lsquic_frab_list_empty(&enc_sess->esi_frals[enc_level]); write = !lsquic_frab_list_empty(&enc_sess->esi_frals[enc_level]);
enc_sess->esi_cryst_if->csi_wantwrite(stream, write); enc_sess->esi_cryst_if->csi_wantwrite(stream, write);
enc_sess->esi_cryst_if->csi_wantread(stream, 1); enc_sess->esi_cryst_if->csi_wantread(stream, 1);
break; break;
case IHS_WANT_WRITE: case IHS_WANT_WRITE:
enc_sess->esi_cryst_if->csi_wantwrite(stream, 1); enc_sess->esi_cryst_if->csi_wantwrite(stream, 1);
enc_sess->esi_cryst_if->csi_wantread(stream, 0); enc_sess->esi_cryst_if->csi_wantread(stream, 0);
break; break;
case IHS_WANT_RW:
enc_sess->esi_cryst_if->csi_wantwrite(stream, 1);
enc_sess->esi_cryst_if->csi_wantread(stream, 1);
break;
default: default:
assert(st == IHS_STOP); assert(st == IHS_STOP);
write = !lsquic_frab_list_empty(&enc_sess->esi_frals[enc_level]); write = !lsquic_frab_list_empty(&enc_sess->esi_frals[enc_level]);
enc_sess->esi_cryst_if->csi_wantwrite(stream, write); enc_sess->esi_cryst_if->csi_wantwrite(stream, write);
enc_sess->esi_cryst_if->csi_wantread(stream, 0); enc_sess->esi_cryst_if->csi_wantread(stream, 0);
break; break;
} }
LSQ_DEBUG("Exit shake_stream"); LSQ_DEBUG("Exit shake_stream");
maybe_drop_SSL(enc_sess); maybe_drop_SSL(enc_sess);
} }
skipping to change at line 3115 skipping to change at line 3184
"\xcc\xce\x18\x7e\xd0\x9a\x09\xd0\x57\x28\x15\x5a\x6c\xb9\x6b\xe1", "\xcc\xce\x18\x7e\xd0\x9a\x09\xd0\x57\x28\x15\x5a\x6c\xb9\x6b\xe1",
}; };
const unsigned char *const lsquic_retry_nonce_buf[N_IETF_RETRY_VERSIONS] = const unsigned char *const lsquic_retry_nonce_buf[N_IETF_RETRY_VERSIONS] =
{ {
/* [draft-ietf-quic-tls-25] Section 5.8 */ /* [draft-ietf-quic-tls-25] Section 5.8 */
(unsigned char *) "\x4d\x16\x11\xd0\x55\x13\xa5\x52\xc5\x87\xd5\x75", (unsigned char *) "\x4d\x16\x11\xd0\x55\x13\xa5\x52\xc5\x87\xd5\x75",
/* [draft-ietf-quic-tls-29] Section 5.8 */ /* [draft-ietf-quic-tls-29] Section 5.8 */
(unsigned char *) "\xe5\x49\x30\xf9\x7f\x21\x36\xf0\x53\x0a\x8c\x1c", (unsigned char *) "\xe5\x49\x30\xf9\x7f\x21\x36\xf0\x53\x0a\x8c\x1c",
}; };
int
lsquic_enc_sess_ietf_gen_quic_ctx (
const struct lsquic_engine_settings *settings,
enum lsquic_version version, unsigned char *buf, size_t bufsz)
{
struct transport_params params;
int len;
/* This code is pretty much copied from gen_trans_params(), with
* small (but important) exceptions.
*/
memset(&params, 0, sizeof(params));
params.tp_init_max_data = settings->es_init_max_data;
params.tp_init_max_stream_data_bidi_local
= settings->es_init_max_stream_data_bidi_local;
params.tp_init_max_stream_data_bidi_remote
= settings->es_init_max_stream_data_bidi_remote;
params.tp_init_max_stream_data_uni
= settings->es_init_max_stream_data_uni;
params.tp_init_max_streams_uni
= settings->es_init_max_streams_uni;
params.tp_init_max_streams_bidi
= settings->es_init_max_streams_bidi;
params.tp_ack_delay_exponent
= TP_DEF_ACK_DELAY_EXP;
params.tp_max_idle_timeout = settings->es_idle_timeout * 1000;
params.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY;
params.tp_active_connection_id_limit = MAX_IETF_CONN_DCIDS;
params.tp_set |= (1 << TPI_INIT_MAX_DATA)
| (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL)
| (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE)
| (1 << TPI_INIT_MAX_STREAM_DATA_UNI)
| (1 << TPI_INIT_MAX_STREAMS_UNI)
| (1 << TPI_INIT_MAX_STREAMS_BIDI)
| (1 << TPI_ACK_DELAY_EXPONENT)
| (1 << TPI_MAX_IDLE_TIMEOUT)
| (1 << TPI_MAX_ACK_DELAY)
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT)
;
if (settings->es_max_udp_payload_size_rx)
{
params.tp_max_udp_payload_size = settings->es_max_udp_payload_size_rx;
params.tp_set |= 1 << TPI_MAX_UDP_PAYLOAD_SIZE;
}
if (!settings->es_allow_migration)
params.tp_set |= 1 << TPI_DISABLE_ACTIVE_MIGRATION;
if (settings->es_ql_bits)
{
params.tp_loss_bits = settings->es_ql_bits - 1;
params.tp_set |= 1 << TPI_LOSS_BITS;
}
if (settings->es_delayed_acks)
{
params.tp_numerics[TPI_MIN_ACK_DELAY] = 10000; /* TODO: make into a c
onstant? make configurable? */
params.tp_set |= 1 << TPI_MIN_ACK_DELAY;
}
if (settings->es_timestamps)
{
params.tp_numerics[TPI_TIMESTAMPS] = TS_GENERATE_THEM;
params.tp_set |= 1 << TPI_TIMESTAMPS;
}
if (settings->es_datagrams)
{
if (params.tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
params.tp_numerics[TPI_MAX_DATAGRAM_FRAME_SIZE]
= params.tp_max_udp_payload_size;
else
params.tp_numerics[TPI_MAX_DATAGRAM_FRAME_SIZE]
= TP_DEF_MAX_UDP_PAYLOAD_SIZE;
params.tp_set |= 1 << TPI_MAX_DATAGRAM_FRAME_SIZE;
}
params.tp_set &= SERVER_0RTT_TPS;
len = (version == LSQVER_ID27 ? lsquic_tp_encode_27 : lsquic_tp_encode)(
&params, 1, buf, bufsz);
if (len >= 0)
{
char str[MAX_TP_STR_SZ];
LSQ_LOG1(LSQ_LOG_DEBUG, "generated QUIC server context of %d bytes "
"for version %s", len, lsquic_ver2str[version]);
LSQ_LOG1(LSQ_LOG_DEBUG, "%s", ((version == LSQVER_ID27
? lsquic_tp_to_str_27 : lsquic_tp_to_str)(&params, str,
sizeof(str)), str));
}
else
LSQ_LOG1(LSQ_LOG_WARN, "cannot generate QUIC server context: %d",
errno);
return len;
}
 End of changes. 45 change blocks. 
195 lines changed or deleted 263 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)