in tls/s2n_kex.c [70:117]
static S2N_RESULT s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
RESULT_ENSURE_REF(cipher_suite);
RESULT_ENSURE_REF(conn);
RESULT_ENSURE_REF(is_supported);
/* If any of the necessary conditions are not met, we will return early and indicate KEM is not supported. */
*is_supported = false;
const struct s2n_kem_preferences *kem_preferences = NULL;
RESULT_GUARD_POSIX(s2n_connection_get_kem_preferences(conn, &kem_preferences));
RESULT_ENSURE_REF(kem_preferences);
if (!s2n_pq_is_enabled() || kem_preferences->kem_count == 0) {
return S2N_RESULT_OK;
}
const struct s2n_iana_to_kem *supported_params = NULL;
if (s2n_cipher_suite_to_kem(cipher_suite->iana_value, &supported_params) != S2N_SUCCESS) {
return S2N_RESULT_OK;
}
RESULT_ENSURE_REF(supported_params);
if (supported_params->kem_count == 0) {
return S2N_RESULT_OK;
}
struct s2n_blob *client_kem_pref_list = &(conn->kex_params.client_pq_kem_extension);
const struct s2n_kem *chosen_kem = NULL;
if (client_kem_pref_list == NULL || client_kem_pref_list->data == NULL) {
/* If the client did not send a PQ KEM extension, then the server can pick its preferred parameter */
if (s2n_choose_kem_without_peer_pref_list(
cipher_suite->iana_value, kem_preferences->kems, kem_preferences->kem_count, &chosen_kem)
!= S2N_SUCCESS) {
return S2N_RESULT_OK;
}
} else {
/* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */
if (s2n_choose_kem_with_peer_pref_list(
cipher_suite->iana_value, client_kem_pref_list, kem_preferences->kems, kem_preferences->kem_count, &chosen_kem)
!= S2N_SUCCESS) {
return S2N_RESULT_OK;
}
}
*is_supported = chosen_kem != NULL;
return S2N_RESULT_OK;
}