mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-02 00:13:02 +00:00
This follows the pattern of every other singleton in the system.
Also, remove use of AK::Singleton in place of a function-scope static.
There are only three uses of that class outside of the Kernel, and all
the remaining uses are suspect. We need it in the Kernel because we
want to avoid global destructors to prevent nasty surprises about
expected lifetimes of objects. In Userland, we have normal thread-safe
statics available. 7d11edbe1
attempted to standardize the pattern, but
it seems like more uses of awkward singleton creation have crept in or
were missed back then.
As a bonus, this fixes a linker error on macOS with -g -O0 for Lagom
WebContent.
306 lines
9.2 KiB
C++
306 lines
9.2 KiB
C++
/*
|
|
* Copyright (c) 2020-2023, the SerenityOS developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/ByteBuffer.h>
|
|
#include <AK/Forward.h>
|
|
#include <AK/Optional.h>
|
|
#include <AK/Types.h>
|
|
#include <LibCore/ConfigFile.h>
|
|
#include <LibCore/DateTime.h>
|
|
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
|
|
#include <LibCrypto/PK/RSA.h>
|
|
#include <LibTLS/Extensions.h>
|
|
|
|
namespace TLS {
|
|
|
|
constexpr static Array<int, 7>
|
|
rsa_encryption_oid { 1, 2, 840, 113549, 1, 1, 1 },
|
|
rsa_md5_encryption_oid { 1, 2, 840, 113549, 1, 1, 4 },
|
|
rsa_sha1_encryption_oid { 1, 2, 840, 113549, 1, 1, 5 },
|
|
rsa_sha256_encryption_oid { 1, 2, 840, 113549, 1, 1, 11 },
|
|
rsa_sha384_encryption_oid { 1, 2, 840, 113549, 1, 1, 12 },
|
|
rsa_sha512_encryption_oid { 1, 2, 840, 113549, 1, 1, 13 },
|
|
rsa_sha224_encryption_oid { 1, 2, 840, 113549, 1, 1, 14 },
|
|
ecdsa_with_sha224_encryption_oid { 1, 2, 840, 10045, 4, 3, 1 },
|
|
ecdsa_with_sha256_encryption_oid { 1, 2, 840, 10045, 4, 3, 2 },
|
|
ecdsa_with_sha384_encryption_oid { 1, 2, 840, 10045, 4, 3, 3 },
|
|
ecdsa_with_sha512_encryption_oid { 1, 2, 840, 10045, 4, 3, 4 },
|
|
ec_public_key_encryption_oid { 1, 2, 840, 10045, 2, 1 };
|
|
|
|
constexpr static Array<Array<int, 7>, 9> known_algorithm_identifiers {
|
|
rsa_encryption_oid,
|
|
rsa_md5_encryption_oid,
|
|
rsa_sha1_encryption_oid,
|
|
rsa_sha256_encryption_oid,
|
|
rsa_sha384_encryption_oid,
|
|
rsa_sha512_encryption_oid,
|
|
ecdsa_with_sha256_encryption_oid,
|
|
ecdsa_with_sha384_encryption_oid,
|
|
ec_public_key_encryption_oid
|
|
};
|
|
|
|
constexpr static Array<int, 7>
|
|
curve_ansip384r1 { 1, 3, 132, 0, 34 },
|
|
curve_prime256 { 1, 2, 840, 10045, 3, 1, 7 };
|
|
|
|
constexpr static Array<Array<int, 7>, 9> known_curve_identifiers {
|
|
curve_ansip384r1,
|
|
curve_prime256
|
|
};
|
|
|
|
constexpr static Array<int, 4>
|
|
key_usage_oid { 2, 5, 29, 15 },
|
|
subject_alternative_name_oid { 2, 5, 29, 17 },
|
|
issuer_alternative_name_oid { 2, 5, 29, 18 },
|
|
basic_constraints_oid { 2, 5, 29, 19 };
|
|
|
|
#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
|
|
}
|
|
|
|
struct AlgorithmIdentifier {
|
|
AlgorithmIdentifier()
|
|
{
|
|
}
|
|
|
|
explicit AlgorithmIdentifier(Vector<int, 9> identifier)
|
|
: identifier(identifier)
|
|
{
|
|
}
|
|
|
|
Vector<int, 9> identifier;
|
|
SupportedGroup ec_parameters {};
|
|
};
|
|
|
|
struct BasicConstraints {
|
|
bool is_certificate_authority;
|
|
Crypto::UnsignedBigInteger path_length_constraint;
|
|
};
|
|
|
|
class RelativeDistinguishedName {
|
|
public:
|
|
ErrorOr<String> to_string() const;
|
|
|
|
ErrorOr<AK::HashSetResult> set(String key, String value)
|
|
{
|
|
return m_members.try_set(key, value);
|
|
}
|
|
|
|
Optional<String> get(StringView key) const
|
|
{
|
|
return m_members.get(key);
|
|
}
|
|
|
|
Optional<String> get(AttributeType key) const
|
|
{
|
|
return m_members.get(enum_value(key));
|
|
}
|
|
|
|
Optional<String> get(ObjectClass key) const
|
|
{
|
|
return m_members.get(enum_value(key));
|
|
}
|
|
|
|
String common_name() const
|
|
{
|
|
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;
|
|
|
|
AlgorithmIdentifier algorithm;
|
|
ByteBuffer raw_key;
|
|
};
|
|
|
|
class Certificate {
|
|
public:
|
|
u16 version { 0 };
|
|
AlgorithmIdentifier algorithm;
|
|
SubjectPublicKey public_key;
|
|
ByteBuffer exponent {};
|
|
Crypto::PK::RSAPrivateKey<Crypto::UnsignedBigInteger> private_key {};
|
|
RelativeDistinguishedName issuer, subject;
|
|
Validity validity {};
|
|
Vector<String> SAN;
|
|
Vector<String> IAN;
|
|
u8* ocsp { nullptr };
|
|
Crypto::UnsignedBigInteger serial_number;
|
|
ByteBuffer sign_key {};
|
|
ByteBuffer fingerprint {};
|
|
ByteBuffer der {};
|
|
ByteBuffer data {};
|
|
AlgorithmIdentifier signature_algorithm;
|
|
ByteBuffer signature_value {};
|
|
ByteBuffer original_asn1 {};
|
|
ByteBuffer tbs_asn1 {};
|
|
bool is_allowed_to_sign_certificate { false };
|
|
bool is_certificate_authority { false };
|
|
Optional<size_t> path_length_constraint {};
|
|
bool is_self_issued { false };
|
|
|
|
static ErrorOr<Certificate> parse_certificate(ReadonlyBytes, bool client_cert = false);
|
|
|
|
bool is_self_signed();
|
|
bool is_valid() const;
|
|
|
|
private:
|
|
Optional<bool> m_is_self_signed;
|
|
};
|
|
|
|
class DefaultRootCACertificates {
|
|
public:
|
|
DefaultRootCACertificates();
|
|
|
|
Vector<Certificate> const& certificates() const { return m_ca_certificates; }
|
|
|
|
static ErrorOr<Vector<Certificate>> parse_pem_root_certificate_authorities(ByteBuffer&);
|
|
static ErrorOr<Vector<Certificate>> load_certificates();
|
|
|
|
static DefaultRootCACertificates& the();
|
|
|
|
private:
|
|
Vector<Certificate> m_ca_certificates;
|
|
};
|
|
|
|
}
|
|
|
|
using TLS::Certificate;
|
|
using TLS::DefaultRootCACertificates;
|