Feersum
view release on metacpan or search on metacpan
picotls-git/lib/picotls.c view on Meta::CPAN
}
Exit:
return ret;
#undef COPY_BLOCK
}
/* Wrapper function for invoking the on_client_hello callback, taking an exhaustive list of parameters as arguments. The intention
* is to not miss setting them as we add new parameters to the struct. */
static inline int call_on_client_hello_cb(ptls_t *tls, ptls_iovec_t server_name, ptls_iovec_t raw_message,
ptls_iovec_t cipher_suites, ptls_iovec_t *alpns, size_t num_alpns,
const uint16_t *sig_algos, size_t num_sig_algos, const uint16_t *cert_comp_algos,
size_t num_cert_comp_algos, const uint8_t *server_cert_types,
size_t num_server_cert_types, const ptls_client_hello_psk_identity_t *psk_identities,
size_t num_psk_identities, int incompatible_version)
{
if (tls->ctx->on_client_hello == NULL)
return 0;
ptls_on_client_hello_parameters_t params = {server_name,
raw_message,
cipher_suites,
{alpns, num_alpns},
{sig_algos, num_sig_algos},
{cert_comp_algos, num_cert_comp_algos},
{server_cert_types, num_server_cert_types},
{psk_identities, num_psk_identities},
incompatible_version};
return tls->ctx->on_client_hello->cb(tls->ctx->on_client_hello, tls, ¶ms);
}
static int check_client_hello_constraints(ptls_context_t *ctx, struct st_ptls_client_hello_t *ch, const void *prev_random,
int ech_is_inner_ch, ptls_iovec_t raw_message, ptls_t *tls_cbarg)
{
int is_second_flight = prev_random != 0;
/* The following check is necessary so that we would be able to track the connection in SSLKEYLOGFILE, even though it might not
* be for the safety of the protocol. */
if (is_second_flight && !ptls_mem_equal(ch->random_bytes, prev_random, PTLS_HELLO_RANDOM_SIZE))
return PTLS_ALERT_HANDSHAKE_FAILURE;
/* bail out if CH cannot be handled as TLS 1.3 */
if (!is_supported_version(ch->selected_version)) {
/* ECH: server MUST abort with an "illegal_parameter" alert if the client offers TLS 1.2 or below (draft-15 7.1) */
if (ech_is_inner_ch)
return PTLS_ALERT_ILLEGAL_PARAMETER;
/* fail with PROTOCOL_VERSION alert, after providing the applications the raw CH and SNI to help them fallback */
if (!is_second_flight) {
int ret;
if ((ret = call_on_client_hello_cb(tls_cbarg, ch->server_name, raw_message, ch->cipher_suites, ch->alpn.list,
ch->alpn.count, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 1)) != 0)
return ret;
}
return PTLS_ALERT_PROTOCOL_VERSION;
}
/* Check TLS 1.3-specific constraints. Hereafter, we might exit without calling on_client_hello. That's fine because this CH is
* ought to be rejected. */
if (ch->legacy_version <= 0x0300) {
/* RFC 8446 Appendix D.5: any endpoint receiving a Hello message with legacy_version set to 0x0300 MUST abort the handshake
* with a "protocol_version" alert. */
return PTLS_ALERT_PROTOCOL_VERSION;
}
if (!(ch->compression_methods.count == 1 && ch->compression_methods.ids[0] == 0))
return PTLS_ALERT_ILLEGAL_PARAMETER;
/* pre-shared key */
if (ch->psk.hash_end != NULL) {
/* PSK must be the last extension */
if (!ch->psk.is_last_extension)
return PTLS_ALERT_ILLEGAL_PARAMETER;
} else {
if (ch->psk.early_data_indication)
return PTLS_ALERT_ILLEGAL_PARAMETER;
}
if (ech_is_inner_ch && ch->ech.payload.base == NULL)
return PTLS_ALERT_ILLEGAL_PARAMETER;
if (ch->ech.payload.base != NULL &&
ch->ech.type != (ech_is_inner_ch ? PTLS_ECH_CLIENT_HELLO_TYPE_INNER : PTLS_ECH_CLIENT_HELLO_TYPE_OUTER))
return PTLS_ALERT_ILLEGAL_PARAMETER;
return 0;
}
static int vec_is_string(ptls_iovec_t x, const char *y)
{
return strncmp((const char *)x.base, y, x.len) == 0 && y[x.len] == '\0';
}
/**
* Looks for a PSK identity that can be used, and if found, updates the handshake state and returns the necessary variables. If
* `ptls_context_t::pre_shared_key` is set, only tries handshake using those keys provided. Otherwise, tries resumption.
*/
static int try_psk_handshake(ptls_t *tls, size_t *psk_index, int *accept_early_data, struct st_ptls_client_hello_t *ch,
ptls_iovec_t ch_trunc, int is_second_flight)
{
ptls_buffer_t decbuf;
ptls_iovec_t secret, ticket_ctx, ticket_negotiated_protocol;
uint64_t issue_at, now = tls->ctx->get_time->cb(tls->ctx->get_time);
uint32_t age_add;
uint16_t ticket_key_exchange_id, ticket_csid;
uint8_t binder_key[PTLS_MAX_DIGEST_SIZE];
int ret;
ptls_buffer_init(&decbuf, "", 0);
for (*psk_index = 0; *psk_index < ch->psk.identities.count; ++*psk_index) {
ptls_client_hello_psk_identity_t *identity = ch->psk.identities.list + *psk_index;
/* negotiate using fixed pre-shared key */
if (tls->ctx->pre_shared_key.identity.base != NULL) {
if (identity->identity.len == tls->ctx->pre_shared_key.identity.len &&
memcmp(identity->identity.base, tls->ctx->pre_shared_key.identity.base, identity->identity.len) == 0) {
*accept_early_data = ch->psk.early_data_indication && *psk_index == 0;
tls->key_share = NULL;
secret = tls->ctx->pre_shared_key.secret;
goto Found;
}
continue;
}
( run in 1.022 second using v1.01-cache-2.11-cpan-16aabcbfbcb )