xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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