1 // Copyright (c) 2021 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/test_tools/fake_proof_source_handle.h"
6
7 #include <cstddef>
8 #include <cstdint>
9 #include <memory>
10 #include <optional>
11 #include <string>
12 #include <utility>
13 #include <vector>
14
15 #include "absl/strings/string_view.h"
16 #include "quiche/quic/core/crypto/proof_source.h"
17 #include "quiche/quic/core/quic_connection_id.h"
18 #include "quiche/quic/core/quic_types.h"
19 #include "quiche/quic/platform/api/quic_bug_tracker.h"
20 #include "quiche/quic/platform/api/quic_socket_address.h"
21 #include "quiche/common/platform/api/quiche_logging.h"
22 #include "quiche/common/platform/api/quiche_reference_counted.h"
23
24 namespace quic {
25 namespace test {
26 namespace {
27
28 struct ComputeSignatureResult {
29 bool ok;
30 std::string signature;
31 std::unique_ptr<ProofSource::Details> details;
32 };
33
34 class ResultSavingSignatureCallback : public ProofSource::SignatureCallback {
35 public:
ResultSavingSignatureCallback(std::optional<ComputeSignatureResult> * result)36 explicit ResultSavingSignatureCallback(
37 std::optional<ComputeSignatureResult>* result)
38 : result_(result) {
39 QUICHE_DCHECK(!result_->has_value());
40 }
Run(bool ok,std::string signature,std::unique_ptr<ProofSource::Details> details)41 void Run(bool ok, std::string signature,
42 std::unique_ptr<ProofSource::Details> details) override {
43 result_->emplace(
44 ComputeSignatureResult{ok, std::move(signature), std::move(details)});
45 }
46
47 private:
48 std::optional<ComputeSignatureResult>* result_;
49 };
50
ComputeSignatureNow(ProofSource * delegate,const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,const std::string & hostname,uint16_t signature_algorithm,absl::string_view in)51 ComputeSignatureResult ComputeSignatureNow(
52 ProofSource* delegate, const QuicSocketAddress& server_address,
53 const QuicSocketAddress& client_address, const std::string& hostname,
54 uint16_t signature_algorithm, absl::string_view in) {
55 std::optional<ComputeSignatureResult> result;
56 delegate->ComputeTlsSignature(
57 server_address, client_address, hostname, signature_algorithm, in,
58 std::make_unique<ResultSavingSignatureCallback>(&result));
59 QUICHE_CHECK(result.has_value())
60 << "delegate->ComputeTlsSignature must computes a "
61 "signature immediately";
62 return std::move(result.value());
63 }
64 } // namespace
65
FakeProofSourceHandle(ProofSource * delegate,ProofSourceHandleCallback * callback,Action select_cert_action,Action compute_signature_action,QuicDelayedSSLConfig delayed_ssl_config)66 FakeProofSourceHandle::FakeProofSourceHandle(
67 ProofSource* delegate, ProofSourceHandleCallback* callback,
68 Action select_cert_action, Action compute_signature_action,
69 QuicDelayedSSLConfig delayed_ssl_config)
70 : delegate_(delegate),
71 callback_(callback),
72 select_cert_action_(select_cert_action),
73 compute_signature_action_(compute_signature_action),
74 delayed_ssl_config_(delayed_ssl_config) {}
75
CloseHandle()76 void FakeProofSourceHandle::CloseHandle() {
77 select_cert_op_.reset();
78 compute_signature_op_.reset();
79 closed_ = true;
80 }
81
SelectCertificate(const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,const QuicConnectionId & original_connection_id,absl::string_view ssl_capabilities,const std::string & hostname,absl::string_view client_hello,const std::string & alpn,std::optional<std::string> alps,const std::vector<uint8_t> & quic_transport_params,const std::optional<std::vector<uint8_t>> & early_data_context,const QuicSSLConfig & ssl_config)82 QuicAsyncStatus FakeProofSourceHandle::SelectCertificate(
83 const QuicSocketAddress& server_address,
84 const QuicSocketAddress& client_address,
85 const QuicConnectionId& original_connection_id,
86 absl::string_view ssl_capabilities, const std::string& hostname,
87 absl::string_view client_hello, const std::string& alpn,
88 std::optional<std::string> alps,
89 const std::vector<uint8_t>& quic_transport_params,
90 const std::optional<std::vector<uint8_t>>& early_data_context,
91 const QuicSSLConfig& ssl_config) {
92 if (select_cert_action_ != Action::FAIL_SYNC_DO_NOT_CHECK_CLOSED) {
93 QUICHE_CHECK(!closed_);
94 }
95 all_select_cert_args_.push_back(
96 SelectCertArgs(server_address, client_address, original_connection_id,
97 ssl_capabilities, hostname, client_hello, alpn, alps,
98 quic_transport_params, early_data_context, ssl_config));
99
100 if (select_cert_action_ == Action::DELEGATE_ASYNC ||
101 select_cert_action_ == Action::FAIL_ASYNC) {
102 select_cert_op_.emplace(delegate_, callback_, select_cert_action_,
103 all_select_cert_args_.back(), delayed_ssl_config_);
104 return QUIC_PENDING;
105 } else if (select_cert_action_ == Action::FAIL_SYNC ||
106 select_cert_action_ == Action::FAIL_SYNC_DO_NOT_CHECK_CLOSED) {
107 callback()->OnSelectCertificateDone(
108 /*ok=*/false,
109 /*is_sync=*/true,
110 ProofSourceHandleCallback::LocalSSLConfig{nullptr, delayed_ssl_config_},
111 /*ticket_encryption_key=*/absl::string_view(),
112 /*cert_matched_sni=*/false);
113 return QUIC_FAILURE;
114 }
115
116 QUICHE_DCHECK(select_cert_action_ == Action::DELEGATE_SYNC);
117 bool cert_matched_sni;
118 quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain =
119 delegate_->GetCertChain(server_address, client_address, hostname,
120 &cert_matched_sni);
121
122 bool ok = chain && !chain->certs.empty();
123 callback_->OnSelectCertificateDone(
124 ok, /*is_sync=*/true,
125 ProofSourceHandleCallback::LocalSSLConfig{chain.get(),
126 delayed_ssl_config_},
127 /*ticket_encryption_key=*/absl::string_view(),
128 /*cert_matched_sni=*/cert_matched_sni);
129 return ok ? QUIC_SUCCESS : QUIC_FAILURE;
130 }
131
ComputeSignature(const QuicSocketAddress & server_address,const QuicSocketAddress & client_address,const std::string & hostname,uint16_t signature_algorithm,absl::string_view in,size_t max_signature_size)132 QuicAsyncStatus FakeProofSourceHandle::ComputeSignature(
133 const QuicSocketAddress& server_address,
134 const QuicSocketAddress& client_address, const std::string& hostname,
135 uint16_t signature_algorithm, absl::string_view in,
136 size_t max_signature_size) {
137 if (compute_signature_action_ != Action::FAIL_SYNC_DO_NOT_CHECK_CLOSED) {
138 QUICHE_CHECK(!closed_);
139 }
140 all_compute_signature_args_.push_back(
141 ComputeSignatureArgs(server_address, client_address, hostname,
142 signature_algorithm, in, max_signature_size));
143
144 if (compute_signature_action_ == Action::DELEGATE_ASYNC ||
145 compute_signature_action_ == Action::FAIL_ASYNC) {
146 compute_signature_op_.emplace(delegate_, callback_,
147 compute_signature_action_,
148 all_compute_signature_args_.back());
149 return QUIC_PENDING;
150 } else if (compute_signature_action_ == Action::FAIL_SYNC ||
151 compute_signature_action_ ==
152 Action::FAIL_SYNC_DO_NOT_CHECK_CLOSED) {
153 callback()->OnComputeSignatureDone(/*ok=*/false, /*is_sync=*/true,
154 /*signature=*/"", /*details=*/nullptr);
155 return QUIC_FAILURE;
156 }
157
158 QUICHE_DCHECK(compute_signature_action_ == Action::DELEGATE_SYNC);
159 ComputeSignatureResult result =
160 ComputeSignatureNow(delegate_, server_address, client_address, hostname,
161 signature_algorithm, in);
162 callback_->OnComputeSignatureDone(
163 result.ok, /*is_sync=*/true, result.signature, std::move(result.details));
164 return result.ok ? QUIC_SUCCESS : QUIC_FAILURE;
165 }
166
callback()167 ProofSourceHandleCallback* FakeProofSourceHandle::callback() {
168 return callback_;
169 }
170
HasPendingOperation() const171 bool FakeProofSourceHandle::HasPendingOperation() const {
172 int num_pending_operations = NumPendingOperations();
173 return num_pending_operations > 0;
174 }
175
CompletePendingOperation()176 void FakeProofSourceHandle::CompletePendingOperation() {
177 QUICHE_DCHECK_LE(NumPendingOperations(), 1);
178
179 if (select_cert_op_.has_value()) {
180 select_cert_op_->Run();
181 select_cert_op_.reset();
182 } else if (compute_signature_op_.has_value()) {
183 compute_signature_op_->Run();
184 compute_signature_op_.reset();
185 }
186 }
187
NumPendingOperations() const188 int FakeProofSourceHandle::NumPendingOperations() const {
189 return static_cast<int>(select_cert_op_.has_value()) +
190 static_cast<int>(compute_signature_op_.has_value());
191 }
192
SelectCertOperation(ProofSource * delegate,ProofSourceHandleCallback * callback,Action action,SelectCertArgs args,QuicDelayedSSLConfig delayed_ssl_config)193 FakeProofSourceHandle::SelectCertOperation::SelectCertOperation(
194 ProofSource* delegate, ProofSourceHandleCallback* callback, Action action,
195 SelectCertArgs args, QuicDelayedSSLConfig delayed_ssl_config)
196 : PendingOperation(delegate, callback, action),
197 args_(std::move(args)),
198 delayed_ssl_config_(delayed_ssl_config) {}
199
Run()200 void FakeProofSourceHandle::SelectCertOperation::Run() {
201 if (action_ == Action::FAIL_ASYNC) {
202 callback_->OnSelectCertificateDone(
203 /*ok=*/false,
204 /*is_sync=*/false,
205 ProofSourceHandleCallback::LocalSSLConfig{nullptr, delayed_ssl_config_},
206 /*ticket_encryption_key=*/absl::string_view(),
207 /*cert_matched_sni=*/false);
208 } else if (action_ == Action::DELEGATE_ASYNC) {
209 bool cert_matched_sni;
210 quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain =
211 delegate_->GetCertChain(args_.server_address, args_.client_address,
212 args_.hostname, &cert_matched_sni);
213 bool ok = chain && !chain->certs.empty();
214 callback_->OnSelectCertificateDone(
215 ok, /*is_sync=*/false,
216 ProofSourceHandleCallback::LocalSSLConfig{chain.get(),
217 delayed_ssl_config_},
218 /*ticket_encryption_key=*/absl::string_view(),
219 /*cert_matched_sni=*/cert_matched_sni);
220 } else {
221 QUIC_BUG(quic_bug_10139_1)
222 << "Unexpected action: " << static_cast<int>(action_);
223 }
224 }
225
ComputeSignatureOperation(ProofSource * delegate,ProofSourceHandleCallback * callback,Action action,ComputeSignatureArgs args)226 FakeProofSourceHandle::ComputeSignatureOperation::ComputeSignatureOperation(
227 ProofSource* delegate, ProofSourceHandleCallback* callback, Action action,
228 ComputeSignatureArgs args)
229 : PendingOperation(delegate, callback, action), args_(std::move(args)) {}
230
Run()231 void FakeProofSourceHandle::ComputeSignatureOperation::Run() {
232 if (action_ == Action::FAIL_ASYNC) {
233 callback_->OnComputeSignatureDone(
234 /*ok=*/false, /*is_sync=*/false,
235 /*signature=*/"", /*details=*/nullptr);
236 } else if (action_ == Action::DELEGATE_ASYNC) {
237 ComputeSignatureResult result = ComputeSignatureNow(
238 delegate_, args_.server_address, args_.client_address, args_.hostname,
239 args_.signature_algorithm, args_.in);
240 callback_->OnComputeSignatureDone(result.ok, /*is_sync=*/false,
241 result.signature,
242 std::move(result.details));
243 } else {
244 QUIC_BUG(quic_bug_10139_2)
245 << "Unexpected action: " << static_cast<int>(action_);
246 }
247 }
248
249 } // namespace test
250 } // namespace quic
251