blob: e0673983df600a861c58932d4c5728582238536e [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"
[email protected]ed3fc15d2013-03-08 18:37:4420#include "net/quic/test_tools/quic_test_utils.h"
21#include "net/quic/test_tools/simple_quic_framer.h"
[email protected]ed3fc15d2013-03-08 18:37:4422
[email protected]14e8106c2013-03-14 16:25:3323using base::StringPiece;
[email protected]691f45a982013-11-19 10:52:0424using std::make_pair;
25using std::pair;
[email protected]ccc66e8a2013-03-26 08:26:1426using std::string;
[email protected]fe053f92013-04-23 20:18:5527using std::vector;
[email protected]14e8106c2013-03-14 16:25:3328
[email protected]ed3fc15d2013-03-08 18:37:4429namespace net {
30namespace test {
31
32namespace {
33
[email protected]e4c3ea62014-03-15 00:45:1434const char kServerHostname[] = "test.example.com";
35const uint16 kServerPort = 80;
36
[email protected]fe053f92013-04-23 20:18:5537// CryptoFramerVisitor is a framer visitor that records handshake messages.
38class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
39 public:
40 CryptoFramerVisitor()
41 : error_(false) {
42 }
[email protected]ed3fc15d2013-03-08 18:37:4443
[email protected]257f24f2014-04-01 09:15:3744 virtual void OnError(CryptoFramer* framer) OVERRIDE { error_ = true; }
[email protected]ed3fc15d2013-03-08 18:37:4445
[email protected]42091902013-05-02 02:24:1246 virtual void OnHandshakeMessage(
47 const CryptoHandshakeMessage& message) OVERRIDE {
[email protected]fe053f92013-04-23 20:18:5548 messages_.push_back(message);
49 }
[email protected]ed3fc15d2013-03-08 18:37:4450
[email protected]fe053f92013-04-23 20:18:5551 bool error() const {
52 return error_;
53 }
[email protected]ed3fc15d2013-03-08 18:37:4454
[email protected]fe053f92013-04-23 20:18:5555 const vector<CryptoHandshakeMessage>& messages() const {
56 return messages_;
57 }
[email protected]ed3fc15d2013-03-08 18:37:4458
[email protected]fe053f92013-04-23 20:18:5559 private:
60 bool error_;
61 vector<CryptoHandshakeMessage> messages_;
62};
63
64// MovePackets parses crypto handshake messages from packet number
65// |*inout_packet_index| through to the last packet and has |dest_stream|
66// process them. |*inout_packet_index| is updated with an index one greater
67// than the last packet processed.
68void MovePackets(PacketSavingConnection* source_conn,
69 size_t *inout_packet_index,
[email protected]2532de12013-05-09 12:29:3370 QuicCryptoStream* dest_stream,
71 PacketSavingConnection* dest_conn) {
[email protected]4d640792013-12-18 22:21:0872 SimpleQuicFramer framer(source_conn->supported_versions());
[email protected]fe053f92013-04-23 20:18:5573 CryptoFramer crypto_framer;
74 CryptoFramerVisitor crypto_visitor;
75
[email protected]2532de12013-05-09 12:29:3376 // In order to properly test the code we need to perform encryption and
77 // decryption so that the crypters latch when expected. The crypters are in
78 // |dest_conn|, but we don't want to try and use them there. Instead we swap
79 // them into |framer|, perform the decryption with them, and then swap them
80 // back.
81 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
82
[email protected]fe053f92013-04-23 20:18:5583 crypto_framer.set_visitor(&crypto_visitor);
84
85 size_t index = *inout_packet_index;
[email protected]2532de12013-05-09 12:29:3386 for (; index < source_conn->encrypted_packets_.size(); index++) {
87 ASSERT_TRUE(framer.ProcessPacket(*source_conn->encrypted_packets_[index]));
[email protected]fe053f92013-04-23 20:18:5588 for (vector<QuicStreamFrame>::const_iterator
89 i = framer.stream_frames().begin();
90 i != framer.stream_frames().end(); ++i) {
[email protected]5dafdb62013-11-14 01:24:2691 scoped_ptr<string> frame_data(i->GetDataAsString());
92 ASSERT_TRUE(crypto_framer.ProcessInput(*frame_data));
[email protected]fe053f92013-04-23 20:18:5593 ASSERT_FALSE(crypto_visitor.error());
94 }
95 }
96 *inout_packet_index = index;
97
[email protected]2532de12013-05-09 12:29:3398 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
99
[email protected]fe053f92013-04-23 20:18:55100 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
101
102 for (vector<CryptoHandshakeMessage>::const_iterator
103 i = crypto_visitor.messages().begin();
104 i != crypto_visitor.messages().end(); ++i) {
105 dest_stream->OnHandshakeMessage(*i);
[email protected]ed3fc15d2013-03-08 18:37:44106 }
107}
108
[email protected]0bbeb6972013-05-23 04:10:21109// HexChar parses |c| as a hex character. If valid, it sets |*value| to the
110// value of the hex character and returns true. Otherwise it returns false.
111bool HexChar(char c, uint8* value) {
112 if (c >= '0' && c <= '9') {
113 *value = c - '0';
114 return true;
115 }
116 if (c >= 'a' && c <= 'f') {
[email protected]b064310782013-05-30 21:12:17117 *value = c - 'a' + 10;
[email protected]0bbeb6972013-05-23 04:10:21118 return true;
119 }
120 if (c >= 'A' && c <= 'F') {
[email protected]b064310782013-05-30 21:12:17121 *value = c - 'A' + 10;
[email protected]0bbeb6972013-05-23 04:10:21122 return true;
123 }
124 return false;
125}
126
[email protected]6fc79ea2014-07-10 04:30:23127// A ChannelIDSource that works in asynchronous mode unless the |callback|
128// argument to GetChannelIDKey is NULL.
129class AsyncTestChannelIDSource : public ChannelIDSource,
130 public CryptoTestUtils::WorkSource {
131 public:
132 // Takes ownership of |sync_source|, a synchronous ChannelIDSource.
133 explicit AsyncTestChannelIDSource(ChannelIDSource* sync_source)
134 : sync_source_(sync_source) {}
135 virtual ~AsyncTestChannelIDSource() {}
136
137 // ChannelIDSource implementation.
138 virtual QuicAsyncStatus GetChannelIDKey(
139 const string& hostname,
140 scoped_ptr<ChannelIDKey>* channel_id_key,
141 ChannelIDSourceCallback* callback) OVERRIDE {
142 // Synchronous mode.
143 if (!callback) {
144 return sync_source_->GetChannelIDKey(hostname, channel_id_key, NULL);
145 }
146
147 // Asynchronous mode.
148 QuicAsyncStatus status =
149 sync_source_->GetChannelIDKey(hostname, &channel_id_key_, NULL);
150 if (status != QUIC_SUCCESS) {
151 return QUIC_FAILURE;
152 }
153 callback_.reset(callback);
154 return QUIC_PENDING;
155 }
156
157 // WorkSource implementation.
158 virtual void DoPendingWork() OVERRIDE {
159 if (callback_.get()) {
160 callback_->Run(&channel_id_key_);
161 callback_.reset();
162 }
163 }
164
165 private:
166 scoped_ptr<ChannelIDSource> sync_source_;
167 scoped_ptr<ChannelIDSourceCallback> callback_;
168 scoped_ptr<ChannelIDKey> channel_id_key_;
169};
170
[email protected]ed3fc15d2013-03-08 18:37:44171} // anonymous namespace
172
[email protected]899951652013-05-16 12:52:39173CryptoTestUtils::FakeClientOptions::FakeClientOptions()
[email protected]b064310782013-05-30 21:12:17174 : dont_verify_certs(false),
[email protected]6fc79ea2014-07-10 04:30:23175 channel_id_enabled(false),
176 channel_id_source_async(false) {
[email protected]899951652013-05-16 12:52:39177}
178
[email protected]ed3fc15d2013-03-08 18:37:44179// static
[email protected]fe053f92013-04-23 20:18:55180int CryptoTestUtils::HandshakeWithFakeServer(
[email protected]ed3fc15d2013-03-08 18:37:44181 PacketSavingConnection* client_conn,
[email protected]14e8106c2013-03-14 16:25:33182 QuicCryptoClientStream* client) {
[email protected]4d640792013-12-18 22:21:08183 PacketSavingConnection* server_conn =
184 new PacketSavingConnection(true, client_conn->supported_versions());
[email protected]c05a6d222013-12-16 19:42:03185 TestSession server_session(server_conn, DefaultQuicConfig());
[email protected]ccb34212014-07-18 09:27:50186 server_session.InitializeSession();
[email protected]b064310782013-05-30 21:12:17187 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
188 QuicRandom::GetInstance());
[email protected]ccb34212014-07-18 09:27:50189
[email protected]ef95114d2013-04-17 17:57:01190 SetupCryptoServerConfigForTest(
191 server_session.connection()->clock(),
192 server_session.connection()->random_generator(),
[email protected]899951652013-05-16 12:52:39193 server_session.config(), &crypto_config);
[email protected]ef95114d2013-04-17 17:57:01194
[email protected]899951652013-05-16 12:52:39195 QuicCryptoServerStream server(crypto_config, &server_session);
[email protected]2532de12013-05-09 12:29:33196 server_session.SetCryptoStream(&server);
[email protected]ed3fc15d2013-03-08 18:37:44197
198 // The client's handshake must have been started already.
199 CHECK_NE(0u, client_conn->packets_.size());
200
201 CommunicateHandshakeMessages(client_conn, client, server_conn, &server);
[email protected]14e8106c2013-03-14 16:25:33202
203 CompareClientAndServerKeys(client, &server);
[email protected]fe053f92013-04-23 20:18:55204
205 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44206}
207
208// static
[email protected]fe053f92013-04-23 20:18:55209int CryptoTestUtils::HandshakeWithFakeClient(
[email protected]ed3fc15d2013-03-08 18:37:44210 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39211 QuicCryptoServerStream* server,
212 const FakeClientOptions& options) {
[email protected]c05a6d222013-12-16 19:42:03213 PacketSavingConnection* client_conn = new PacketSavingConnection(false);
[email protected]90f62f092014-03-24 02:41:23214 TestClientSession client_session(client_conn, DefaultQuicConfig());
[email protected]ef95114d2013-04-17 17:57:01215 QuicCryptoClientConfig crypto_config;
216
[email protected]899951652013-05-16 12:52:39217 client_session.config()->SetDefaults();
[email protected]ef95114d2013-04-17 17:57:01218 crypto_config.SetDefaults();
[email protected]0cceb922014-07-01 02:00:56219 if (!options.dont_verify_certs) {
220 // TODO(wtc): replace this with ProofVerifierForTesting() when we have
221 // a working ProofSourceForTesting().
222 crypto_config.SetProofVerifier(FakeProofVerifierForTesting());
223 }
224 bool is_https = false;
[email protected]6fc79ea2014-07-10 04:30:23225 AsyncTestChannelIDSource* async_channel_id_source = NULL;
[email protected]b064310782013-05-30 21:12:17226 if (options.channel_id_enabled) {
[email protected]0cceb922014-07-01 02:00:56227 is_https = true;
[email protected]6fc79ea2014-07-10 04:30:23228
229 ChannelIDSource* source = ChannelIDSourceForTesting();
230 if (options.channel_id_source_async) {
231 async_channel_id_source = new AsyncTestChannelIDSource(source);
232 source = async_channel_id_source;
233 }
234 crypto_config.SetChannelIDSource(source);
[email protected]b064310782013-05-30 21:12:17235 }
[email protected]0cceb922014-07-01 02:00:56236 QuicServerId server_id(kServerHostname, kServerPort, is_https,
[email protected]257f24f2014-04-01 09:15:37237 PRIVACY_MODE_DISABLED);
[email protected]0cceb922014-07-01 02:00:56238 QuicCryptoClientStream client(server_id, &client_session,
239 ProofVerifyContextForTesting(),
[email protected]b694e48c2014-03-18 17:10:13240 &crypto_config);
[email protected]2532de12013-05-09 12:29:33241 client_session.SetCryptoStream(&client);
[email protected]ed3fc15d2013-03-08 18:37:44242
243 CHECK(client.CryptoConnect());
244 CHECK_EQ(1u, client_conn->packets_.size());
245
[email protected]6fc79ea2014-07-10 04:30:23246 CommunicateHandshakeMessagesAndDoWork(
247 client_conn, &client, server_conn, server, async_channel_id_source);
[email protected]14e8106c2013-03-14 16:25:33248
249 CompareClientAndServerKeys(&client, server);
[email protected]fe053f92013-04-23 20:18:55250
[email protected]38b3fd12013-06-18 08:19:01251 if (options.channel_id_enabled) {
[email protected]03dd32532014-05-30 07:11:25252 scoped_ptr<ChannelIDKey> channel_id_key;
[email protected]05bfc260f2014-06-07 06:31:25253 QuicAsyncStatus status =
254 crypto_config.channel_id_source()->GetChannelIDKey(kServerHostname,
255 &channel_id_key,
256 NULL);
257 EXPECT_EQ(QUIC_SUCCESS, status);
[email protected]03dd32532014-05-30 07:11:25258 EXPECT_EQ(channel_id_key->SerializeKey(),
259 server->crypto_negotiated_params().channel_id);
[email protected]38b3fd12013-06-18 08:19:01260 }
261
[email protected]fe053f92013-04-23 20:18:55262 return client.num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33263}
264
265// static
[email protected]ef95114d2013-04-17 17:57:01266void CryptoTestUtils::SetupCryptoServerConfigForTest(
267 const QuicClock* clock,
268 QuicRandom* rand,
269 QuicConfig* config,
270 QuicCryptoServerConfig* crypto_config) {
271 config->SetDefaults();
[email protected]b064310782013-05-30 21:12:17272 QuicCryptoServerConfig::ConfigOptions options;
273 options.channel_id_enabled = true;
[email protected]ef95114d2013-04-17 17:57:01274 scoped_ptr<CryptoHandshakeMessage> scfg(
[email protected]b064310782013-05-30 21:12:17275 crypto_config->AddDefaultConfig(rand, clock, options));
[email protected]ef95114d2013-04-17 17:57:01276}
277
278// static
[email protected]0bbeb6972013-05-23 04:10:21279void CryptoTestUtils::CommunicateHandshakeMessages(
280 PacketSavingConnection* a_conn,
281 QuicCryptoStream* a,
282 PacketSavingConnection* b_conn,
283 QuicCryptoStream* b) {
[email protected]6fc79ea2014-07-10 04:30:23284 CommunicateHandshakeMessagesAndDoWork(a_conn, a, b_conn, b, NULL);
285}
286
287// static
288void CryptoTestUtils::CommunicateHandshakeMessagesAndDoWork(
289 PacketSavingConnection* a_conn,
290 QuicCryptoStream* a,
291 PacketSavingConnection* b_conn,
292 QuicCryptoStream* b,
293 WorkSource* work_source) {
[email protected]0bbeb6972013-05-23 04:10:21294 size_t a_i = 0, b_i = 0;
295 while (!a->handshake_confirmed()) {
296 ASSERT_GT(a_conn->packets_.size(), a_i);
[email protected]b46d6992013-11-25 19:30:52297 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
[email protected]0bbeb6972013-05-23 04:10:21298 << " packets a->b";
299 MovePackets(a_conn, &a_i, b, b_conn);
[email protected]6fc79ea2014-07-10 04:30:23300 if (work_source) {
301 work_source->DoPendingWork();
302 }
[email protected]0bbeb6972013-05-23 04:10:21303
304 ASSERT_GT(b_conn->packets_.size(), b_i);
[email protected]b46d6992013-11-25 19:30:52305 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
[email protected]0bbeb6972013-05-23 04:10:21306 << " packets b->a";
[email protected]0bbeb6972013-05-23 04:10:21307 MovePackets(b_conn, &b_i, a, a_conn);
[email protected]6fc79ea2014-07-10 04:30:23308 if (work_source) {
309 work_source->DoPendingWork();
310 }
[email protected]0bbeb6972013-05-23 04:10:21311 }
312}
313
[email protected]b694e48c2014-03-18 17:10:13314// static
[email protected]691f45a982013-11-19 10:52:04315pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
316 PacketSavingConnection* a_conn,
317 QuicCryptoStream* a,
318 size_t a_i,
319 PacketSavingConnection* b_conn,
320 QuicCryptoStream* b,
321 size_t b_i) {
[email protected]b46d6992013-11-25 19:30:52322 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
[email protected]691f45a982013-11-19 10:52:04323 << " packets a->b";
324 MovePackets(a_conn, &a_i, b, b_conn);
325
[email protected]b46d6992013-11-25 19:30:52326 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
[email protected]691f45a982013-11-19 10:52:04327 << " packets b->a";
328 if (b_conn->packets_.size() - b_i == 2) {
[email protected]b46d6992013-11-25 19:30:52329 LOG(INFO) << "here";
[email protected]691f45a982013-11-19 10:52:04330 }
331 MovePackets(b_conn, &b_i, a, a_conn);
332
333 return make_pair(a_i, b_i);
334}
335
[email protected]0bbeb6972013-05-23 04:10:21336// static
[email protected]ccc66e8a2013-03-26 08:26:14337string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33338 QuicTag tag) {
339 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14340 if (it == message.tag_value_map().end()) {
341 return string();
342 }
343 return it->second;
344}
345
[email protected]2532de12013-05-09 12:29:33346class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04347 public:
[email protected]2532de12013-05-09 12:29:33348 MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
[email protected]c244c5a12013-05-07 20:55:04349 : cert_(cert.as_string()),
350 hash_(hash),
351 index_(index) {
352 }
353
[email protected]2532de12013-05-09 12:29:33354 virtual StringPiece GetCommonHashes() const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04355 CHECK(false) << "not implemented";
356 return StringPiece();
357 }
358
[email protected]2532de12013-05-09 12:29:33359 virtual StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04360 if (hash == hash_ && index == index_) {
361 return cert_;
362 }
363 return StringPiece();
364 }
365
366 virtual bool MatchCert(StringPiece cert,
367 StringPiece common_set_hashes,
368 uint64* out_hash,
[email protected]2532de12013-05-09 12:29:33369 uint32* out_index) const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04370 if (cert != cert_) {
371 return false;
372 }
373
374 if (common_set_hashes.size() % sizeof(uint64) != 0) {
375 return false;
376 }
377 bool client_has_set = false;
378 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) {
379 uint64 hash;
380 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
381 if (hash == hash_) {
382 client_has_set = true;
383 break;
384 }
385 }
386
387 if (!client_has_set) {
388 return false;
389 }
390
391 *out_hash = hash_;
392 *out_index = index_;
393 return true;
394 }
395
396 private:
397 const string cert_;
398 const uint64 hash_;
399 const uint32 index_;
400};
401
[email protected]2532de12013-05-09 12:29:33402CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
[email protected]899951652013-05-16 12:52:39403 uint64 hash,
404 uint32 index) {
[email protected]2532de12013-05-09 12:29:33405 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04406}
407
[email protected]14e8106c2013-03-14 16:25:33408void CryptoTestUtils::CompareClientAndServerKeys(
409 QuicCryptoClientStream* client,
410 QuicCryptoServerStream* server) {
[email protected]8ba81212013-05-03 13:11:48411 const QuicEncrypter* client_encrypter(
412 client->session()->connection()->encrypter(ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48413 const QuicDecrypter* client_decrypter(
[email protected]2532de12013-05-09 12:29:33414 client->session()->connection()->decrypter());
415 const QuicEncrypter* client_forward_secure_encrypter(
416 client->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
417 const QuicDecrypter* client_forward_secure_decrypter(
[email protected]8ba81212013-05-03 13:11:48418 client->session()->connection()->alternative_decrypter());
419 const QuicEncrypter* server_encrypter(
420 server->session()->connection()->encrypter(ENCRYPTION_INITIAL));
421 const QuicDecrypter* server_decrypter(
422 server->session()->connection()->decrypter());
[email protected]2532de12013-05-09 12:29:33423 const QuicEncrypter* server_forward_secure_encrypter(
424 server->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
425 const QuicDecrypter* server_forward_secure_decrypter(
426 server->session()->connection()->alternative_decrypter());
[email protected]8ba81212013-05-03 13:11:48427
428 StringPiece client_encrypter_key = client_encrypter->GetKey();
429 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
430 StringPiece client_decrypter_key = client_decrypter->GetKey();
431 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33432 StringPiece client_forward_secure_encrypter_key =
433 client_forward_secure_encrypter->GetKey();
434 StringPiece client_forward_secure_encrypter_iv =
435 client_forward_secure_encrypter->GetNoncePrefix();
436 StringPiece client_forward_secure_decrypter_key =
437 client_forward_secure_decrypter->GetKey();
438 StringPiece client_forward_secure_decrypter_iv =
439 client_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48440 StringPiece server_encrypter_key = server_encrypter->GetKey();
441 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
442 StringPiece server_decrypter_key = server_decrypter->GetKey();
443 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33444 StringPiece server_forward_secure_encrypter_key =
445 server_forward_secure_encrypter->GetKey();
446 StringPiece server_forward_secure_encrypter_iv =
447 server_forward_secure_encrypter->GetNoncePrefix();
448 StringPiece server_forward_secure_decrypter_key =
449 server_forward_secure_decrypter->GetKey();
450 StringPiece server_forward_secure_decrypter_iv =
451 server_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48452
[email protected]14e8106c2013-03-14 16:25:33453 CompareCharArraysWithHexError("client write key",
454 client_encrypter_key.data(),
455 client_encrypter_key.length(),
456 server_decrypter_key.data(),
457 server_decrypter_key.length());
458 CompareCharArraysWithHexError("client write IV",
459 client_encrypter_iv.data(),
460 client_encrypter_iv.length(),
461 server_decrypter_iv.data(),
462 server_decrypter_iv.length());
463 CompareCharArraysWithHexError("server write key",
464 server_encrypter_key.data(),
465 server_encrypter_key.length(),
466 client_decrypter_key.data(),
467 client_decrypter_key.length());
468 CompareCharArraysWithHexError("server write IV",
469 server_encrypter_iv.data(),
470 server_encrypter_iv.length(),
471 client_decrypter_iv.data(),
472 client_decrypter_iv.length());
[email protected]2532de12013-05-09 12:29:33473 CompareCharArraysWithHexError("client forward secure write key",
474 client_forward_secure_encrypter_key.data(),
475 client_forward_secure_encrypter_key.length(),
476 server_forward_secure_decrypter_key.data(),
477 server_forward_secure_decrypter_key.length());
478 CompareCharArraysWithHexError("client forward secure write IV",
479 client_forward_secure_encrypter_iv.data(),
480 client_forward_secure_encrypter_iv.length(),
481 server_forward_secure_decrypter_iv.data(),
482 server_forward_secure_decrypter_iv.length());
483 CompareCharArraysWithHexError("server forward secure write key",
484 server_forward_secure_encrypter_key.data(),
485 server_forward_secure_encrypter_key.length(),
486 client_forward_secure_decrypter_key.data(),
487 client_forward_secure_decrypter_key.length());
488 CompareCharArraysWithHexError("server forward secure write IV",
489 server_forward_secure_encrypter_iv.data(),
490 server_forward_secure_encrypter_iv.length(),
491 client_forward_secure_decrypter_iv.data(),
492 client_forward_secure_decrypter_iv.length());
[email protected]ed3fc15d2013-03-08 18:37:44493}
[email protected]0bbeb6972013-05-23 04:10:21494
495// static
496QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
497 const size_t len = strlen(tagstr);
498 CHECK_NE(0u, len);
499
500 QuicTag tag = 0;
501
502 if (tagstr[0] == '#') {
503 CHECK_EQ(static_cast<size_t>(1 + 2*4), len);
504 tagstr++;
505
506 for (size_t i = 0; i < 8; i++) {
507 tag <<= 4;
508
509 uint8 v = 0;
510 CHECK(HexChar(tagstr[i], &v));
511 tag |= v;
512 }
513
514 return tag;
515 }
516
517 CHECK_LE(len, 4u);
518 for (size_t i = 0; i < 4; i++) {
519 tag >>= 8;
520 if (i < len) {
521 tag |= static_cast<uint32>(tagstr[i]) << 24;
522 }
523 }
524
525 return tag;
526}
527
528// static
529CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
530 va_list ap;
531 va_start(ap, message_tag);
532
533 CryptoHandshakeMessage message = BuildMessage(message_tag, ap);
534 va_end(ap);
535 return message;
536}
537
538// static
539CryptoHandshakeMessage CryptoTestUtils::BuildMessage(const char* message_tag,
540 va_list ap) {
541 CryptoHandshakeMessage msg;
542 msg.set_tag(ParseTag(message_tag));
543
544 for (;;) {
545 const char* tagstr = va_arg(ap, const char*);
546 if (tagstr == NULL) {
547 break;
548 }
549
[email protected]4e49b6a2013-06-18 16:39:28550 if (tagstr[0] == '$') {
551 // Special value.
552 const char* const special = tagstr + 1;
553 if (strcmp(special, "padding") == 0) {
554 const int min_bytes = va_arg(ap, int);
555 msg.set_minimum_size(min_bytes);
556 } else {
557 CHECK(false) << "Unknown special value: " << special;
558 }
559
560 continue;
561 }
562
[email protected]0bbeb6972013-05-23 04:10:21563 const QuicTag tag = ParseTag(tagstr);
564 const char* valuestr = va_arg(ap, const char*);
565
566 size_t len = strlen(valuestr);
567 if (len > 0 && valuestr[0] == '#') {
568 valuestr++;
569 len--;
570
[email protected]257f24f2014-04-01 09:15:37571 CHECK_EQ(0u, len % 2);
[email protected]0bbeb6972013-05-23 04:10:21572 scoped_ptr<uint8[]> buf(new uint8[len/2]);
573
574 for (size_t i = 0; i < len/2; i++) {
575 uint8 v = 0;
576 CHECK(HexChar(valuestr[i*2], &v));
577 buf[i] = v << 4;
578 CHECK(HexChar(valuestr[i*2 + 1], &v));
579 buf[i] |= v;
580 }
581
582 msg.SetStringPiece(
583 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len/2));
584 continue;
585 }
586
587 msg.SetStringPiece(tag, valuestr);
588 }
589
[email protected]4e49b6a2013-06-18 16:39:28590 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
591 // that any padding is included.
592 scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
593 scoped_ptr<CryptoHandshakeMessage> parsed(
594 CryptoFramer::ParseMessage(bytes->AsStringPiece()));
595 CHECK(parsed.get());
596
597 return *parsed;
[email protected]0bbeb6972013-05-23 04:10:21598}
599
[email protected]ed3fc15d2013-03-08 18:37:44600} // namespace test
601} // namespace net