mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-10 13:00:29 +03:00
928287b782
We are currently using Core::DateTime, which is meant to represent local time. However, we are doing no conversion between the parsed time in UTC and local time, so we end up comparing time stamps from different time zones. Instead, store the parsed times as UnixDateTime, which is UTC. Then we can always compare the parsed times against the current UTC time. This also lets us store parsed milliseconds.
304 lines
9.2 KiB
C++
304 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/Time.h>
|
|
#include <AK/Types.h>
|
|
#include <LibCore/ConfigFile.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(move(key), move(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() const
|
|
{
|
|
return get(AttributeType::Ou).value_or({});
|
|
}
|
|
|
|
private:
|
|
HashMap<String, String> m_members;
|
|
};
|
|
|
|
struct Validity {
|
|
UnixDateTime not_before;
|
|
UnixDateTime 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(Span<ByteString> custom_cert_paths = {});
|
|
|
|
static DefaultRootCACertificates& the();
|
|
|
|
static void set_default_certificate_paths(Span<ByteString> paths);
|
|
|
|
private:
|
|
Vector<Certificate> m_ca_certificates;
|
|
};
|
|
|
|
}
|
|
|
|
using TLS::Certificate;
|
|
using TLS::DefaultRootCACertificates;
|