blob: af780b27cd364d9f26e561320779947972629411 [file] [log] [blame]
[email protected]ed3fc15d2013-03-08 18:37:441// Copyright (c) 2012 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 "net/quic/test_tools/crypto_test_utils.h"
[email protected]72818ea2013-03-13 03:23:576
[email protected]38b3fd12013-06-18 08:19:017#include "net/quic/crypto/channel_id.h"
[email protected]c244c5a12013-05-07 20:55:048#include "net/quic/crypto/common_cert_set.h"
[email protected]ef95114d2013-04-17 17:57:019#include "net/quic/crypto/crypto_handshake.h"
[email protected]8e01c062013-10-31 07:35:3110#include "net/quic/crypto/quic_crypto_server_config.h"
[email protected]14e8106c2013-03-14 16:25:3311#include "net/quic/crypto/quic_decrypter.h"
12#include "net/quic/crypto/quic_encrypter.h"
[email protected]ef95114d2013-04-17 17:57:0113#include "net/quic/crypto/quic_random.h"
14#include "net/quic/quic_clock.h"
[email protected]ed3fc15d2013-03-08 18:37:4415#include "net/quic/quic_crypto_client_stream.h"
16#include "net/quic/quic_crypto_server_stream.h"
17#include "net/quic/quic_crypto_stream.h"
[email protected]257f24f2014-04-01 09:15:3718#include "net/quic/quic_server_id.h"
rch28f6469d2016-03-13 21:13:0819#include "net/quic/quic_utils.h"
[email protected]2532de12013-05-09 12:29:3320#include "net/quic/test_tools/quic_connection_peer.h"
rch1e543ec2015-03-29 07:04:4021#include "net/quic/test_tools/quic_framer_peer.h"
[email protected]ed3fc15d2013-03-08 18:37:4422#include "net/quic/test_tools/quic_test_utils.h"
23#include "net/quic/test_tools/simple_quic_framer.h"
[email protected]ed3fc15d2013-03-08 18:37:4424
[email protected]14e8106c2013-03-14 16:25:3325using base::StringPiece;
[email protected]691f45a982013-11-19 10:52:0426using std::make_pair;
27using std::pair;
[email protected]ccc66e8a2013-03-26 08:26:1428using std::string;
[email protected]fe053f92013-04-23 20:18:5529using std::vector;
[email protected]14e8106c2013-03-14 16:25:3330
[email protected]ed3fc15d2013-03-08 18:37:4431namespace net {
32namespace test {
33
34namespace {
35
[email protected]fe053f92013-04-23 20:18:5536// CryptoFramerVisitor is a framer visitor that records handshake messages.
37class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
38 public:
rjshaded5ced072015-12-18 19:26:0239 CryptoFramerVisitor() : error_(false) {}
[email protected]ed3fc15d2013-03-08 18:37:4440
dchengb03027d2014-10-21 12:00:2041 void OnError(CryptoFramer* framer) override { error_ = true; }
[email protected]ed3fc15d2013-03-08 18:37:4442
dchengb03027d2014-10-21 12:00:2043 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
[email protected]fe053f92013-04-23 20:18:5544 messages_.push_back(message);
45 }
[email protected]ed3fc15d2013-03-08 18:37:4446
rjshaded5ced072015-12-18 19:26:0247 bool error() const { return error_; }
[email protected]ed3fc15d2013-03-08 18:37:4448
rjshaded5ced072015-12-18 19:26:0249 const vector<CryptoHandshakeMessage>& messages() const { return messages_; }
[email protected]ed3fc15d2013-03-08 18:37:4450
[email protected]fe053f92013-04-23 20:18:5551 private:
52 bool error_;
53 vector<CryptoHandshakeMessage> messages_;
54};
55
[email protected]0bbeb6972013-05-23 04:10:2156// HexChar parses |c| as a hex character. If valid, it sets |*value| to the
57// value of the hex character and returns true. Otherwise it returns false.
Avi Drissman13fc8932015-12-20 04:40:4658bool HexChar(char c, uint8_t* value) {
[email protected]0bbeb6972013-05-23 04:10:2159 if (c >= '0' && c <= '9') {
60 *value = c - '0';
61 return true;
62 }
63 if (c >= 'a' && c <= 'f') {
[email protected]b064310782013-05-30 21:12:1764 *value = c - 'a' + 10;
[email protected]0bbeb6972013-05-23 04:10:2165 return true;
66 }
67 if (c >= 'A' && c <= 'F') {
[email protected]b064310782013-05-30 21:12:1768 *value = c - 'A' + 10;
[email protected]0bbeb6972013-05-23 04:10:2169 return true;
70 }
71 return false;
72}
73
[email protected]6fc79ea2014-07-10 04:30:2374// A ChannelIDSource that works in asynchronous mode unless the |callback|
rtennetibe635732014-10-02 22:51:4275// argument to GetChannelIDKey is nullptr.
[email protected]6fc79ea2014-07-10 04:30:2376class AsyncTestChannelIDSource : public ChannelIDSource,
[email protected]dc6094a2014-07-23 01:50:0477 public CryptoTestUtils::CallbackSource {
[email protected]6fc79ea2014-07-10 04:30:2378 public:
79 // Takes ownership of |sync_source|, a synchronous ChannelIDSource.
80 explicit AsyncTestChannelIDSource(ChannelIDSource* sync_source)
81 : sync_source_(sync_source) {}
dchengb03027d2014-10-21 12:00:2082 ~AsyncTestChannelIDSource() override {}
[email protected]6fc79ea2014-07-10 04:30:2383
84 // ChannelIDSource implementation.
dchengb03027d2014-10-21 12:00:2085 QuicAsyncStatus GetChannelIDKey(const string& hostname,
86 scoped_ptr<ChannelIDKey>* channel_id_key,
87 ChannelIDSourceCallback* callback) override {
[email protected]6fc79ea2014-07-10 04:30:2388 // Synchronous mode.
89 if (!callback) {
rtennetibe635732014-10-02 22:51:4290 return sync_source_->GetChannelIDKey(hostname, channel_id_key, nullptr);
[email protected]6fc79ea2014-07-10 04:30:2391 }
92
93 // Asynchronous mode.
94 QuicAsyncStatus status =
rtennetibe635732014-10-02 22:51:4295 sync_source_->GetChannelIDKey(hostname, &channel_id_key_, nullptr);
[email protected]6fc79ea2014-07-10 04:30:2396 if (status != QUIC_SUCCESS) {
97 return QUIC_FAILURE;
98 }
99 callback_.reset(callback);
100 return QUIC_PENDING;
101 }
102
[email protected]dc6094a2014-07-23 01:50:04103 // CallbackSource implementation.
dchengb03027d2014-10-21 12:00:20104 void RunPendingCallbacks() override {
[email protected]6fc79ea2014-07-10 04:30:23105 if (callback_.get()) {
106 callback_->Run(&channel_id_key_);
107 callback_.reset();
108 }
109 }
110
111 private:
112 scoped_ptr<ChannelIDSource> sync_source_;
113 scoped_ptr<ChannelIDSourceCallback> callback_;
114 scoped_ptr<ChannelIDKey> channel_id_key_;
115};
116
[email protected]ed3fc15d2013-03-08 18:37:44117} // anonymous namespace
118
rjshadec86dbfa2015-11-12 20:16:25119CryptoTestUtils::FakeServerOptions::FakeServerOptions()
120 : token_binding_enabled(false) {}
121
[email protected]899951652013-05-16 12:52:39122CryptoTestUtils::FakeClientOptions::FakeClientOptions()
rjshadec86dbfa2015-11-12 20:16:25123 : channel_id_enabled(false),
124 channel_id_source_async(false),
125 token_binding_enabled(false) {}
[email protected]899951652013-05-16 12:52:39126
[email protected]ed3fc15d2013-03-08 18:37:44127// static
[email protected]fe053f92013-04-23 20:18:55128int CryptoTestUtils::HandshakeWithFakeServer(
rch99b644c2015-11-04 05:25:28129 MockConnectionHelper* helper,
[email protected]ed3fc15d2013-03-08 18:37:44130 PacketSavingConnection* client_conn,
rjshadec86dbfa2015-11-12 20:16:25131 QuicCryptoClientStream* client,
132 const FakeServerOptions& options) {
rtenneti6f48aa92015-03-16 02:18:48133 PacketSavingConnection* server_conn = new PacketSavingConnection(
rtenneti8a4a0732015-10-18 00:45:51134 helper, Perspective::IS_SERVER, client_conn->supported_versions());
rtennetid39bd762015-06-12 01:05:52135
136 QuicConfig config = DefaultQuicConfig();
[email protected]b064310782013-05-30 21:12:17137 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
rch1fe2eeb2015-10-26 14:45:57138 QuicRandom::GetInstance(),
139 ProofSourceForTesting());
rjshaded069aaee2016-03-11 20:42:17140 QuicCompressedCertsCache compressed_certs_cache(
141 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
rtennetid39bd762015-06-12 01:05:52142 SetupCryptoServerConfigForTest(server_conn->clock(),
143 server_conn->random_generator(), &config,
rjshadec86dbfa2015-11-12 20:16:25144 &crypto_config, options);
[email protected]ccb34212014-07-18 09:27:50145
rjshaded069aaee2016-03-11 20:42:17146 TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config,
147 &compressed_certs_cache);
[email protected]ed3fc15d2013-03-08 18:37:44148
149 // The client's handshake must have been started already.
rtennetib6ac61a52015-02-11 20:20:52150 CHECK_NE(0u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44151
rtennetid39bd762015-06-12 01:05:52152 CommunicateHandshakeMessages(client_conn, client, server_conn,
153 server_session.GetCryptoStream());
rtennetid39bd762015-06-12 01:05:52154 CompareClientAndServerKeys(client, server_session.GetCryptoStream());
[email protected]fe053f92013-04-23 20:18:55155
156 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44157}
158
159// static
[email protected]fe053f92013-04-23 20:18:55160int CryptoTestUtils::HandshakeWithFakeClient(
rch99b644c2015-11-04 05:25:28161 MockConnectionHelper* helper,
[email protected]ed3fc15d2013-03-08 18:37:44162 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39163 QuicCryptoServerStream* server,
zhongyic92bc492015-09-22 19:14:36164 const QuicServerId& server_id,
[email protected]899951652013-05-16 12:52:39165 const FakeClientOptions& options) {
rtenneti6f48aa92015-03-16 02:18:48166 PacketSavingConnection* client_conn =
rtenneti8a4a0732015-10-18 00:45:51167 new PacketSavingConnection(helper, Perspective::IS_CLIENT);
rtenneti85d89712014-11-20 03:32:24168 // Advance the time, because timers do not like uninitialized times.
169 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
[email protected]ef95114d2013-04-17 17:57:01170
rch1fe2eeb2015-10-26 14:45:57171 QuicCryptoClientConfig crypto_config(ProofVerifierForTesting());
rtennetibe635732014-10-02 22:51:42172 AsyncTestChannelIDSource* async_channel_id_source = nullptr;
[email protected]b064310782013-05-30 21:12:17173 if (options.channel_id_enabled) {
[email protected]6fc79ea2014-07-10 04:30:23174 ChannelIDSource* source = ChannelIDSourceForTesting();
175 if (options.channel_id_source_async) {
176 async_channel_id_source = new AsyncTestChannelIDSource(source);
177 source = async_channel_id_source;
178 }
179 crypto_config.SetChannelIDSource(source);
[email protected]b064310782013-05-30 21:12:17180 }
rjshadec86dbfa2015-11-12 20:16:25181 if (options.token_binding_enabled) {
182 crypto_config.tb_key_params.push_back(kP256);
183 }
rtennetib865eb82015-06-17 20:21:46184 TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(),
185 server_id, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44186
rch28f6469d2016-03-13 21:13:08187 EXPECT_CALL(client_session, OnProofValid(testing::_))
188 .Times(testing::AnyNumber());
rtennetid39bd762015-06-12 01:05:52189 client_session.GetCryptoStream()->CryptoConnect();
rtennetib6ac61a52015-02-11 20:20:52190 CHECK_EQ(1u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44191
[email protected]dc6094a2014-07-23 01:50:04192 CommunicateHandshakeMessagesAndRunCallbacks(
rtennetid39bd762015-06-12 01:05:52193 client_conn, client_session.GetCryptoStream(), server_conn, server,
194 async_channel_id_source);
[email protected]14e8106c2013-03-14 16:25:33195
rtennetid39bd762015-06-12 01:05:52196 CompareClientAndServerKeys(client_session.GetCryptoStream(), server);
[email protected]fe053f92013-04-23 20:18:55197
[email protected]38b3fd12013-06-18 08:19:01198 if (options.channel_id_enabled) {
[email protected]03dd32532014-05-30 07:11:25199 scoped_ptr<ChannelIDKey> channel_id_key;
rtennetibe635732014-10-02 22:51:42200 QuicAsyncStatus status = crypto_config.channel_id_source()->GetChannelIDKey(
zhongyic92bc492015-09-22 19:14:36201 server_id.host(), &channel_id_key, nullptr);
[email protected]05bfc260f2014-06-07 06:31:25202 EXPECT_EQ(QUIC_SUCCESS, status);
[email protected]03dd32532014-05-30 07:11:25203 EXPECT_EQ(channel_id_key->SerializeKey(),
204 server->crypto_negotiated_params().channel_id);
rtennetid39bd762015-06-12 01:05:52205 EXPECT_EQ(
206 options.channel_id_source_async,
207 client_session.GetCryptoStream()->WasChannelIDSourceCallbackRun());
[email protected]38b3fd12013-06-18 08:19:01208 }
209
rtennetid39bd762015-06-12 01:05:52210 return client_session.GetCryptoStream()->num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33211}
212
213// static
[email protected]ef95114d2013-04-17 17:57:01214void CryptoTestUtils::SetupCryptoServerConfigForTest(
215 const QuicClock* clock,
216 QuicRandom* rand,
217 QuicConfig* config,
rjshadec86dbfa2015-11-12 20:16:25218 QuicCryptoServerConfig* crypto_config,
219 const FakeServerOptions& fake_options) {
[email protected]b064310782013-05-30 21:12:17220 QuicCryptoServerConfig::ConfigOptions options;
221 options.channel_id_enabled = true;
rjshadec86dbfa2015-11-12 20:16:25222 options.token_binding_enabled = fake_options.token_binding_enabled;
[email protected]ef95114d2013-04-17 17:57:01223 scoped_ptr<CryptoHandshakeMessage> scfg(
[email protected]b064310782013-05-30 21:12:17224 crypto_config->AddDefaultConfig(rand, clock, options));
[email protected]ef95114d2013-04-17 17:57:01225}
226
227// static
[email protected]0bbeb6972013-05-23 04:10:21228void CryptoTestUtils::CommunicateHandshakeMessages(
229 PacketSavingConnection* a_conn,
230 QuicCryptoStream* a,
231 PacketSavingConnection* b_conn,
232 QuicCryptoStream* b) {
rtennetibe635732014-10-02 22:51:42233 CommunicateHandshakeMessagesAndRunCallbacks(a_conn, a, b_conn, b, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23234}
235
236// static
[email protected]dc6094a2014-07-23 01:50:04237void CryptoTestUtils::CommunicateHandshakeMessagesAndRunCallbacks(
[email protected]6fc79ea2014-07-10 04:30:23238 PacketSavingConnection* a_conn,
239 QuicCryptoStream* a,
240 PacketSavingConnection* b_conn,
241 QuicCryptoStream* b,
[email protected]dc6094a2014-07-23 01:50:04242 CallbackSource* callback_source) {
[email protected]0bbeb6972013-05-23 04:10:21243 size_t a_i = 0, b_i = 0;
244 while (!a->handshake_confirmed()) {
rtennetib6ac61a52015-02-11 20:20:52245 ASSERT_GT(a_conn->encrypted_packets_.size(), a_i);
246 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
247 << " packets a->b";
[email protected]0bbeb6972013-05-23 04:10:21248 MovePackets(a_conn, &a_i, b, b_conn);
[email protected]dc6094a2014-07-23 01:50:04249 if (callback_source) {
250 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23251 }
[email protected]0bbeb6972013-05-23 04:10:21252
rtennetib6ac61a52015-02-11 20:20:52253 ASSERT_GT(b_conn->encrypted_packets_.size(), b_i);
254 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
255 << " packets b->a";
[email protected]0bbeb6972013-05-23 04:10:21256 MovePackets(b_conn, &b_i, a, a_conn);
[email protected]dc6094a2014-07-23 01:50:04257 if (callback_source) {
258 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23259 }
[email protected]0bbeb6972013-05-23 04:10:21260 }
261}
262
[email protected]b694e48c2014-03-18 17:10:13263// static
[email protected]691f45a982013-11-19 10:52:04264pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
265 PacketSavingConnection* a_conn,
266 QuicCryptoStream* a,
267 size_t a_i,
268 PacketSavingConnection* b_conn,
269 QuicCryptoStream* b,
270 size_t b_i) {
rtennetib6ac61a52015-02-11 20:20:52271 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
272 << " packets a->b";
[email protected]691f45a982013-11-19 10:52:04273 MovePackets(a_conn, &a_i, b, b_conn);
274
rtennetib6ac61a52015-02-11 20:20:52275 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
276 << " packets b->a";
277 if (b_conn->encrypted_packets_.size() - b_i == 2) {
278 VLOG(1) << "here";
[email protected]691f45a982013-11-19 10:52:04279 }
280 MovePackets(b_conn, &b_i, a, a_conn);
281
rtenneti16a20772015-02-17 18:58:48282 return std::make_pair(a_i, b_i);
[email protected]691f45a982013-11-19 10:52:04283}
284
[email protected]0bbeb6972013-05-23 04:10:21285// static
[email protected]ccc66e8a2013-03-26 08:26:14286string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33287 QuicTag tag) {
288 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14289 if (it == message.tag_value_map().end()) {
290 return string();
291 }
292 return it->second;
293}
294
[email protected]2532de12013-05-09 12:29:33295class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04296 public:
Avi Drissman13fc8932015-12-20 04:40:46297 MockCommonCertSets(StringPiece cert, uint64_t hash, uint32_t index)
rjshaded5ced072015-12-18 19:26:02298 : cert_(cert.as_string()), hash_(hash), index_(index) {}
[email protected]c244c5a12013-05-07 20:55:04299
dchengb03027d2014-10-21 12:00:20300 StringPiece GetCommonHashes() const override {
[email protected]c244c5a12013-05-07 20:55:04301 CHECK(false) << "not implemented";
302 return StringPiece();
303 }
304
Avi Drissman13fc8932015-12-20 04:40:46305 StringPiece GetCert(uint64_t hash, uint32_t index) const override {
[email protected]c244c5a12013-05-07 20:55:04306 if (hash == hash_ && index == index_) {
307 return cert_;
308 }
309 return StringPiece();
310 }
311
dchengb03027d2014-10-21 12:00:20312 bool MatchCert(StringPiece cert,
313 StringPiece common_set_hashes,
Avi Drissman13fc8932015-12-20 04:40:46314 uint64_t* out_hash,
315 uint32_t* out_index) const override {
[email protected]c244c5a12013-05-07 20:55:04316 if (cert != cert_) {
317 return false;
318 }
319
Avi Drissman13fc8932015-12-20 04:40:46320 if (common_set_hashes.size() % sizeof(uint64_t) != 0) {
[email protected]c244c5a12013-05-07 20:55:04321 return false;
322 }
323 bool client_has_set = false;
Avi Drissman13fc8932015-12-20 04:40:46324 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64_t)) {
325 uint64_t hash;
[email protected]c244c5a12013-05-07 20:55:04326 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
327 if (hash == hash_) {
328 client_has_set = true;
329 break;
330 }
331 }
332
333 if (!client_has_set) {
334 return false;
335 }
336
337 *out_hash = hash_;
338 *out_index = index_;
339 return true;
340 }
341
342 private:
343 const string cert_;
Avi Drissman13fc8932015-12-20 04:40:46344 const uint64_t hash_;
345 const uint32_t index_;
[email protected]c244c5a12013-05-07 20:55:04346};
347
[email protected]2532de12013-05-09 12:29:33348CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
Avi Drissman13fc8932015-12-20 04:40:46349 uint64_t hash,
350 uint32_t index) {
[email protected]2532de12013-05-09 12:29:33351 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04352}
353
rch94e52bc2015-12-06 04:28:26354// static
355void CryptoTestUtils::FillInDummyReject(CryptoHandshakeMessage* rej,
356 bool reject_is_stateless) {
357 if (reject_is_stateless) {
358 rej->set_tag(kSREJ);
359 } else {
360 rej->set_tag(kREJ);
361 }
362
363 // Minimum SCFG that passes config validation checks.
364 // clang-format off
365 unsigned char scfg[] = {
366 // SCFG
367 0x53, 0x43, 0x46, 0x47,
368 // num entries
369 0x01, 0x00,
370 // padding
371 0x00, 0x00,
372 // EXPY
373 0x45, 0x58, 0x50, 0x59,
374 // EXPY end offset
375 0x08, 0x00, 0x00, 0x00,
376 // Value
377 '1', '2', '3', '4',
378 '5', '6', '7', '8'
379 };
380 // clang-format on
381 rej->SetValue(kSCFG, scfg);
382 rej->SetStringPiece(kServerNonceTag, "SERVER_NONCE");
383 vector<QuicTag> reject_reasons;
384 reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
385 rej->SetVector(kRREJ, reject_reasons);
386}
387
[email protected]14e8106c2013-03-14 16:25:33388void CryptoTestUtils::CompareClientAndServerKeys(
389 QuicCryptoClientStream* client,
390 QuicCryptoServerStream* server) {
rch1e543ec2015-03-29 07:04:40391 QuicFramer* client_framer =
392 QuicConnectionPeer::GetFramer(client->session()->connection());
393 QuicFramer* server_framer =
394 QuicConnectionPeer::GetFramer(server->session()->connection());
[email protected]8ba81212013-05-03 13:11:48395 const QuicEncrypter* client_encrypter(
rch1e543ec2015-03-29 07:04:40396 QuicFramerPeer::GetEncrypter(client_framer, ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48397 const QuicDecrypter* client_decrypter(
[email protected]2532de12013-05-09 12:29:33398 client->session()->connection()->decrypter());
399 const QuicEncrypter* client_forward_secure_encrypter(
rch1e543ec2015-03-29 07:04:40400 QuicFramerPeer::GetEncrypter(client_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33401 const QuicDecrypter* client_forward_secure_decrypter(
[email protected]8ba81212013-05-03 13:11:48402 client->session()->connection()->alternative_decrypter());
403 const QuicEncrypter* server_encrypter(
rch1e543ec2015-03-29 07:04:40404 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48405 const QuicDecrypter* server_decrypter(
406 server->session()->connection()->decrypter());
[email protected]2532de12013-05-09 12:29:33407 const QuicEncrypter* server_forward_secure_encrypter(
rch1e543ec2015-03-29 07:04:40408 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33409 const QuicDecrypter* server_forward_secure_decrypter(
410 server->session()->connection()->alternative_decrypter());
[email protected]8ba81212013-05-03 13:11:48411
412 StringPiece client_encrypter_key = client_encrypter->GetKey();
413 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
414 StringPiece client_decrypter_key = client_decrypter->GetKey();
415 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33416 StringPiece client_forward_secure_encrypter_key =
417 client_forward_secure_encrypter->GetKey();
418 StringPiece client_forward_secure_encrypter_iv =
419 client_forward_secure_encrypter->GetNoncePrefix();
420 StringPiece client_forward_secure_decrypter_key =
421 client_forward_secure_decrypter->GetKey();
422 StringPiece client_forward_secure_decrypter_iv =
423 client_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48424 StringPiece server_encrypter_key = server_encrypter->GetKey();
425 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
426 StringPiece server_decrypter_key = server_decrypter->GetKey();
427 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33428 StringPiece server_forward_secure_encrypter_key =
429 server_forward_secure_encrypter->GetKey();
430 StringPiece server_forward_secure_encrypter_iv =
431 server_forward_secure_encrypter->GetNoncePrefix();
432 StringPiece server_forward_secure_decrypter_key =
433 server_forward_secure_decrypter->GetKey();
434 StringPiece server_forward_secure_decrypter_iv =
435 server_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48436
[email protected]2fe8b632014-07-31 11:36:37437 StringPiece client_subkey_secret =
438 client->crypto_negotiated_params().subkey_secret;
439 StringPiece server_subkey_secret =
440 server->crypto_negotiated_params().subkey_secret;
441
[email protected]2fe8b632014-07-31 11:36:37442 const char kSampleLabel[] = "label";
443 const char kSampleContext[] = "context";
444 const size_t kSampleOutputLength = 32;
445 string client_key_extraction;
446 string server_key_extraction;
fayanga64c1a92016-02-13 01:55:58447 string client_tb_ekm;
448 string server_tb_ekm;
rjshaded5ced072015-12-18 19:26:02449 EXPECT_TRUE(client->ExportKeyingMaterial(kSampleLabel, kSampleContext,
[email protected]2fe8b632014-07-31 11:36:37450 kSampleOutputLength,
451 &client_key_extraction));
rjshaded5ced072015-12-18 19:26:02452 EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel, kSampleContext,
[email protected]2fe8b632014-07-31 11:36:37453 kSampleOutputLength,
454 &server_key_extraction));
fayanga64c1a92016-02-13 01:55:58455 if (FLAGS_quic_save_initial_subkey_secret) {
456 EXPECT_TRUE(client->ExportTokenBindingKeyingMaterial(&client_tb_ekm));
457 EXPECT_TRUE(server->ExportTokenBindingKeyingMaterial(&server_tb_ekm));
458 }
[email protected]2fe8b632014-07-31 11:36:37459
rjshaded5ced072015-12-18 19:26:02460 CompareCharArraysWithHexError("client write key", client_encrypter_key.data(),
[email protected]14e8106c2013-03-14 16:25:33461 client_encrypter_key.length(),
462 server_decrypter_key.data(),
463 server_decrypter_key.length());
rjshaded5ced072015-12-18 19:26:02464 CompareCharArraysWithHexError("client write IV", client_encrypter_iv.data(),
[email protected]14e8106c2013-03-14 16:25:33465 client_encrypter_iv.length(),
466 server_decrypter_iv.data(),
467 server_decrypter_iv.length());
rjshaded5ced072015-12-18 19:26:02468 CompareCharArraysWithHexError("server write key", server_encrypter_key.data(),
[email protected]14e8106c2013-03-14 16:25:33469 server_encrypter_key.length(),
470 client_decrypter_key.data(),
471 client_decrypter_key.length());
rjshaded5ced072015-12-18 19:26:02472 CompareCharArraysWithHexError("server write IV", server_encrypter_iv.data(),
[email protected]14e8106c2013-03-14 16:25:33473 server_encrypter_iv.length(),
474 client_decrypter_iv.data(),
475 client_decrypter_iv.length());
[email protected]2532de12013-05-09 12:29:33476 CompareCharArraysWithHexError("client forward secure write key",
477 client_forward_secure_encrypter_key.data(),
478 client_forward_secure_encrypter_key.length(),
479 server_forward_secure_decrypter_key.data(),
480 server_forward_secure_decrypter_key.length());
481 CompareCharArraysWithHexError("client forward secure write IV",
482 client_forward_secure_encrypter_iv.data(),
483 client_forward_secure_encrypter_iv.length(),
484 server_forward_secure_decrypter_iv.data(),
485 server_forward_secure_decrypter_iv.length());
486 CompareCharArraysWithHexError("server forward secure write key",
487 server_forward_secure_encrypter_key.data(),
488 server_forward_secure_encrypter_key.length(),
489 client_forward_secure_decrypter_key.data(),
490 client_forward_secure_decrypter_key.length());
491 CompareCharArraysWithHexError("server forward secure write IV",
492 server_forward_secure_encrypter_iv.data(),
493 server_forward_secure_encrypter_iv.length(),
494 client_forward_secure_decrypter_iv.data(),
495 client_forward_secure_decrypter_iv.length());
rjshaded5ced072015-12-18 19:26:02496 CompareCharArraysWithHexError("subkey secret", client_subkey_secret.data(),
[email protected]2fe8b632014-07-31 11:36:37497 client_subkey_secret.length(),
498 server_subkey_secret.data(),
499 server_subkey_secret.length());
rjshaded5ced072015-12-18 19:26:02500 CompareCharArraysWithHexError(
501 "sample key extraction", client_key_extraction.data(),
502 client_key_extraction.length(), server_key_extraction.data(),
503 server_key_extraction.length());
fayanga64c1a92016-02-13 01:55:58504
505 if (FLAGS_quic_save_initial_subkey_secret) {
506 CompareCharArraysWithHexError("token binding key extraction",
507 client_tb_ekm.data(), client_tb_ekm.length(),
508 server_tb_ekm.data(), server_tb_ekm.length());
509 }
[email protected]ed3fc15d2013-03-08 18:37:44510}
[email protected]0bbeb6972013-05-23 04:10:21511
512// static
513QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
514 const size_t len = strlen(tagstr);
515 CHECK_NE(0u, len);
516
517 QuicTag tag = 0;
518
519 if (tagstr[0] == '#') {
rjshaded5ced072015-12-18 19:26:02520 CHECK_EQ(static_cast<size_t>(1 + 2 * 4), len);
[email protected]0bbeb6972013-05-23 04:10:21521 tagstr++;
522
523 for (size_t i = 0; i < 8; i++) {
524 tag <<= 4;
525
Avi Drissman13fc8932015-12-20 04:40:46526 uint8_t v = 0;
[email protected]0bbeb6972013-05-23 04:10:21527 CHECK(HexChar(tagstr[i], &v));
528 tag |= v;
529 }
530
531 return tag;
532 }
533
534 CHECK_LE(len, 4u);
535 for (size_t i = 0; i < 4; i++) {
536 tag >>= 8;
537 if (i < len) {
Avi Drissman13fc8932015-12-20 04:40:46538 tag |= static_cast<uint32_t>(tagstr[i]) << 24;
[email protected]0bbeb6972013-05-23 04:10:21539 }
540 }
541
542 return tag;
543}
544
545// static
546CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
547 va_list ap;
548 va_start(ap, message_tag);
549
[email protected]0bbeb6972013-05-23 04:10:21550 CryptoHandshakeMessage msg;
551 msg.set_tag(ParseTag(message_tag));
552
553 for (;;) {
554 const char* tagstr = va_arg(ap, const char*);
rtennetibe635732014-10-02 22:51:42555 if (tagstr == nullptr) {
[email protected]0bbeb6972013-05-23 04:10:21556 break;
557 }
558
[email protected]4e49b6a2013-06-18 16:39:28559 if (tagstr[0] == '$') {
560 // Special value.
561 const char* const special = tagstr + 1;
562 if (strcmp(special, "padding") == 0) {
563 const int min_bytes = va_arg(ap, int);
564 msg.set_minimum_size(min_bytes);
565 } else {
566 CHECK(false) << "Unknown special value: " << special;
567 }
568
569 continue;
570 }
571
[email protected]0bbeb6972013-05-23 04:10:21572 const QuicTag tag = ParseTag(tagstr);
573 const char* valuestr = va_arg(ap, const char*);
574
575 size_t len = strlen(valuestr);
576 if (len > 0 && valuestr[0] == '#') {
577 valuestr++;
578 len--;
579
[email protected]257f24f2014-04-01 09:15:37580 CHECK_EQ(0u, len % 2);
Avi Drissman13fc8932015-12-20 04:40:46581 scoped_ptr<uint8_t[]> buf(new uint8_t[len / 2]);
[email protected]0bbeb6972013-05-23 04:10:21582
rjshaded5ced072015-12-18 19:26:02583 for (size_t i = 0; i < len / 2; i++) {
Avi Drissman13fc8932015-12-20 04:40:46584 uint8_t v = 0;
rjshaded5ced072015-12-18 19:26:02585 CHECK(HexChar(valuestr[i * 2], &v));
[email protected]0bbeb6972013-05-23 04:10:21586 buf[i] = v << 4;
rjshaded5ced072015-12-18 19:26:02587 CHECK(HexChar(valuestr[i * 2 + 1], &v));
[email protected]0bbeb6972013-05-23 04:10:21588 buf[i] |= v;
589 }
590
591 msg.SetStringPiece(
rjshaded5ced072015-12-18 19:26:02592 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len / 2));
[email protected]0bbeb6972013-05-23 04:10:21593 continue;
594 }
595
596 msg.SetStringPiece(tag, valuestr);
597 }
598
[email protected]4e49b6a2013-06-18 16:39:28599 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
600 // that any padding is included.
601 scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
602 scoped_ptr<CryptoHandshakeMessage> parsed(
603 CryptoFramer::ParseMessage(bytes->AsStringPiece()));
604 CHECK(parsed.get());
605
rtenneti48f371c682015-08-27 05:34:26606 va_end(ap);
[email protected]4e49b6a2013-06-18 16:39:28607 return *parsed;
[email protected]0bbeb6972013-05-23 04:10:21608}
609
rjshadec86dbfa2015-11-12 20:16:25610// static
611void CryptoTestUtils::MovePackets(PacketSavingConnection* source_conn,
612 size_t* inout_packet_index,
613 QuicCryptoStream* dest_stream,
614 PacketSavingConnection* dest_conn) {
615 SimpleQuicFramer framer(source_conn->supported_versions());
616 CryptoFramer crypto_framer;
617 CryptoFramerVisitor crypto_visitor;
618
619 // In order to properly test the code we need to perform encryption and
620 // decryption so that the crypters latch when expected. The crypters are in
621 // |dest_conn|, but we don't want to try and use them there. Instead we swap
622 // them into |framer|, perform the decryption with them, and then swap ther
623 // back.
624 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
625
626 crypto_framer.set_visitor(&crypto_visitor);
627
628 size_t index = *inout_packet_index;
629 for (; index < source_conn->encrypted_packets_.size(); index++) {
630 if (!framer.ProcessPacket(*source_conn->encrypted_packets_[index])) {
631 // The framer will be unable to decrypt forward-secure packets sent after
632 // the handshake is complete. Don't treat them as handshake packets.
633 break;
634 }
635
zhongyi36727b82015-12-03 00:42:23636 for (const QuicStreamFrame* stream_frame : framer.stream_frames()) {
jokulik2324d282015-12-08 21:42:57637 ASSERT_TRUE(crypto_framer.ProcessInput(
638 StringPiece(stream_frame->frame_buffer, stream_frame->frame_length)));
rjshadec86dbfa2015-11-12 20:16:25639 ASSERT_FALSE(crypto_visitor.error());
640 }
641 }
642 *inout_packet_index = index;
643
644 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
645
646 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
647
648 for (const CryptoHandshakeMessage& message : crypto_visitor.messages()) {
649 dest_stream->OnHandshakeMessage(message);
650 }
651}
652
[email protected]ed3fc15d2013-03-08 18:37:44653} // namespace test
654} // namespace net