blob: ed34502a61f7257ca13cbb7f290eeff405312583 [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"
[email protected]2532de12013-05-09 12:29:3319#include "net/quic/test_tools/quic_connection_peer.h"
rch1e543ec2015-03-29 07:04:4020#include "net/quic/test_tools/quic_framer_peer.h"
[email protected]ed3fc15d2013-03-08 18:37:4421#include "net/quic/test_tools/quic_test_utils.h"
22#include "net/quic/test_tools/simple_quic_framer.h"
[email protected]ed3fc15d2013-03-08 18:37:4423
[email protected]14e8106c2013-03-14 16:25:3324using base::StringPiece;
[email protected]691f45a982013-11-19 10:52:0425using std::make_pair;
26using std::pair;
[email protected]ccc66e8a2013-03-26 08:26:1427using std::string;
[email protected]fe053f92013-04-23 20:18:5528using std::vector;
[email protected]14e8106c2013-03-14 16:25:3329
[email protected]ed3fc15d2013-03-08 18:37:4430namespace net {
31namespace test {
32
33namespace {
34
[email protected]fe053f92013-04-23 20:18:5535// CryptoFramerVisitor is a framer visitor that records handshake messages.
36class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
37 public:
38 CryptoFramerVisitor()
39 : error_(false) {
40 }
[email protected]ed3fc15d2013-03-08 18:37:4441
dchengb03027d2014-10-21 12:00:2042 void OnError(CryptoFramer* framer) override { error_ = true; }
[email protected]ed3fc15d2013-03-08 18:37:4443
dchengb03027d2014-10-21 12:00:2044 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
[email protected]fe053f92013-04-23 20:18:5545 messages_.push_back(message);
46 }
[email protected]ed3fc15d2013-03-08 18:37:4447
[email protected]fe053f92013-04-23 20:18:5548 bool error() const {
49 return error_;
50 }
[email protected]ed3fc15d2013-03-08 18:37:4451
[email protected]fe053f92013-04-23 20:18:5552 const vector<CryptoHandshakeMessage>& messages() const {
53 return messages_;
54 }
[email protected]ed3fc15d2013-03-08 18:37:4455
[email protected]fe053f92013-04-23 20:18:5556 private:
57 bool error_;
58 vector<CryptoHandshakeMessage> messages_;
59};
60
[email protected]0bbeb6972013-05-23 04:10:2161// HexChar parses |c| as a hex character. If valid, it sets |*value| to the
62// value of the hex character and returns true. Otherwise it returns false.
63bool HexChar(char c, uint8* value) {
64 if (c >= '0' && c <= '9') {
65 *value = c - '0';
66 return true;
67 }
68 if (c >= 'a' && c <= 'f') {
[email protected]b064310782013-05-30 21:12:1769 *value = c - 'a' + 10;
[email protected]0bbeb6972013-05-23 04:10:2170 return true;
71 }
72 if (c >= 'A' && c <= 'F') {
[email protected]b064310782013-05-30 21:12:1773 *value = c - 'A' + 10;
[email protected]0bbeb6972013-05-23 04:10:2174 return true;
75 }
76 return false;
77}
78
[email protected]6fc79ea2014-07-10 04:30:2379// A ChannelIDSource that works in asynchronous mode unless the |callback|
rtennetibe635732014-10-02 22:51:4280// argument to GetChannelIDKey is nullptr.
[email protected]6fc79ea2014-07-10 04:30:2381class AsyncTestChannelIDSource : public ChannelIDSource,
[email protected]dc6094a2014-07-23 01:50:0482 public CryptoTestUtils::CallbackSource {
[email protected]6fc79ea2014-07-10 04:30:2383 public:
84 // Takes ownership of |sync_source|, a synchronous ChannelIDSource.
85 explicit AsyncTestChannelIDSource(ChannelIDSource* sync_source)
86 : sync_source_(sync_source) {}
dchengb03027d2014-10-21 12:00:2087 ~AsyncTestChannelIDSource() override {}
[email protected]6fc79ea2014-07-10 04:30:2388
89 // ChannelIDSource implementation.
dchengb03027d2014-10-21 12:00:2090 QuicAsyncStatus GetChannelIDKey(const string& hostname,
91 scoped_ptr<ChannelIDKey>* channel_id_key,
92 ChannelIDSourceCallback* callback) override {
[email protected]6fc79ea2014-07-10 04:30:2393 // Synchronous mode.
94 if (!callback) {
rtennetibe635732014-10-02 22:51:4295 return sync_source_->GetChannelIDKey(hostname, channel_id_key, nullptr);
[email protected]6fc79ea2014-07-10 04:30:2396 }
97
98 // Asynchronous mode.
99 QuicAsyncStatus status =
rtennetibe635732014-10-02 22:51:42100 sync_source_->GetChannelIDKey(hostname, &channel_id_key_, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23101 if (status != QUIC_SUCCESS) {
102 return QUIC_FAILURE;
103 }
104 callback_.reset(callback);
105 return QUIC_PENDING;
106 }
107
[email protected]dc6094a2014-07-23 01:50:04108 // CallbackSource implementation.
dchengb03027d2014-10-21 12:00:20109 void RunPendingCallbacks() override {
[email protected]6fc79ea2014-07-10 04:30:23110 if (callback_.get()) {
111 callback_->Run(&channel_id_key_);
112 callback_.reset();
113 }
114 }
115
116 private:
117 scoped_ptr<ChannelIDSource> sync_source_;
118 scoped_ptr<ChannelIDSourceCallback> callback_;
119 scoped_ptr<ChannelIDKey> channel_id_key_;
120};
121
[email protected]ed3fc15d2013-03-08 18:37:44122} // anonymous namespace
123
rjshadec86dbfa2015-11-12 20:16:25124CryptoTestUtils::FakeServerOptions::FakeServerOptions()
125 : token_binding_enabled(false) {}
126
[email protected]899951652013-05-16 12:52:39127CryptoTestUtils::FakeClientOptions::FakeClientOptions()
rjshadec86dbfa2015-11-12 20:16:25128 : channel_id_enabled(false),
129 channel_id_source_async(false),
130 token_binding_enabled(false) {}
[email protected]899951652013-05-16 12:52:39131
[email protected]ed3fc15d2013-03-08 18:37:44132// static
[email protected]fe053f92013-04-23 20:18:55133int CryptoTestUtils::HandshakeWithFakeServer(
rch99b644c2015-11-04 05:25:28134 MockConnectionHelper* helper,
[email protected]ed3fc15d2013-03-08 18:37:44135 PacketSavingConnection* client_conn,
rjshadec86dbfa2015-11-12 20:16:25136 QuicCryptoClientStream* client,
137 const FakeServerOptions& options) {
rtenneti6f48aa92015-03-16 02:18:48138 PacketSavingConnection* server_conn = new PacketSavingConnection(
rtenneti8a4a0732015-10-18 00:45:51139 helper, Perspective::IS_SERVER, client_conn->supported_versions());
rtennetid39bd762015-06-12 01:05:52140
141 QuicConfig config = DefaultQuicConfig();
[email protected]b064310782013-05-30 21:12:17142 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
rch1fe2eeb2015-10-26 14:45:57143 QuicRandom::GetInstance(),
144 ProofSourceForTesting());
rtennetid39bd762015-06-12 01:05:52145 SetupCryptoServerConfigForTest(server_conn->clock(),
146 server_conn->random_generator(), &config,
rjshadec86dbfa2015-11-12 20:16:25147 &crypto_config, options);
[email protected]ccb34212014-07-18 09:27:50148
rtennetib865eb82015-06-17 20:21:46149 TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44150
151 // The client's handshake must have been started already.
rtennetib6ac61a52015-02-11 20:20:52152 CHECK_NE(0u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44153
rtennetid39bd762015-06-12 01:05:52154 CommunicateHandshakeMessages(client_conn, client, server_conn,
155 server_session.GetCryptoStream());
rtennetid39bd762015-06-12 01:05:52156 CompareClientAndServerKeys(client, server_session.GetCryptoStream());
[email protected]fe053f92013-04-23 20:18:55157
158 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44159}
160
161// static
[email protected]fe053f92013-04-23 20:18:55162int CryptoTestUtils::HandshakeWithFakeClient(
rch99b644c2015-11-04 05:25:28163 MockConnectionHelper* helper,
[email protected]ed3fc15d2013-03-08 18:37:44164 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39165 QuicCryptoServerStream* server,
zhongyic92bc492015-09-22 19:14:36166 const QuicServerId& server_id,
[email protected]899951652013-05-16 12:52:39167 const FakeClientOptions& options) {
rtenneti6f48aa92015-03-16 02:18:48168 PacketSavingConnection* client_conn =
rtenneti8a4a0732015-10-18 00:45:51169 new PacketSavingConnection(helper, Perspective::IS_CLIENT);
rtenneti85d89712014-11-20 03:32:24170 // Advance the time, because timers do not like uninitialized times.
171 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
[email protected]ef95114d2013-04-17 17:57:01172
rch1fe2eeb2015-10-26 14:45:57173 QuicCryptoClientConfig crypto_config(ProofVerifierForTesting());
rtennetibe635732014-10-02 22:51:42174 AsyncTestChannelIDSource* async_channel_id_source = nullptr;
[email protected]b064310782013-05-30 21:12:17175 if (options.channel_id_enabled) {
[email protected]6fc79ea2014-07-10 04:30:23176
177 ChannelIDSource* source = ChannelIDSourceForTesting();
178 if (options.channel_id_source_async) {
179 async_channel_id_source = new AsyncTestChannelIDSource(source);
180 source = async_channel_id_source;
181 }
182 crypto_config.SetChannelIDSource(source);
[email protected]b064310782013-05-30 21:12:17183 }
rjshadec86dbfa2015-11-12 20:16:25184 if (options.token_binding_enabled) {
185 crypto_config.tb_key_params.push_back(kP256);
186 }
rtennetib865eb82015-06-17 20:21:46187 TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(),
188 server_id, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44189
rtennetid39bd762015-06-12 01:05:52190 client_session.GetCryptoStream()->CryptoConnect();
rtennetib6ac61a52015-02-11 20:20:52191 CHECK_EQ(1u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44192
[email protected]dc6094a2014-07-23 01:50:04193 CommunicateHandshakeMessagesAndRunCallbacks(
rtennetid39bd762015-06-12 01:05:52194 client_conn, client_session.GetCryptoStream(), server_conn, server,
195 async_channel_id_source);
[email protected]14e8106c2013-03-14 16:25:33196
rtennetid39bd762015-06-12 01:05:52197 CompareClientAndServerKeys(client_session.GetCryptoStream(), server);
[email protected]fe053f92013-04-23 20:18:55198
[email protected]38b3fd12013-06-18 08:19:01199 if (options.channel_id_enabled) {
[email protected]03dd32532014-05-30 07:11:25200 scoped_ptr<ChannelIDKey> channel_id_key;
rtennetibe635732014-10-02 22:51:42201 QuicAsyncStatus status = crypto_config.channel_id_source()->GetChannelIDKey(
zhongyic92bc492015-09-22 19:14:36202 server_id.host(), &channel_id_key, nullptr);
[email protected]05bfc260f2014-06-07 06:31:25203 EXPECT_EQ(QUIC_SUCCESS, status);
[email protected]03dd32532014-05-30 07:11:25204 EXPECT_EQ(channel_id_key->SerializeKey(),
205 server->crypto_negotiated_params().channel_id);
rtennetid39bd762015-06-12 01:05:52206 EXPECT_EQ(
207 options.channel_id_source_async,
208 client_session.GetCryptoStream()->WasChannelIDSourceCallbackRun());
[email protected]38b3fd12013-06-18 08:19:01209 }
210
rtennetid39bd762015-06-12 01:05:52211 return client_session.GetCryptoStream()->num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33212}
213
214// static
[email protected]ef95114d2013-04-17 17:57:01215void CryptoTestUtils::SetupCryptoServerConfigForTest(
216 const QuicClock* clock,
217 QuicRandom* rand,
218 QuicConfig* config,
rjshadec86dbfa2015-11-12 20:16:25219 QuicCryptoServerConfig* crypto_config,
220 const FakeServerOptions& fake_options) {
[email protected]b064310782013-05-30 21:12:17221 QuicCryptoServerConfig::ConfigOptions options;
222 options.channel_id_enabled = true;
rjshadec86dbfa2015-11-12 20:16:25223 options.token_binding_enabled = fake_options.token_binding_enabled;
[email protected]ef95114d2013-04-17 17:57:01224 scoped_ptr<CryptoHandshakeMessage> scfg(
[email protected]b064310782013-05-30 21:12:17225 crypto_config->AddDefaultConfig(rand, clock, options));
[email protected]ef95114d2013-04-17 17:57:01226}
227
228// static
[email protected]0bbeb6972013-05-23 04:10:21229void CryptoTestUtils::CommunicateHandshakeMessages(
230 PacketSavingConnection* a_conn,
231 QuicCryptoStream* a,
232 PacketSavingConnection* b_conn,
233 QuicCryptoStream* b) {
rtennetibe635732014-10-02 22:51:42234 CommunicateHandshakeMessagesAndRunCallbacks(a_conn, a, b_conn, b, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23235}
236
237// static
[email protected]dc6094a2014-07-23 01:50:04238void CryptoTestUtils::CommunicateHandshakeMessagesAndRunCallbacks(
[email protected]6fc79ea2014-07-10 04:30:23239 PacketSavingConnection* a_conn,
240 QuicCryptoStream* a,
241 PacketSavingConnection* b_conn,
242 QuicCryptoStream* b,
[email protected]dc6094a2014-07-23 01:50:04243 CallbackSource* callback_source) {
[email protected]0bbeb6972013-05-23 04:10:21244 size_t a_i = 0, b_i = 0;
245 while (!a->handshake_confirmed()) {
rtennetib6ac61a52015-02-11 20:20:52246 ASSERT_GT(a_conn->encrypted_packets_.size(), a_i);
247 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
248 << " packets a->b";
[email protected]0bbeb6972013-05-23 04:10:21249 MovePackets(a_conn, &a_i, b, b_conn);
[email protected]dc6094a2014-07-23 01:50:04250 if (callback_source) {
251 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23252 }
[email protected]0bbeb6972013-05-23 04:10:21253
rtennetib6ac61a52015-02-11 20:20:52254 ASSERT_GT(b_conn->encrypted_packets_.size(), b_i);
255 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
256 << " packets b->a";
[email protected]0bbeb6972013-05-23 04:10:21257 MovePackets(b_conn, &b_i, a, a_conn);
[email protected]dc6094a2014-07-23 01:50:04258 if (callback_source) {
259 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23260 }
[email protected]0bbeb6972013-05-23 04:10:21261 }
262}
263
[email protected]b694e48c2014-03-18 17:10:13264// static
[email protected]691f45a982013-11-19 10:52:04265pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
266 PacketSavingConnection* a_conn,
267 QuicCryptoStream* a,
268 size_t a_i,
269 PacketSavingConnection* b_conn,
270 QuicCryptoStream* b,
271 size_t b_i) {
rtennetib6ac61a52015-02-11 20:20:52272 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
273 << " packets a->b";
[email protected]691f45a982013-11-19 10:52:04274 MovePackets(a_conn, &a_i, b, b_conn);
275
rtennetib6ac61a52015-02-11 20:20:52276 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
277 << " packets b->a";
278 if (b_conn->encrypted_packets_.size() - b_i == 2) {
279 VLOG(1) << "here";
[email protected]691f45a982013-11-19 10:52:04280 }
281 MovePackets(b_conn, &b_i, a, a_conn);
282
rtenneti16a20772015-02-17 18:58:48283 return std::make_pair(a_i, b_i);
[email protected]691f45a982013-11-19 10:52:04284}
285
[email protected]0bbeb6972013-05-23 04:10:21286// static
[email protected]ccc66e8a2013-03-26 08:26:14287string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33288 QuicTag tag) {
289 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14290 if (it == message.tag_value_map().end()) {
291 return string();
292 }
293 return it->second;
294}
295
[email protected]2532de12013-05-09 12:29:33296class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04297 public:
[email protected]2532de12013-05-09 12:29:33298 MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
[email protected]c244c5a12013-05-07 20:55:04299 : cert_(cert.as_string()),
300 hash_(hash),
301 index_(index) {
302 }
303
dchengb03027d2014-10-21 12:00:20304 StringPiece GetCommonHashes() const override {
[email protected]c244c5a12013-05-07 20:55:04305 CHECK(false) << "not implemented";
306 return StringPiece();
307 }
308
dchengb03027d2014-10-21 12:00:20309 StringPiece GetCert(uint64 hash, uint32 index) const override {
[email protected]c244c5a12013-05-07 20:55:04310 if (hash == hash_ && index == index_) {
311 return cert_;
312 }
313 return StringPiece();
314 }
315
dchengb03027d2014-10-21 12:00:20316 bool MatchCert(StringPiece cert,
317 StringPiece common_set_hashes,
318 uint64* out_hash,
319 uint32* out_index) const override {
[email protected]c244c5a12013-05-07 20:55:04320 if (cert != cert_) {
321 return false;
322 }
323
324 if (common_set_hashes.size() % sizeof(uint64) != 0) {
325 return false;
326 }
327 bool client_has_set = false;
328 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) {
329 uint64 hash;
330 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
331 if (hash == hash_) {
332 client_has_set = true;
333 break;
334 }
335 }
336
337 if (!client_has_set) {
338 return false;
339 }
340
341 *out_hash = hash_;
342 *out_index = index_;
343 return true;
344 }
345
346 private:
347 const string cert_;
348 const uint64 hash_;
349 const uint32 index_;
350};
351
[email protected]2532de12013-05-09 12:29:33352CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
[email protected]899951652013-05-16 12:52:39353 uint64 hash,
354 uint32 index) {
[email protected]2532de12013-05-09 12:29:33355 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04356}
357
rch94e52bc2015-12-06 04:28:26358// static
359void CryptoTestUtils::FillInDummyReject(CryptoHandshakeMessage* rej,
360 bool reject_is_stateless) {
361 if (reject_is_stateless) {
362 rej->set_tag(kSREJ);
363 } else {
364 rej->set_tag(kREJ);
365 }
366
367 // Minimum SCFG that passes config validation checks.
368 // clang-format off
369 unsigned char scfg[] = {
370 // SCFG
371 0x53, 0x43, 0x46, 0x47,
372 // num entries
373 0x01, 0x00,
374 // padding
375 0x00, 0x00,
376 // EXPY
377 0x45, 0x58, 0x50, 0x59,
378 // EXPY end offset
379 0x08, 0x00, 0x00, 0x00,
380 // Value
381 '1', '2', '3', '4',
382 '5', '6', '7', '8'
383 };
384 // clang-format on
385 rej->SetValue(kSCFG, scfg);
386 rej->SetStringPiece(kServerNonceTag, "SERVER_NONCE");
387 vector<QuicTag> reject_reasons;
388 reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
389 rej->SetVector(kRREJ, reject_reasons);
390}
391
[email protected]14e8106c2013-03-14 16:25:33392void CryptoTestUtils::CompareClientAndServerKeys(
393 QuicCryptoClientStream* client,
394 QuicCryptoServerStream* server) {
rch1e543ec2015-03-29 07:04:40395 QuicFramer* client_framer =
396 QuicConnectionPeer::GetFramer(client->session()->connection());
397 QuicFramer* server_framer =
398 QuicConnectionPeer::GetFramer(server->session()->connection());
[email protected]8ba81212013-05-03 13:11:48399 const QuicEncrypter* client_encrypter(
rch1e543ec2015-03-29 07:04:40400 QuicFramerPeer::GetEncrypter(client_framer, ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48401 const QuicDecrypter* client_decrypter(
[email protected]2532de12013-05-09 12:29:33402 client->session()->connection()->decrypter());
403 const QuicEncrypter* client_forward_secure_encrypter(
rch1e543ec2015-03-29 07:04:40404 QuicFramerPeer::GetEncrypter(client_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33405 const QuicDecrypter* client_forward_secure_decrypter(
[email protected]8ba81212013-05-03 13:11:48406 client->session()->connection()->alternative_decrypter());
407 const QuicEncrypter* server_encrypter(
rch1e543ec2015-03-29 07:04:40408 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48409 const QuicDecrypter* server_decrypter(
410 server->session()->connection()->decrypter());
[email protected]2532de12013-05-09 12:29:33411 const QuicEncrypter* server_forward_secure_encrypter(
rch1e543ec2015-03-29 07:04:40412 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33413 const QuicDecrypter* server_forward_secure_decrypter(
414 server->session()->connection()->alternative_decrypter());
[email protected]8ba81212013-05-03 13:11:48415
416 StringPiece client_encrypter_key = client_encrypter->GetKey();
417 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
418 StringPiece client_decrypter_key = client_decrypter->GetKey();
419 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33420 StringPiece client_forward_secure_encrypter_key =
421 client_forward_secure_encrypter->GetKey();
422 StringPiece client_forward_secure_encrypter_iv =
423 client_forward_secure_encrypter->GetNoncePrefix();
424 StringPiece client_forward_secure_decrypter_key =
425 client_forward_secure_decrypter->GetKey();
426 StringPiece client_forward_secure_decrypter_iv =
427 client_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48428 StringPiece server_encrypter_key = server_encrypter->GetKey();
429 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
430 StringPiece server_decrypter_key = server_decrypter->GetKey();
431 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33432 StringPiece server_forward_secure_encrypter_key =
433 server_forward_secure_encrypter->GetKey();
434 StringPiece server_forward_secure_encrypter_iv =
435 server_forward_secure_encrypter->GetNoncePrefix();
436 StringPiece server_forward_secure_decrypter_key =
437 server_forward_secure_decrypter->GetKey();
438 StringPiece server_forward_secure_decrypter_iv =
439 server_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48440
[email protected]2fe8b632014-07-31 11:36:37441 StringPiece client_subkey_secret =
442 client->crypto_negotiated_params().subkey_secret;
443 StringPiece server_subkey_secret =
444 server->crypto_negotiated_params().subkey_secret;
445
446
447 const char kSampleLabel[] = "label";
448 const char kSampleContext[] = "context";
449 const size_t kSampleOutputLength = 32;
450 string client_key_extraction;
451 string server_key_extraction;
452 EXPECT_TRUE(client->ExportKeyingMaterial(kSampleLabel,
453 kSampleContext,
454 kSampleOutputLength,
455 &client_key_extraction));
456 EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel,
457 kSampleContext,
458 kSampleOutputLength,
459 &server_key_extraction));
460
[email protected]14e8106c2013-03-14 16:25:33461 CompareCharArraysWithHexError("client write key",
462 client_encrypter_key.data(),
463 client_encrypter_key.length(),
464 server_decrypter_key.data(),
465 server_decrypter_key.length());
466 CompareCharArraysWithHexError("client write IV",
467 client_encrypter_iv.data(),
468 client_encrypter_iv.length(),
469 server_decrypter_iv.data(),
470 server_decrypter_iv.length());
471 CompareCharArraysWithHexError("server write key",
472 server_encrypter_key.data(),
473 server_encrypter_key.length(),
474 client_decrypter_key.data(),
475 client_decrypter_key.length());
476 CompareCharArraysWithHexError("server write IV",
477 server_encrypter_iv.data(),
478 server_encrypter_iv.length(),
479 client_decrypter_iv.data(),
480 client_decrypter_iv.length());
[email protected]2532de12013-05-09 12:29:33481 CompareCharArraysWithHexError("client forward secure write key",
482 client_forward_secure_encrypter_key.data(),
483 client_forward_secure_encrypter_key.length(),
484 server_forward_secure_decrypter_key.data(),
485 server_forward_secure_decrypter_key.length());
486 CompareCharArraysWithHexError("client forward secure write IV",
487 client_forward_secure_encrypter_iv.data(),
488 client_forward_secure_encrypter_iv.length(),
489 server_forward_secure_decrypter_iv.data(),
490 server_forward_secure_decrypter_iv.length());
491 CompareCharArraysWithHexError("server forward secure write key",
492 server_forward_secure_encrypter_key.data(),
493 server_forward_secure_encrypter_key.length(),
494 client_forward_secure_decrypter_key.data(),
495 client_forward_secure_decrypter_key.length());
496 CompareCharArraysWithHexError("server forward secure write IV",
497 server_forward_secure_encrypter_iv.data(),
498 server_forward_secure_encrypter_iv.length(),
499 client_forward_secure_decrypter_iv.data(),
500 client_forward_secure_decrypter_iv.length());
[email protected]2fe8b632014-07-31 11:36:37501 CompareCharArraysWithHexError("subkey secret",
502 client_subkey_secret.data(),
503 client_subkey_secret.length(),
504 server_subkey_secret.data(),
505 server_subkey_secret.length());
506 CompareCharArraysWithHexError("sample key extraction",
507 client_key_extraction.data(),
508 client_key_extraction.length(),
509 server_key_extraction.data(),
510 server_key_extraction.length());
[email protected]ed3fc15d2013-03-08 18:37:44511}
[email protected]0bbeb6972013-05-23 04:10:21512
513// static
514QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
515 const size_t len = strlen(tagstr);
516 CHECK_NE(0u, len);
517
518 QuicTag tag = 0;
519
520 if (tagstr[0] == '#') {
521 CHECK_EQ(static_cast<size_t>(1 + 2*4), len);
522 tagstr++;
523
524 for (size_t i = 0; i < 8; i++) {
525 tag <<= 4;
526
527 uint8 v = 0;
528 CHECK(HexChar(tagstr[i], &v));
529 tag |= v;
530 }
531
532 return tag;
533 }
534
535 CHECK_LE(len, 4u);
536 for (size_t i = 0; i < 4; i++) {
537 tag >>= 8;
538 if (i < len) {
539 tag |= static_cast<uint32>(tagstr[i]) << 24;
540 }
541 }
542
543 return tag;
544}
545
546// static
547CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
548 va_list ap;
549 va_start(ap, message_tag);
550
[email protected]0bbeb6972013-05-23 04:10:21551 CryptoHandshakeMessage msg;
552 msg.set_tag(ParseTag(message_tag));
553
554 for (;;) {
555 const char* tagstr = va_arg(ap, const char*);
rtennetibe635732014-10-02 22:51:42556 if (tagstr == nullptr) {
[email protected]0bbeb6972013-05-23 04:10:21557 break;
558 }
559
[email protected]4e49b6a2013-06-18 16:39:28560 if (tagstr[0] == '$') {
561 // Special value.
562 const char* const special = tagstr + 1;
563 if (strcmp(special, "padding") == 0) {
564 const int min_bytes = va_arg(ap, int);
565 msg.set_minimum_size(min_bytes);
566 } else {
567 CHECK(false) << "Unknown special value: " << special;
568 }
569
570 continue;
571 }
572
[email protected]0bbeb6972013-05-23 04:10:21573 const QuicTag tag = ParseTag(tagstr);
574 const char* valuestr = va_arg(ap, const char*);
575
576 size_t len = strlen(valuestr);
577 if (len > 0 && valuestr[0] == '#') {
578 valuestr++;
579 len--;
580
[email protected]257f24f2014-04-01 09:15:37581 CHECK_EQ(0u, len % 2);
[email protected]0bbeb6972013-05-23 04:10:21582 scoped_ptr<uint8[]> buf(new uint8[len/2]);
583
584 for (size_t i = 0; i < len/2; i++) {
585 uint8 v = 0;
586 CHECK(HexChar(valuestr[i*2], &v));
587 buf[i] = v << 4;
588 CHECK(HexChar(valuestr[i*2 + 1], &v));
589 buf[i] |= v;
590 }
591
592 msg.SetStringPiece(
593 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len/2));
594 continue;
595 }
596
597 msg.SetStringPiece(tag, valuestr);
598 }
599
[email protected]4e49b6a2013-06-18 16:39:28600 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
601 // that any padding is included.
602 scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
603 scoped_ptr<CryptoHandshakeMessage> parsed(
604 CryptoFramer::ParseMessage(bytes->AsStringPiece()));
605 CHECK(parsed.get());
606
rtenneti48f371c682015-08-27 05:34:26607 va_end(ap);
[email protected]4e49b6a2013-06-18 16:39:28608 return *parsed;
[email protected]0bbeb6972013-05-23 04:10:21609}
610
rjshadec86dbfa2015-11-12 20:16:25611// static
612void CryptoTestUtils::MovePackets(PacketSavingConnection* source_conn,
613 size_t* inout_packet_index,
614 QuicCryptoStream* dest_stream,
615 PacketSavingConnection* dest_conn) {
616 SimpleQuicFramer framer(source_conn->supported_versions());
617 CryptoFramer crypto_framer;
618 CryptoFramerVisitor crypto_visitor;
619
620 // In order to properly test the code we need to perform encryption and
621 // decryption so that the crypters latch when expected. The crypters are in
622 // |dest_conn|, but we don't want to try and use them there. Instead we swap
623 // them into |framer|, perform the decryption with them, and then swap ther
624 // back.
625 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
626
627 crypto_framer.set_visitor(&crypto_visitor);
628
629 size_t index = *inout_packet_index;
630 for (; index < source_conn->encrypted_packets_.size(); index++) {
631 if (!framer.ProcessPacket(*source_conn->encrypted_packets_[index])) {
632 // The framer will be unable to decrypt forward-secure packets sent after
633 // the handshake is complete. Don't treat them as handshake packets.
634 break;
635 }
636
zhongyi36727b82015-12-03 00:42:23637 for (const QuicStreamFrame* stream_frame : framer.stream_frames()) {
638 ASSERT_TRUE(crypto_framer.ProcessInput(stream_frame->data));
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