diff options
Diffstat (limited to 'Userland/Libraries/LibTLS')
-rw-r--r-- | Userland/Libraries/LibTLS/Certificate.cpp | 119 | ||||
-rw-r--r-- | Userland/Libraries/LibTLS/Certificate.h | 85 | ||||
-rw-r--r-- | Userland/Libraries/LibTLS/TLSv12.cpp | 26 |
3 files changed, 96 insertions, 134 deletions
diff --git a/Userland/Libraries/LibTLS/Certificate.cpp b/Userland/Libraries/LibTLS/Certificate.cpp index f857d22c38..839538cc74 100644 --- a/Userland/Libraries/LibTLS/Certificate.cpp +++ b/Userland/Libraries/LibTLS/Certificate.cpp @@ -11,51 +11,9 @@ #include <LibCrypto/ASN1/ASN1.h> #include <LibCrypto/ASN1/DER.h> #include <LibCrypto/ASN1/PEM.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, 3 }, - 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 ERROR_WITH_SCOPE(error) \ do { \ return Error::from_string_view(TRY(String::formatted("{}: {}", current_scope, error))); \ @@ -122,34 +80,6 @@ static ErrorOr<SupportedGroup> oid_to_curve(Vector<int> curve) return Error::from_string_view(TRY(String::formatted("Unknown curve oid {}", curve))); } -static ErrorOr<CertificateKeyAlgorithm> oid_to_algorithm(Vector<int> algorithm) -{ - if (algorithm == rsa_encryption_oid) - return CertificateKeyAlgorithm::RSA_RSA; - else if (algorithm == rsa_md5_encryption_oid) - return CertificateKeyAlgorithm::RSA_MD5; - else if (algorithm == rsa_sha1_encryption_oid) - return CertificateKeyAlgorithm::RSA_SHA1; - else if (algorithm == rsa_sha256_encryption_oid) - return CertificateKeyAlgorithm::RSA_SHA256; - else if (algorithm == rsa_sha384_encryption_oid) - return CertificateKeyAlgorithm::RSA_SHA384; - else if (algorithm == rsa_sha512_encryption_oid) - return CertificateKeyAlgorithm::RSA_SHA512; - else if (algorithm == rsa_sha224_encryption_oid) - return CertificateKeyAlgorithm::RSA_SHA224; - else if (algorithm == ecdsa_with_sha224_encryption_oid) - return CertificateKeyAlgorithm::ECDSA_SHA224; - else if (algorithm == ecdsa_with_sha256_encryption_oid) - return CertificateKeyAlgorithm::ECDSA_SHA256; - else if (algorithm == ecdsa_with_sha384_encryption_oid) - return CertificateKeyAlgorithm::ECDSA_SHA384; - else if (algorithm == ecdsa_with_sha512_encryption_oid) - return CertificateKeyAlgorithm::ECDSA_SHA512; - - return Error::from_string_view(TRY(String::formatted("Unknown algorithm oid {}", algorithm))); -} - static ErrorOr<Crypto::UnsignedBigInteger> parse_version(Crypto::ASN1::Decoder& decoder, Vector<StringView> current_scope) { // Version ::= INTEGER {v1(0), v2(1), v3(2)} @@ -203,7 +133,7 @@ static ErrorOr<SupportedGroup> parse_ec_parameters(Crypto::ASN1::Decoder& decode return oid_to_curve(named_curve); } -static ErrorOr<CertificateKeyAlgorithm> parse_algorithm_identifier(Crypto::ASN1::Decoder& decoder, Vector<StringView> current_scope) +static ErrorOr<AlgorithmIdentifier> parse_algorithm_identifier(Crypto::ASN1::Decoder& decoder, Vector<StringView> current_scope) { // AlgorithmIdentifier{ALGORITHM:SupportedAlgorithms} ::= SEQUENCE { // algorithm ALGORITHM.&id({SupportedAlgorithms}), @@ -264,7 +194,7 @@ static ErrorOr<CertificateKeyAlgorithm> parse_algorithm_identifier(Crypto::ASN1: POP_SCOPE(); EXIT_SCOPE(); - return oid_to_algorithm(algorithm); + return AlgorithmIdentifier(algorithm); } // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or @@ -288,7 +218,7 @@ static ErrorOr<CertificateKeyAlgorithm> parse_algorithm_identifier(Crypto::ASN1: if (is_no_parameter_algorithm) { EXIT_SCOPE(); - return oid_to_algorithm(algorithm); + return AlgorithmIdentifier(algorithm); } if (algorithm.span() == ec_public_key_encryption_oid.span()) { @@ -297,7 +227,7 @@ static ErrorOr<CertificateKeyAlgorithm> parse_algorithm_identifier(Crypto::ASN1: if (decoder.eof()) { EXIT_SCOPE(); - return oid_to_algorithm(algorithm); + return AlgorithmIdentifier(algorithm); } auto tag = TRY(decoder.peek()); @@ -308,16 +238,14 @@ static ErrorOr<CertificateKeyAlgorithm> parse_algorithm_identifier(Crypto::ASN1: POP_SCOPE(); EXIT_SCOPE(); - return oid_to_algorithm(algorithm); + return AlgorithmIdentifier(algorithm); } - auto ec_parameters = TRY(parse_ec_parameters(decoder, current_scope)); - EXIT_SCOPE(); + auto algorithm_identifier = AlgorithmIdentifier(algorithm); + algorithm_identifier.ec_parameters = TRY(parse_ec_parameters(decoder, current_scope)); - if (ec_parameters == SupportedGroup::SECP256R1) - return CertificateKeyAlgorithm::ECDSA_SECP256R1; - else if (ec_parameters == SupportedGroup::SECP384R1) - return CertificateKeyAlgorithm::ECDSA_SECP384R1; + EXIT_SCOPE(); + return algorithm_identifier; } ERROR_WITH_SCOPE(TRY(String::formatted("Unhandled parameters for algorithm {}", algorithm))); @@ -432,27 +360,29 @@ static ErrorOr<SubjectPublicKey> parse_subject_public_key_info(Crypto::ASN1::Dec READ_OBJECT(BitString, Crypto::ASN1::BitStringView, value); POP_SCOPE(); - switch (public_key.algorithm) { - case CertificateKeyAlgorithm::ECDSA_SECP256R1: - case CertificateKeyAlgorithm::ECDSA_SECP384R1: { - public_key.raw_key = TRY(ByteBuffer::copy(value.raw_bytes())); - break; - } - case CertificateKeyAlgorithm::RSA_RSA: { - public_key.raw_key = TRY(ByteBuffer::copy(value.raw_bytes())); + public_key.raw_key = TRY(ByteBuffer::copy(value.raw_bytes())); + + if (public_key.algorithm.identifier.span() == rsa_encryption_oid.span()) { auto key = Crypto::PK::RSA::parse_rsa_key(value.raw_bytes()); if (!key.public_key.length()) { return Error::from_string_literal("Invalid RSA key"); } public_key.rsa = move(key.public_key); - break; - } - default: { - ERROR_WITH_SCOPE(TRY(String::formatted("Unknown algorithm {}", static_cast<u8>(public_key.algorithm)))); + + EXIT_SCOPE(); + return public_key; } + + if (public_key.algorithm.identifier.span() == ec_public_key_encryption_oid.span()) { + // Note: Raw key is already stored, so we can just exit out at this point. + EXIT_SCOPE(); + return public_key; } + String algo_oid = TRY(String::join("."sv, public_key.algorithm.identifier)); + ERROR_WITH_SCOPE(TRY(String::formatted("Unhandled algorithm {}", algo_oid))); + EXIT_SCOPE(); return public_key; } @@ -822,8 +752,7 @@ ErrorOr<Certificate> Certificate::parse_certificate(ReadonlyBytes buffer, bool) Certificate certificate = TRY(parse_tbs_certificate(decoder, current_scope)); certificate.original_asn1 = TRY(ByteBuffer::copy(buffer)); - CertificateKeyAlgorithm signature_algorithm = TRY(parse_algorithm_identifier(decoder, current_scope)); - certificate.signature_algorithm = signature_algorithm; + certificate.signature_algorithm = TRY(parse_algorithm_identifier(decoder, current_scope)); PUSH_SCOPE("signature"sv); READ_OBJECT(BitString, Crypto::ASN1::BitStringView, signature); diff --git a/Userland/Libraries/LibTLS/Certificate.h b/Userland/Libraries/LibTLS/Certificate.h index 464809fe43..612c7ca11a 100644 --- a/Userland/Libraries/LibTLS/Certificate.h +++ b/Userland/Libraries/LibTLS/Certificate.h @@ -15,9 +15,51 @@ #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, 3 }, + 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 \ @@ -129,28 +171,18 @@ constexpr static StringView enum_value(AttributeType object_class) #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 AlgorithmIdentifier { + AlgorithmIdentifier() + { + } + + explicit AlgorithmIdentifier(Vector<int, 9> identifier) + : identifier(identifier) + { + } + + Vector<int, 9> identifier; + SupportedGroup ec_parameters {}; }; struct BasicConstraints { @@ -215,16 +247,15 @@ class SubjectPublicKey { public: Crypto::PK::RSAPublicKey<Crypto::UnsignedBigInteger> rsa; - CertificateKeyAlgorithm algorithm { CertificateKeyAlgorithm::Unsupported }; + AlgorithmIdentifier algorithm; ByteBuffer raw_key; }; class Certificate { public: u16 version { 0 }; - CertificateKeyAlgorithm algorithm { CertificateKeyAlgorithm::Unsupported }; - CertificateKeyAlgorithm ec_algorithm { CertificateKeyAlgorithm::Unsupported }; - SubjectPublicKey public_key {}; + AlgorithmIdentifier algorithm; + SubjectPublicKey public_key; ByteBuffer exponent {}; Crypto::PK::RSAPrivateKey<Crypto::UnsignedBigInteger> private_key {}; RelativeDistinguishedName issuer, subject; @@ -237,7 +268,7 @@ public: ByteBuffer fingerprint {}; ByteBuffer der {}; ByteBuffer data {}; - CertificateKeyAlgorithm signature_algorithm { CertificateKeyAlgorithm::Unsupported }; + AlgorithmIdentifier signature_algorithm; ByteBuffer signature_value {}; ByteBuffer original_asn1 {}; bool is_allowed_to_sign_certificate { false }; diff --git a/Userland/Libraries/LibTLS/TLSv12.cpp b/Userland/Libraries/LibTLS/TLSv12.cpp index 4f0b785b03..caf762f065 100644 --- a/Userland/Libraries/LibTLS/TLSv12.cpp +++ b/Userland/Libraries/LibTLS/TLSv12.cpp @@ -344,22 +344,24 @@ bool Context::verify_chain(StringView host) const bool Context::verify_certificate_pair(Certificate const& subject, Certificate const& issuer) const { - Crypto::Hash::HashKind kind; - switch (subject.signature_algorithm) { - case CertificateKeyAlgorithm::RSA_SHA1: + Crypto::Hash::HashKind kind = Crypto::Hash::HashKind::Unknown; + auto identifier = subject.signature_algorithm.identifier; + + if (identifier == rsa_encryption_oid) + kind = Crypto::Hash::HashKind::None; + if (identifier == rsa_md5_encryption_oid) + kind = Crypto::Hash::HashKind::MD5; + if (identifier == rsa_sha1_encryption_oid) kind = Crypto::Hash::HashKind::SHA1; - break; - case CertificateKeyAlgorithm::RSA_SHA256: + if (identifier == rsa_sha256_encryption_oid) kind = Crypto::Hash::HashKind::SHA256; - break; - case CertificateKeyAlgorithm::RSA_SHA384: + if (identifier == rsa_sha384_encryption_oid) kind = Crypto::Hash::HashKind::SHA384; - break; - case CertificateKeyAlgorithm::RSA_SHA512: + if (identifier == rsa_sha512_encryption_oid) kind = Crypto::Hash::HashKind::SHA512; - break; - default: - dbgln("verify_certificate_pair: Unknown signature algorithm, expected RSA with SHA1/256/384/512, got {}", (u8)subject.signature_algorithm); + + if (kind == Crypto::Hash::HashKind::Unknown) { + dbgln("verify_certificate_pair: Unknown signature algorithm, expected RSA with SHA1/256/384/512, got OID {}", identifier); return false; } |