mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibTLS: Change Certificate parsing to use ErrorOr
Loads of changes that are tightly connected... :/ * Change lambdas to static functions * Add spec docs to those functions * Keep the current scope around as a parameter * Add wrapping classes for some Certificate members * Parse ec and ecdsa data from certificates
This commit is contained in:
parent
b1d80b35af
commit
d527edf0ab
Notes:
sideshowbarker
2024-07-17 06:40:21 +09:00
Author: https://github.com/stelar7 Commit: https://github.com/SerenityOS/serenity/commit/d527edf0ab Pull-request: https://github.com/SerenityOS/serenity/pull/18166 Reviewed-by: https://github.com/alimpfard Reviewed-by: https://github.com/fdellwing ✅
8 changed files with 1044 additions and 553 deletions
|
@ -10,7 +10,7 @@
|
|||
|
||||
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
|
||||
{
|
||||
(void)TLS::Certificate::parse_asn1({ data, size });
|
||||
(void)TLS::Certificate::parse_certificate({ data, size });
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "CertificateStore.h"
|
||||
#include <AK/String.h>
|
||||
#include <Applications/CertificateSettings/CertificateStoreGML.h>
|
||||
#include <LibCrypto/ASN1/PEM.h>
|
||||
#include <LibFileSystem/FileSystem.h>
|
||||
|
@ -66,12 +67,24 @@ GUI::Variant CertificateStoreModel::data(GUI::ModelIndex const& index, GUI::Mode
|
|||
auto cert = m_certificates.at(index.row());
|
||||
|
||||
switch (index.column()) {
|
||||
case Column::IssuedTo:
|
||||
return cert.subject.subject.is_empty() ? cert.subject.unit : cert.subject.subject;
|
||||
case Column::IssuedBy:
|
||||
return cert.issuer.subject.is_empty() ? cert.issuer.unit : cert.issuer.subject;
|
||||
case Column::IssuedTo: {
|
||||
auto issued_to = cert.subject.common_name();
|
||||
if (issued_to.is_empty()) {
|
||||
issued_to = cert.subject.organizational_unit();
|
||||
}
|
||||
|
||||
return issued_to;
|
||||
}
|
||||
case Column::IssuedBy: {
|
||||
auto issued_by = cert.issuer.common_name();
|
||||
if (issued_by.is_empty()) {
|
||||
issued_by = cert.issuer.organizational_unit();
|
||||
}
|
||||
|
||||
return issued_by;
|
||||
}
|
||||
case Column::Expire:
|
||||
return cert.not_after.to_deprecated_string("%Y-%m-%d"sv);
|
||||
return cert.validity.not_after.to_deprecated_string("%Y-%m-%d"sv);
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
@ -128,8 +141,14 @@ ErrorOr<void> CertificateStoreWidget::export_pem()
|
|||
auto real_index = m_root_ca_proxy_model->map_to_source(index);
|
||||
auto cert = m_root_ca_model->get(real_index.row());
|
||||
|
||||
auto filename = cert.subject.subject.is_empty() ? cert.subject.unit : cert.subject.subject;
|
||||
auto file = FileSystemAccessClient::Client::the().save_file(window(), filename.replace(" "sv, "_"sv), "pem"sv);
|
||||
String filename = cert.subject.common_name();
|
||||
if (filename.is_empty()) {
|
||||
filename = cert.subject.organizational_unit();
|
||||
}
|
||||
|
||||
filename = TRY(filename.replace(" "sv, "_"sv, ReplaceMode::All));
|
||||
|
||||
auto file = FileSystemAccessClient::Client::the().save_file(window(), filename.to_deprecated_string(), "pem"sv);
|
||||
if (file.is_error())
|
||||
return {};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
* Copyright (c) 2020-2023, the SerenityOS developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -18,36 +18,219 @@
|
|||
|
||||
namespace TLS {
|
||||
|
||||
enum class CertificateKeyAlgorithm {
|
||||
#define _ENUM(key, value) key,
|
||||
|
||||
#define __ENUM_OBJECT_CLASS \
|
||||
_ENUM(ApplicationProcess, "2.5.6.11"sv) \
|
||||
_ENUM(Country, "2.5.6.2"sv) \
|
||||
_ENUM(DcObject, "1.3.6.1.4.1.1466.344"sv) \
|
||||
_ENUM(Device, "2.5.6.14"sv) \
|
||||
_ENUM(GroupOfNames, "2.5.6.9"sv) \
|
||||
_ENUM(GroupOfUniqueNames, "2.5.6.17"sv) \
|
||||
_ENUM(Locality, "2.5.6.3"sv) \
|
||||
_ENUM(Organization, "2.5.6.4"sv) \
|
||||
_ENUM(OrganizationalPerson, "2.5.6.7"sv) \
|
||||
_ENUM(OrganizationalRole, "2.5.6.8"sv) \
|
||||
_ENUM(OrganizationalUnit, "2.5.6.5"sv) \
|
||||
_ENUM(Person, "2.5.6.6"sv) \
|
||||
_ENUM(ResidentialPerson, "2.5.6.10"sv) \
|
||||
_ENUM(UidObject, "1.3.6.1.1.3.1"sv)
|
||||
|
||||
// NOTE: Type = O
|
||||
// NOTE: This list is not exhaustive. If more members are needed, find them at the link below.
|
||||
// https://www.iana.org/assignments/ldap-parameters/ldap-parameters.xhtml#ldap-parameters-3
|
||||
enum class ObjectClass {
|
||||
__ENUM_OBJECT_CLASS
|
||||
};
|
||||
|
||||
#define __ENUM_ATTRIBUTE_TYPE \
|
||||
_ENUM(BusinessCategory, "2.5.4.15"sv) \
|
||||
_ENUM(C, "2.5.4.6"sv) \
|
||||
_ENUM(Cn, "2.5.4.3"sv) \
|
||||
_ENUM(Dc, "0.9.2342.19200300.100.1.25"sv) \
|
||||
_ENUM(Description, "2.5.4.13"sv) \
|
||||
_ENUM(DestinationIndicator, "2.5.4.27"sv) \
|
||||
_ENUM(DistinguishedName, "2.5.4.49"sv) \
|
||||
_ENUM(DnQualifier, "2.5.4.46"sv) \
|
||||
_ENUM(EnhancedSearchGuide, "2.5.4.47"sv) \
|
||||
_ENUM(Email, "1.2.840.113549.1.9.1"sv) \
|
||||
_ENUM(FacsimileTelephoneNumber, "2.5.4.23"sv) \
|
||||
_ENUM(GenerationQualifier, "2.5.4.44"sv) \
|
||||
_ENUM(GivenName, "2.5.4.42"sv) \
|
||||
_ENUM(HouseIdentifier, "2.5.4.51"sv) \
|
||||
_ENUM(Initials, "2.5.4.43"sv) \
|
||||
_ENUM(InternationalISDNNumber, "2.5.4.25"sv) \
|
||||
_ENUM(L, "2.5.4.7"sv) \
|
||||
_ENUM(Member, "2.5.4.31"sv) \
|
||||
_ENUM(Name, "2.5.4.41"sv) \
|
||||
_ENUM(O, "2.5.4.10"sv) \
|
||||
_ENUM(Ou, "2.5.4.11"sv) \
|
||||
_ENUM(Owner, "2.5.4.32"sv) \
|
||||
_ENUM(PhysicalDeliveryOfficeName, "2.5.4.19"sv) \
|
||||
_ENUM(PostalAddress, "2.5.4.16"sv) \
|
||||
_ENUM(PostalCode, "2.5.4.17"sv) \
|
||||
_ENUM(PostOfficeBox, "2.5.4.18"sv) \
|
||||
_ENUM(PreferredDeliveryMethod, "2.5.4.28"sv) \
|
||||
_ENUM(RegisteredAddress, "2.5.4.26"sv) \
|
||||
_ENUM(RoleOccupant, "2.5.4.33"sv) \
|
||||
_ENUM(SearchGuide, "2.5.4.14"sv) \
|
||||
_ENUM(SeeAlso, "2.5.4.34"sv) \
|
||||
_ENUM(SerialNumber, "2.5.4.5"sv) \
|
||||
_ENUM(Sn, "2.5.4.4"sv) \
|
||||
_ENUM(St, "2.5.4.8"sv) \
|
||||
_ENUM(Street, "2.5.4.9"sv) \
|
||||
_ENUM(Surname, "2.5.4.4"sv) \
|
||||
_ENUM(TelephoneNumber, "2.5.4.20"sv) \
|
||||
_ENUM(TeletexTerminalIdentifier, "2.5.4.22"sv) \
|
||||
_ENUM(TelexNumber, "2.5.4.21"sv) \
|
||||
_ENUM(Title, "2.5.4.12"sv) \
|
||||
_ENUM(Uid, "0.9.2342.19200300.100.1.1"sv) \
|
||||
_ENUM(UniqueMember, "2.5.4.50"sv) \
|
||||
_ENUM(UserPassword, "2.5.4.35"sv) \
|
||||
_ENUM(X121Address, "2.5.4.24"sv) \
|
||||
_ENUM(X500UniqueIdentifier, "2.5.4.45"sv)
|
||||
|
||||
// NOTE: Type = A
|
||||
// NOTE: This list is not exhaustive. If more members are needed, find them at the link below.
|
||||
// https://www.iana.org/assignments/ldap-parameters/ldap-parameters.xhtml#ldap-parameters-3
|
||||
enum class AttributeType {
|
||||
__ENUM_ATTRIBUTE_TYPE
|
||||
};
|
||||
|
||||
#undef _ENUM
|
||||
|
||||
constexpr static StringView enum_value(ObjectClass object_class)
|
||||
{
|
||||
#define _ENUM(key, value) \
|
||||
case ObjectClass::key: \
|
||||
return value;
|
||||
|
||||
switch (object_class) {
|
||||
__ENUM_OBJECT_CLASS
|
||||
}
|
||||
|
||||
return "Unknown"sv;
|
||||
#undef _ENUM
|
||||
#undef __ENUM_OBJECT_CLASS
|
||||
}
|
||||
|
||||
constexpr static StringView enum_value(AttributeType object_class)
|
||||
{
|
||||
#define _ENUM(key, value) \
|
||||
case AttributeType::key: \
|
||||
return value;
|
||||
|
||||
switch (object_class) {
|
||||
__ENUM_ATTRIBUTE_TYPE
|
||||
}
|
||||
|
||||
return "Unknown"sv;
|
||||
#undef _ENUM
|
||||
#undef __ENUM_ATTRIBUTE_TYPE
|
||||
}
|
||||
|
||||
enum class CertificateKeyAlgorithm : u8 {
|
||||
Unsupported = 0x00,
|
||||
RSA_RSA = 0x01,
|
||||
RSA_MD2 = 0x2,
|
||||
RSA_MD4 = 0x3,
|
||||
RSA_MD5 = 0x04,
|
||||
RSA_SHA1 = 0x05,
|
||||
RSA_OAEP = 0x6,
|
||||
RSAES_OAEP = 0x7,
|
||||
RSA_MGF1 = 0x8,
|
||||
RSA_SPECIFIED = 0x9,
|
||||
RSA_PSS = 0xa,
|
||||
RSA_SHA256 = 0x0b,
|
||||
RSA_SHA384 = 0x0c,
|
||||
RSA_SHA512 = 0x0d,
|
||||
RSA_SHA224 = 0xe,
|
||||
ECDSA_SHA224 = 0x10,
|
||||
ECDSA_SHA256 = 0x11,
|
||||
ECDSA_SHA384 = 0x12,
|
||||
ECDSA_SHA512 = 0x13,
|
||||
ECDSA_SECP256R1 = 0x14,
|
||||
ECDSA_SECP384R1 = 0x15,
|
||||
};
|
||||
|
||||
struct BasicConstraints {
|
||||
bool is_certificate_authority;
|
||||
Crypto::UnsignedBigInteger path_length_constraint;
|
||||
};
|
||||
|
||||
class RelativeDistinguishedName {
|
||||
public:
|
||||
ErrorOr<String> to_string();
|
||||
|
||||
ErrorOr<AK::HashSetResult> set(String key, String value)
|
||||
{
|
||||
return m_members.try_set(key, value);
|
||||
}
|
||||
|
||||
Optional<String> get(StringView key)
|
||||
{
|
||||
return m_members.get(key);
|
||||
}
|
||||
|
||||
Optional<String> get(AttributeType key)
|
||||
{
|
||||
return m_members.get(enum_value(key));
|
||||
}
|
||||
|
||||
Optional<String> get(ObjectClass key)
|
||||
{
|
||||
return m_members.get(enum_value(key));
|
||||
}
|
||||
|
||||
String common_name()
|
||||
{
|
||||
auto entry = get(AttributeType::Cn);
|
||||
if (entry.has_value()) {
|
||||
return entry.value();
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
String organizational_unit()
|
||||
{
|
||||
auto entry = get(AttributeType::Ou);
|
||||
if (entry.has_value()) {
|
||||
return entry.value();
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
private:
|
||||
HashMap<String, String> m_members;
|
||||
};
|
||||
|
||||
struct Validity {
|
||||
Core::DateTime not_before;
|
||||
Core::DateTime not_after;
|
||||
};
|
||||
|
||||
class SubjectPublicKey {
|
||||
public:
|
||||
Crypto::PK::RSAPublicKey<Crypto::UnsignedBigInteger> rsa;
|
||||
|
||||
CertificateKeyAlgorithm algorithm { CertificateKeyAlgorithm::Unsupported };
|
||||
ByteBuffer raw_key;
|
||||
};
|
||||
|
||||
class Certificate {
|
||||
public:
|
||||
u16 version { 0 };
|
||||
CertificateKeyAlgorithm algorithm { CertificateKeyAlgorithm::Unsupported };
|
||||
CertificateKeyAlgorithm key_algorithm { CertificateKeyAlgorithm::Unsupported };
|
||||
CertificateKeyAlgorithm ec_algorithm { CertificateKeyAlgorithm::Unsupported };
|
||||
SubjectPublicKey public_key {};
|
||||
ByteBuffer exponent {};
|
||||
Crypto::PK::RSAPublicKey<Crypto::UnsignedBigInteger> public_key {};
|
||||
Crypto::PK::RSAPrivateKey<Crypto::UnsignedBigInteger> private_key {};
|
||||
struct Name {
|
||||
DeprecatedString country;
|
||||
DeprecatedString state;
|
||||
DeprecatedString location;
|
||||
DeprecatedString entity;
|
||||
DeprecatedString subject;
|
||||
DeprecatedString unit;
|
||||
} issuer, subject;
|
||||
Core::DateTime not_before;
|
||||
Core::DateTime not_after;
|
||||
Vector<DeprecatedString> SAN;
|
||||
RelativeDistinguishedName issuer, subject;
|
||||
Validity validity {};
|
||||
Vector<String> SAN;
|
||||
Vector<String> IAN;
|
||||
u8* ocsp { nullptr };
|
||||
Crypto::UnsignedBigInteger serial_number;
|
||||
ByteBuffer sign_key {};
|
||||
|
@ -62,71 +245,11 @@ public:
|
|||
Optional<size_t> path_length_constraint {};
|
||||
bool is_self_issued { false };
|
||||
|
||||
static Optional<Certificate> parse_asn1(ReadonlyBytes, bool client_cert = false);
|
||||
static ErrorOr<Certificate> parse_certificate(ReadonlyBytes, bool client_cert = false);
|
||||
|
||||
bool is_self_signed();
|
||||
bool is_valid() const;
|
||||
|
||||
DeprecatedString subject_identifier_string() const
|
||||
{
|
||||
StringBuilder cert_name;
|
||||
if (!subject.country.is_empty()) {
|
||||
cert_name.append("/C="sv);
|
||||
cert_name.append(subject.country);
|
||||
}
|
||||
if (!subject.state.is_empty()) {
|
||||
cert_name.append("/ST="sv);
|
||||
cert_name.append(subject.state);
|
||||
}
|
||||
if (!subject.location.is_empty()) {
|
||||
cert_name.append("/L="sv);
|
||||
cert_name.append(subject.location);
|
||||
}
|
||||
if (!subject.entity.is_empty()) {
|
||||
cert_name.append("/O="sv);
|
||||
cert_name.append(subject.entity);
|
||||
}
|
||||
if (!subject.unit.is_empty()) {
|
||||
cert_name.append("/OU="sv);
|
||||
cert_name.append(subject.unit);
|
||||
}
|
||||
if (!subject.subject.is_empty()) {
|
||||
cert_name.append("/CN="sv);
|
||||
cert_name.append(subject.subject);
|
||||
}
|
||||
return cert_name.to_deprecated_string();
|
||||
}
|
||||
|
||||
DeprecatedString issuer_identifier_string() const
|
||||
{
|
||||
StringBuilder cert_name;
|
||||
if (!issuer.country.is_empty()) {
|
||||
cert_name.append("/C="sv);
|
||||
cert_name.append(issuer.country);
|
||||
}
|
||||
if (!issuer.state.is_empty()) {
|
||||
cert_name.append("/ST="sv);
|
||||
cert_name.append(issuer.state);
|
||||
}
|
||||
if (!issuer.location.is_empty()) {
|
||||
cert_name.append("/L="sv);
|
||||
cert_name.append(issuer.location);
|
||||
}
|
||||
if (!issuer.entity.is_empty()) {
|
||||
cert_name.append("/O="sv);
|
||||
cert_name.append(issuer.entity);
|
||||
}
|
||||
if (!issuer.unit.is_empty()) {
|
||||
cert_name.append("/OU="sv);
|
||||
cert_name.append(issuer.unit);
|
||||
}
|
||||
if (!issuer.subject.is_empty()) {
|
||||
cert_name.append("/CN="sv);
|
||||
cert_name.append(issuer.subject);
|
||||
}
|
||||
return cert_name.to_deprecated_string();
|
||||
}
|
||||
|
||||
private:
|
||||
Optional<bool> m_is_self_signed;
|
||||
};
|
||||
|
|
|
@ -76,10 +76,14 @@ ssize_t TLSv12::handle_certificate(ReadonlyBytes buffer)
|
|||
}
|
||||
remaining -= certificate_size_specific;
|
||||
|
||||
auto certificate = Certificate::parse_asn1(buffer.slice(res_cert, certificate_size_specific), false);
|
||||
if (certificate.has_value()) {
|
||||
auto certificate = Certificate::parse_certificate(buffer.slice(res_cert, certificate_size_specific), false);
|
||||
if (!certificate.is_error()) {
|
||||
m_context.certificates.append(certificate.value());
|
||||
valid_certificate = true;
|
||||
} else {
|
||||
dbgln("Failed to parse client cert: {}", certificate.error());
|
||||
dbgln("{:hex-dump}", buffer.slice(res_cert, certificate_size_specific));
|
||||
dbgln("");
|
||||
}
|
||||
res_cert += certificate_size_specific;
|
||||
} while (remaining > 0);
|
||||
|
|
|
@ -186,7 +186,7 @@ void TLSv12::build_rsa_pre_master_secret(PacketBuilder& builder)
|
|||
print_buffer(m_context.premaster_key);
|
||||
}
|
||||
|
||||
Crypto::PK::RSA_PKCS1_EME rsa(certificate.public_key.modulus(), 0, certificate.public_key.public_exponent());
|
||||
Crypto::PK::RSA_PKCS1_EME rsa(certificate.public_key.rsa.modulus(), 0, certificate.public_key.rsa.public_exponent());
|
||||
|
||||
Vector<u8, 32> out;
|
||||
out.resize(rsa.output_size());
|
||||
|
|
|
@ -362,7 +362,7 @@ ssize_t TLSv12::verify_rsa_server_key_exchange(ReadonlyBytes server_key_info_buf
|
|||
// RFC5246 section 7.4.2: The sender's certificate MUST come first in the list.
|
||||
auto certificate_public_key = m_context.certificates.first().public_key;
|
||||
Crypto::PK::RSAPrivateKey dummy_private_key;
|
||||
auto rsa = Crypto::PK::RSA(certificate_public_key, dummy_private_key);
|
||||
auto rsa = Crypto::PK::RSA(certificate_public_key.rsa, dummy_private_key);
|
||||
|
||||
auto signature_verify_buffer_result = ByteBuffer::create_uninitialized(signature_length);
|
||||
if (signature_verify_buffer_result.is_error()) {
|
||||
|
|
|
@ -102,13 +102,13 @@ bool Certificate::is_valid() const
|
|||
{
|
||||
auto now = Core::DateTime::now();
|
||||
|
||||
if (now < not_before) {
|
||||
dbgln("certificate expired (not yet valid, signed for {})", not_before.to_deprecated_string());
|
||||
if (now < validity.not_before) {
|
||||
dbgln("certificate expired (not yet valid, signed for {})", validity.not_before.to_deprecated_string());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not_after < now) {
|
||||
dbgln("certificate expired (expiry date {})", not_after.to_deprecated_string());
|
||||
if (validity.not_after < now) {
|
||||
dbgln("certificate expired (expiry date {})", validity.not_after.to_deprecated_string());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -201,11 +201,12 @@ void TLSv12::set_root_certificates(Vector<Certificate> certificates)
|
|||
}
|
||||
|
||||
for (auto& cert : certificates) {
|
||||
if (!cert.is_valid())
|
||||
dbgln("Certificate for {} by {} is invalid, things may or may not work!", cert.subject.subject, cert.issuer.subject);
|
||||
if (!cert.is_valid()) {
|
||||
dbgln("Certificate for {} by {} is invalid, things may or may not work!", cert.subject.common_name(), cert.issuer.common_name());
|
||||
}
|
||||
// FIXME: Figure out what we should do when our root certs are invalid.
|
||||
|
||||
m_context.root_certificates.set(cert.subject_identifier_string(), cert);
|
||||
m_context.root_certificates.set(MUST(cert.subject.to_string()).to_deprecated_string(), cert);
|
||||
}
|
||||
dbgln_if(TLS_DEBUG, "{}: Set {} root certificates", this, m_context.root_certificates.size());
|
||||
}
|
||||
|
@ -228,7 +229,7 @@ static bool wildcard_matches(StringView host, StringView subject)
|
|||
|
||||
static bool certificate_subject_matches_host(Certificate& cert, StringView host)
|
||||
{
|
||||
if (wildcard_matches(host, cert.subject.subject))
|
||||
if (wildcard_matches(host, cert.subject.common_name()))
|
||||
return true;
|
||||
|
||||
for (auto& san : cert.SAN) {
|
||||
|
@ -279,15 +280,15 @@ bool Context::verify_chain(StringView host) const
|
|||
for (size_t cert_index = 0; cert_index < local_chain->size(); ++cert_index) {
|
||||
auto cert = local_chain->at(cert_index);
|
||||
|
||||
auto subject_string = cert.subject_identifier_string();
|
||||
auto issuer_string = cert.issuer_identifier_string();
|
||||
auto subject_string = MUST(cert.subject.to_string());
|
||||
auto issuer_string = MUST(cert.issuer.to_string());
|
||||
|
||||
if (!cert.is_valid()) {
|
||||
dbgln("verify_chain: Certificate is not valid {}", subject_string);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto maybe_root_certificate = root_certificates.get(issuer_string);
|
||||
auto maybe_root_certificate = root_certificates.get(issuer_string.to_deprecated_string());
|
||||
if (maybe_root_certificate.has_value()) {
|
||||
auto& root_certificate = *maybe_root_certificate;
|
||||
auto verification_correct = verify_certificate_pair(cert, root_certificate);
|
||||
|
@ -312,7 +313,7 @@ bool Context::verify_chain(StringView host) const
|
|||
}
|
||||
|
||||
auto parent_certificate = local_chain->at(cert_index + 1);
|
||||
if (issuer_string != parent_certificate.subject_identifier_string()) {
|
||||
if (issuer_string != MUST(parent_certificate.subject.to_string())) {
|
||||
dbgln("verify_chain: Next certificate in the chain is not the issuer of this certificate");
|
||||
return false;
|
||||
}
|
||||
|
@ -359,7 +360,7 @@ bool Context::verify_certificate_pair(Certificate const& subject, Certificate co
|
|||
}
|
||||
|
||||
Crypto::PK::RSAPrivateKey dummy_private_key;
|
||||
Crypto::PK::RSAPublicKey public_key_copy { issuer.public_key };
|
||||
Crypto::PK::RSAPublicKey public_key_copy { issuer.public_key.rsa };
|
||||
auto rsa = Crypto::PK::RSA(public_key_copy, dummy_private_key);
|
||||
auto verification_buffer_result = ByteBuffer::create_uninitialized(subject.signature_value.size());
|
||||
if (verification_buffer_result.is_error()) {
|
||||
|
@ -471,8 +472,8 @@ Vector<Certificate> TLSv12::parse_pem_certificate(ReadonlyBytes certificate_pem_
|
|||
return {};
|
||||
}
|
||||
|
||||
auto maybe_certificate = Certificate::parse_asn1(decoded_certificate);
|
||||
if (!maybe_certificate.has_value()) {
|
||||
auto maybe_certificate = Certificate::parse_certificate(decoded_certificate);
|
||||
if (!maybe_certificate.is_error()) {
|
||||
dbgln("Invalid certificate");
|
||||
return {};
|
||||
}
|
||||
|
@ -516,19 +517,20 @@ ErrorOr<Vector<Certificate>> DefaultRootCACertificates::reload_certificates(Byte
|
|||
auto certs = TRY(Crypto::decode_pems(data));
|
||||
|
||||
for (auto& cert : certs) {
|
||||
auto certificate_result = Certificate::parse_asn1(cert.bytes());
|
||||
auto certificate_result = Certificate::parse_certificate(cert.bytes());
|
||||
// If the certificate does not parse it is likely using elliptic curve keys/signatures, which are not
|
||||
// supported right now. It might make sense to cleanup cacert.pem before adding it to the system.
|
||||
if (!certificate_result.has_value()) {
|
||||
if (certificate_result.is_error()) {
|
||||
// FIXME: It would be nice to have more informations about the certificate we failed to parse.
|
||||
// Like: Issuer, Algorithm, CN, etc
|
||||
dbgln("Failed to load certificate: {}", certificate_result.error());
|
||||
continue;
|
||||
}
|
||||
auto certificate = certificate_result.release_value();
|
||||
if (certificate.is_certificate_authority && certificate.is_self_signed()) {
|
||||
TRY(certificates.try_append(move(certificate)));
|
||||
} else {
|
||||
dbgln("Skipped '{}' because it is not a valid root CA", certificate.subject_identifier_string());
|
||||
dbgln("Skipped '{}' because it is not a valid root CA", MUST(certificate.subject.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue