1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef QUICHE_QUIC_CORE_CRYPTO_CERTIFICATE_VIEW_H_ 6 #define QUICHE_QUIC_CORE_CRYPTO_CERTIFICATE_VIEW_H_ 7 8 #include <istream> 9 #include <memory> 10 #include <optional> 11 #include <vector> 12 13 #include "absl/strings/string_view.h" 14 #include "openssl/base.h" 15 #include "openssl/bytestring.h" 16 #include "openssl/evp.h" 17 #include "quiche/quic/core/crypto/boring_utils.h" 18 #include "quiche/quic/core/quic_time.h" 19 #include "quiche/quic/core/quic_types.h" 20 #include "quiche/quic/platform/api/quic_export.h" 21 #include "quiche/quic/platform/api/quic_ip_address.h" 22 23 namespace quic { 24 25 struct QUICHE_EXPORT PemReadResult { 26 enum Status { kOk, kEof, kError }; 27 Status status; 28 std::string contents; 29 // The type of the PEM message (e.g., if the message starts with 30 // "-----BEGIN CERTIFICATE-----", the |type| would be "CERTIFICATE"). 31 std::string type; 32 }; 33 34 // Reads |input| line-by-line and returns the next available PEM message. 35 QUICHE_EXPORT PemReadResult ReadNextPemMessage(std::istream* input); 36 37 // Cryptograhpic algorithms recognized in X.509. 38 enum class PublicKeyType { 39 kRsa, 40 kP256, 41 kP384, 42 kEd25519, 43 kUnknown, 44 }; 45 QUICHE_EXPORT std::string PublicKeyTypeToString(PublicKeyType type); 46 QUICHE_EXPORT PublicKeyType 47 PublicKeyTypeFromSignatureAlgorithm(uint16_t signature_algorithm); 48 49 // Returns the list of the signature algorithms that can be processed by 50 // CertificateView::VerifySignature() and CertificatePrivateKey::Sign(). 51 QUICHE_EXPORT QuicSignatureAlgorithmVector 52 SupportedSignatureAlgorithmsForQuic(); 53 54 // CertificateView represents a parsed version of a single X.509 certificate. As 55 // the word "view" implies, it does not take ownership of the underlying strings 56 // and consists primarily of pointers into the certificate that is passed into 57 // the parser. 58 class QUICHE_EXPORT CertificateView { 59 public: 60 // Parses a single DER-encoded X.509 certificate. Returns nullptr on parse 61 // error. 62 static std::unique_ptr<CertificateView> ParseSingleCertificate( 63 absl::string_view certificate); 64 65 // Loads all PEM-encoded X.509 certificates found in the |input| stream 66 // without parsing them. Returns an empty vector if any parsing error occurs. 67 static std::vector<std::string> LoadPemFromStream(std::istream* input); 68 validity_start()69 QuicWallTime validity_start() const { return validity_start_; } validity_end()70 QuicWallTime validity_end() const { return validity_end_; } public_key()71 const EVP_PKEY* public_key() const { return public_key_.get(); } 72 subject_alt_name_domains()73 const std::vector<absl::string_view>& subject_alt_name_domains() const { 74 return subject_alt_name_domains_; 75 } subject_alt_name_ips()76 const std::vector<QuicIpAddress>& subject_alt_name_ips() const { 77 return subject_alt_name_ips_; 78 } 79 80 // Returns a human-readable representation of the Subject field. The format 81 // is similar to RFC 2253, but does not match it exactly. 82 std::optional<std::string> GetHumanReadableSubject() const; 83 84 // |signature_algorithm| is a TLS signature algorithm ID. 85 bool VerifySignature(absl::string_view data, absl::string_view signature, 86 uint16_t signature_algorithm) const; 87 88 // Returns the type of the key used in the certificate's SPKI. 89 PublicKeyType public_key_type() const; 90 91 private: 92 CertificateView() = default; 93 94 QuicWallTime validity_start_ = QuicWallTime::Zero(); 95 QuicWallTime validity_end_ = QuicWallTime::Zero(); 96 absl::string_view subject_der_; 97 98 // Public key parsed from SPKI. 99 bssl::UniquePtr<EVP_PKEY> public_key_; 100 101 // SubjectAltName, https://tools.ietf.org/html/rfc5280#section-4.2.1.6 102 std::vector<absl::string_view> subject_alt_name_domains_; 103 std::vector<QuicIpAddress> subject_alt_name_ips_; 104 105 // Called from ParseSingleCertificate(). 106 bool ParseExtensions(CBS extensions); 107 bool ValidatePublicKeyParameters(); 108 }; 109 110 // CertificatePrivateKey represents a private key that can be used with an X.509 111 // certificate. 112 class QUICHE_EXPORT CertificatePrivateKey { 113 public: CertificatePrivateKey(bssl::UniquePtr<EVP_PKEY> private_key)114 explicit CertificatePrivateKey(bssl::UniquePtr<EVP_PKEY> private_key) 115 : private_key_(std::move(private_key)) {} 116 117 // Loads a DER-encoded PrivateKeyInfo structure (RFC 5958) as a private key. 118 static std::unique_ptr<CertificatePrivateKey> LoadFromDer( 119 absl::string_view private_key); 120 121 // Loads a private key from a PEM file formatted according to RFC 7468. Also 122 // supports legacy OpenSSL RSA key format ("BEGIN RSA PRIVATE KEY"). 123 static std::unique_ptr<CertificatePrivateKey> LoadPemFromStream( 124 std::istream* input); 125 126 // |signature_algorithm| is a TLS signature algorithm ID. 127 std::string Sign(absl::string_view input, uint16_t signature_algorithm) const; 128 129 // Verifies that the private key in question matches the public key of the 130 // certificate |view|. 131 bool MatchesPublicKey(const CertificateView& view) const; 132 133 // Verifies that the private key can be used with the specified TLS signature 134 // algorithm. 135 bool ValidForSignatureAlgorithm(uint16_t signature_algorithm) const; 136 private_key()137 EVP_PKEY* private_key() const { return private_key_.get(); } 138 139 private: 140 CertificatePrivateKey() = default; 141 142 bssl::UniquePtr<EVP_PKEY> private_key_; 143 }; 144 145 // Parses a DER-encoded X.509 NameAttribute. Exposed primarily for testing. 146 QUICHE_EXPORT std::optional<std::string> X509NameAttributeToString(CBS input); 147 148 // Parses a DER time based on the specified ASN.1 tag. Exposed primarily for 149 // testing. 150 QUICHE_EXPORT std::optional<quic::QuicWallTime> ParseDerTime( 151 unsigned tag, absl::string_view payload); 152 153 } // namespace quic 154 155 #endif // QUICHE_QUIC_CORE_CRYPTO_CERTIFICATE_VIEW_H_ 156