mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:17:36 +00:00
LibTLS: Simplify the way verify_chain
is called
The `build_rsa_pre_master_secret` function originally called `verify_chain_and_get_matching_certificate`, which verified the chain and returned a certificate matching the specified hostname. Since the first certificate in the chain should always be the one matching with the hostname, we can simply use that one instead. This means we can completely remove this method and just use `verify_chain`. To make sure the hostname is still verified, `verify_chain` now also checks that the first certificate in the chain matches the specified hostname. If the hostname is empty, we currently fail the verification, however this basically never happen, as the server name indication extension is always used.
This commit is contained in:
parent
f8ce0eb648
commit
d78813d902
3 changed files with 47 additions and 58 deletions
|
@ -152,38 +152,6 @@ bool TLSv12::compute_master_secret_from_pre_master_secret(size_t length)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool wildcard_matches(StringView host, StringView subject)
|
||||
{
|
||||
if (host.matches(subject))
|
||||
return true;
|
||||
|
||||
if (subject.starts_with("*."))
|
||||
return wildcard_matches(host, subject.substring_view(2));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Optional<size_t> TLSv12::verify_chain_and_get_matching_certificate(StringView host) const
|
||||
{
|
||||
if (m_context.certificates.is_empty() || !m_context.verify_chain())
|
||||
return {};
|
||||
|
||||
if (host.is_empty())
|
||||
return 0;
|
||||
|
||||
for (size_t i = 0; i < m_context.certificates.size(); ++i) {
|
||||
auto& cert = m_context.certificates[i];
|
||||
if (wildcard_matches(host, cert.subject.subject))
|
||||
return i;
|
||||
for (auto& san : cert.SAN) {
|
||||
if (wildcard_matches(host, san))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void TLSv12::build_rsa_pre_master_secret(PacketBuilder& builder)
|
||||
{
|
||||
u8 random_bytes[48];
|
||||
|
@ -211,14 +179,7 @@ void TLSv12::build_rsa_pre_master_secret(PacketBuilder& builder)
|
|||
}
|
||||
m_context.premaster_key = premaster_key_result.release_value();
|
||||
|
||||
auto const& certificate_option = verify_chain_and_get_matching_certificate(m_context.extensions.SNI); // if the SNI is empty, we'll make a special case and match *a* leaf certificate.
|
||||
if (!certificate_option.has_value()) {
|
||||
dbgln("certificate verification failed :(");
|
||||
alert(AlertLevel::Critical, AlertDescription::BadCertificate);
|
||||
return;
|
||||
}
|
||||
|
||||
auto& certificate = m_context.certificates[certificate_option.value()];
|
||||
auto& certificate = m_context.certificates.first();
|
||||
if constexpr (TLS_DEBUG) {
|
||||
dbgln("PreMaster secret");
|
||||
print_buffer(m_context.premaster_key);
|
||||
|
@ -248,13 +209,6 @@ void TLSv12::build_rsa_pre_master_secret(PacketBuilder& builder)
|
|||
|
||||
void TLSv12::build_dhe_rsa_pre_master_secret(PacketBuilder& builder)
|
||||
{
|
||||
const auto& certificate_option = verify_chain_and_get_matching_certificate(m_context.extensions.SNI); // if the SNI is empty, we'll make a special case and match *a* leaf certificate.
|
||||
if (!certificate_option.has_value()) {
|
||||
dbgln("certificate verification failed :(");
|
||||
alert(AlertLevel::Critical, AlertDescription::BadCertificate);
|
||||
return;
|
||||
}
|
||||
|
||||
auto& dh = m_context.server_diffie_hellman_params;
|
||||
auto dh_p = Crypto::UnsignedBigInteger::import_data(dh.p.data(), dh.p.size());
|
||||
auto dh_g = Crypto::UnsignedBigInteger::import_data(dh.g.data(), dh.g.size());
|
||||
|
@ -302,13 +256,6 @@ void TLSv12::build_dhe_rsa_pre_master_secret(PacketBuilder& builder)
|
|||
|
||||
void TLSv12::build_ecdhe_rsa_pre_master_secret(PacketBuilder& builder)
|
||||
{
|
||||
const auto& certificate_option = verify_chain_and_get_matching_certificate(m_context.extensions.SNI); // if the SNI is empty, we'll make a special case and match *a* leaf certificate.
|
||||
if (!certificate_option.has_value()) {
|
||||
dbgln("certificate verification failed :(");
|
||||
alert(AlertLevel::Critical, AlertDescription::BadCertificate);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a random private key
|
||||
auto private_key_result = m_context.server_key_exchange_curve->generate_private_key();
|
||||
if (private_key_result.is_error()) {
|
||||
|
@ -414,6 +361,13 @@ ByteBuffer TLSv12::build_certificate()
|
|||
|
||||
ByteBuffer TLSv12::build_client_key_exchange()
|
||||
{
|
||||
bool chain_verified = m_context.verify_chain(m_context.extensions.SNI);
|
||||
if (!chain_verified) {
|
||||
dbgln("certificate verification failed :(");
|
||||
alert(AlertLevel::Critical, AlertDescription::BadCertificate);
|
||||
return {};
|
||||
}
|
||||
|
||||
PacketBuilder builder { MessageType::Handshake, m_context.options.version };
|
||||
builder.append((u8)HandshakeType::ClientKeyExchange);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue