xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.cc (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 #include "quiche/quic/core/crypto/proof_source_x509.h"
6 
7 #include <memory>
8 #include <optional>
9 
10 #include "absl/strings/str_cat.h"
11 #include "absl/strings/string_view.h"
12 #include "openssl/ssl.h"
13 #include "quiche/quic/core/crypto/certificate_view.h"
14 #include "quiche/quic/core/crypto/crypto_protocol.h"
15 #include "quiche/quic/core/crypto/crypto_utils.h"
16 #include "quiche/quic/core/quic_data_writer.h"
17 #include "quiche/quic/platform/api/quic_bug_tracker.h"
18 #include "quiche/common/quiche_endian.h"
19 
20 namespace quic {
21 
ProofSourceX509(quiche::QuicheReferenceCountedPointer<Chain> default_chain,CertificatePrivateKey default_key)22 ProofSourceX509::ProofSourceX509(
23     quiche::QuicheReferenceCountedPointer<Chain> default_chain,
24     CertificatePrivateKey default_key) {
25   if (!AddCertificateChain(default_chain, std::move(default_key))) {
26     return;
27   }
28   default_certificate_ = &certificates_.front();
29 }
30 
Create(quiche::QuicheReferenceCountedPointer<Chain> default_chain,CertificatePrivateKey default_key)31 std::unique_ptr<ProofSourceX509> ProofSourceX509::Create(
32     quiche::QuicheReferenceCountedPointer<Chain> default_chain,
33     CertificatePrivateKey default_key) {
34   std::unique_ptr<ProofSourceX509> result(
35       new ProofSourceX509(default_chain, std::move(default_key)));
36   if (!result->valid()) {
37     return nullptr;
38   }
39   return result;
40 }
41 
GetProof(const QuicSocketAddress &,const QuicSocketAddress &,const std::string & hostname,const std::string & server_config,QuicTransportVersion,absl::string_view chlo_hash,std::unique_ptr<ProofSource::Callback> callback)42 void ProofSourceX509::GetProof(
43     const QuicSocketAddress& /*server_address*/,
44     const QuicSocketAddress& /*client_address*/, const std::string& hostname,
45     const std::string& server_config,
46     QuicTransportVersion /*transport_version*/, absl::string_view chlo_hash,
47     std::unique_ptr<ProofSource::Callback> callback) {
48   QuicCryptoProof proof;
49 
50   if (!valid()) {
51     QUIC_BUG(ProofSourceX509::GetProof called in invalid state)
52         << "ProofSourceX509::GetProof called while the object is not valid";
53     callback->Run(/*ok=*/false, nullptr, proof, nullptr);
54     return;
55   }
56 
57   std::optional<std::string> payload =
58       CryptoUtils::GenerateProofPayloadToBeSigned(chlo_hash, server_config);
59   if (!payload.has_value()) {
60     callback->Run(/*ok=*/false, nullptr, proof, nullptr);
61     return;
62   }
63 
64   Certificate* certificate = GetCertificate(hostname, &proof.cert_matched_sni);
65   proof.signature =
66       certificate->key.Sign(*payload, SSL_SIGN_RSA_PSS_RSAE_SHA256);
67   MaybeAddSctsForHostname(hostname, proof.leaf_cert_scts);
68   callback->Run(/*ok=*/!proof.signature.empty(), certificate->chain, proof,
69                 nullptr);
70 }
71 
72 quiche::QuicheReferenceCountedPointer<ProofSource::Chain>
GetCertChain(const QuicSocketAddress &,const QuicSocketAddress &,const std::string & hostname,bool * cert_matched_sni)73 ProofSourceX509::GetCertChain(const QuicSocketAddress& /*server_address*/,
74                               const QuicSocketAddress& /*client_address*/,
75                               const std::string& hostname,
76                               bool* cert_matched_sni) {
77   if (!valid()) {
78     QUIC_BUG(ProofSourceX509::GetCertChain called in invalid state)
79         << "ProofSourceX509::GetCertChain called while the object is not "
80            "valid";
81     return nullptr;
82   }
83 
84   return GetCertificate(hostname, cert_matched_sni)->chain;
85 }
86 
ComputeTlsSignature(const QuicSocketAddress &,const QuicSocketAddress &,const std::string & hostname,uint16_t signature_algorithm,absl::string_view in,std::unique_ptr<ProofSource::SignatureCallback> callback)87 void ProofSourceX509::ComputeTlsSignature(
88     const QuicSocketAddress& /*server_address*/,
89     const QuicSocketAddress& /*client_address*/, const std::string& hostname,
90     uint16_t signature_algorithm, absl::string_view in,
91     std::unique_ptr<ProofSource::SignatureCallback> callback) {
92   if (!valid()) {
93     QUIC_BUG(ProofSourceX509::ComputeTlsSignature called in invalid state)
94         << "ProofSourceX509::ComputeTlsSignature called while the object is "
95            "not valid";
96     callback->Run(/*ok=*/false, "", nullptr);
97     return;
98   }
99 
100   bool cert_matched_sni;
101   std::string signature = GetCertificate(hostname, &cert_matched_sni)
102                               ->key.Sign(in, signature_algorithm);
103   callback->Run(/*ok=*/!signature.empty(), signature, nullptr);
104 }
105 
SupportedTlsSignatureAlgorithms() const106 QuicSignatureAlgorithmVector ProofSourceX509::SupportedTlsSignatureAlgorithms()
107     const {
108   return SupportedSignatureAlgorithmsForQuic();
109 }
110 
GetTicketCrypter()111 ProofSource::TicketCrypter* ProofSourceX509::GetTicketCrypter() {
112   return nullptr;
113 }
114 
AddCertificateChain(quiche::QuicheReferenceCountedPointer<Chain> chain,CertificatePrivateKey key)115 bool ProofSourceX509::AddCertificateChain(
116     quiche::QuicheReferenceCountedPointer<Chain> chain,
117     CertificatePrivateKey key) {
118   if (chain->certs.empty()) {
119     QUIC_BUG(quic_bug_10644_1) << "Empty certificate chain supplied.";
120     return false;
121   }
122 
123   std::unique_ptr<CertificateView> leaf =
124       CertificateView::ParseSingleCertificate(chain->certs[0]);
125   if (leaf == nullptr) {
126     QUIC_BUG(quic_bug_10644_2)
127         << "Unable to parse X.509 leaf certificate in the supplied chain.";
128     return false;
129   }
130   if (!key.MatchesPublicKey(*leaf)) {
131     QUIC_BUG(quic_bug_10644_3)
132         << "Private key does not match the leaf certificate.";
133     return false;
134   }
135 
136   certificates_.push_front(Certificate{
137       chain,
138       std::move(key),
139   });
140   Certificate* certificate = &certificates_.front();
141 
142   for (absl::string_view host : leaf->subject_alt_name_domains()) {
143     certificate_map_[std::string(host)] = certificate;
144   }
145   return true;
146 }
147 
GetCertificate(const std::string & hostname,bool * cert_matched_sni) const148 ProofSourceX509::Certificate* ProofSourceX509::GetCertificate(
149     const std::string& hostname, bool* cert_matched_sni) const {
150   QUICHE_DCHECK(valid());
151   auto it = certificate_map_.find(hostname);
152   if (it != certificate_map_.end()) {
153     *cert_matched_sni = true;
154     return it->second;
155   }
156   auto dot_pos = hostname.find('.');
157   if (dot_pos != std::string::npos) {
158     std::string wildcard = absl::StrCat("*", hostname.substr(dot_pos));
159     it = certificate_map_.find(wildcard);
160     if (it != certificate_map_.end()) {
161       *cert_matched_sni = true;
162       return it->second;
163     }
164   }
165   *cert_matched_sni = false;
166   return default_certificate_;
167 }
168 
169 }  // namespace quic
170