blob: d1c19db90d11906935193f77fbd4addde61cc20f [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]ef95114d2013-04-17 17:57:01186
[email protected]b064310782013-05-30 21:12:17187 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
188 QuicRandom::GetInstance());
[email protected]ef95114d2013-04-17 17:57:01189 SetupCryptoServerConfigForTest(
190 server_session.connection()->clock(),
191 server_session.connection()->random_generator(),
[email protected]899951652013-05-16 12:52:39192 server_session.config(), &crypto_config);
[email protected]ef95114d2013-04-17 17:57:01193
[email protected]899951652013-05-16 12:52:39194 QuicCryptoServerStream server(crypto_config, &server_session);
[email protected]2532de12013-05-09 12:29:33195 server_session.SetCryptoStream(&server);
[email protected]ed3fc15d2013-03-08 18:37:44196
197 // The client's handshake must have been started already.
198 CHECK_NE(0u, client_conn->packets_.size());
199
200 CommunicateHandshakeMessages(client_conn, client, server_conn, &server);
[email protected]14e8106c2013-03-14 16:25:33201
202 CompareClientAndServerKeys(client, &server);
[email protected]fe053f92013-04-23 20:18:55203
204 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44205}
206
207// static
[email protected]fe053f92013-04-23 20:18:55208int CryptoTestUtils::HandshakeWithFakeClient(
[email protected]ed3fc15d2013-03-08 18:37:44209 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39210 QuicCryptoServerStream* server,
211 const FakeClientOptions& options) {
[email protected]c05a6d222013-12-16 19:42:03212 PacketSavingConnection* client_conn = new PacketSavingConnection(false);
[email protected]90f62f092014-03-24 02:41:23213 TestClientSession client_session(client_conn, DefaultQuicConfig());
[email protected]ef95114d2013-04-17 17:57:01214 QuicCryptoClientConfig crypto_config;
215
[email protected]899951652013-05-16 12:52:39216 client_session.config()->SetDefaults();
[email protected]ef95114d2013-04-17 17:57:01217 crypto_config.SetDefaults();
[email protected]0cceb922014-07-01 02:00:56218 if (!options.dont_verify_certs) {
219 // TODO(wtc): replace this with ProofVerifierForTesting() when we have
220 // a working ProofSourceForTesting().
221 crypto_config.SetProofVerifier(FakeProofVerifierForTesting());
222 }
223 bool is_https = false;
[email protected]6fc79ea2014-07-10 04:30:23224 AsyncTestChannelIDSource* async_channel_id_source = NULL;
[email protected]b064310782013-05-30 21:12:17225 if (options.channel_id_enabled) {
[email protected]0cceb922014-07-01 02:00:56226 is_https = true;
[email protected]6fc79ea2014-07-10 04:30:23227
228 ChannelIDSource* source = ChannelIDSourceForTesting();
229 if (options.channel_id_source_async) {
230 async_channel_id_source = new AsyncTestChannelIDSource(source);
231 source = async_channel_id_source;
232 }
233 crypto_config.SetChannelIDSource(source);
[email protected]b064310782013-05-30 21:12:17234 }
[email protected]0cceb922014-07-01 02:00:56235 QuicServerId server_id(kServerHostname, kServerPort, is_https,
[email protected]257f24f2014-04-01 09:15:37236 PRIVACY_MODE_DISABLED);
[email protected]0cceb922014-07-01 02:00:56237 QuicCryptoClientStream client(server_id, &client_session,
238 ProofVerifyContextForTesting(),
[email protected]b694e48c2014-03-18 17:10:13239 &crypto_config);
[email protected]2532de12013-05-09 12:29:33240 client_session.SetCryptoStream(&client);
[email protected]ed3fc15d2013-03-08 18:37:44241
242 CHECK(client.CryptoConnect());
243 CHECK_EQ(1u, client_conn->packets_.size());
244
[email protected]6fc79ea2014-07-10 04:30:23245 CommunicateHandshakeMessagesAndDoWork(
246 client_conn, &client, server_conn, server, async_channel_id_source);
[email protected]14e8106c2013-03-14 16:25:33247
248 CompareClientAndServerKeys(&client, server);
[email protected]fe053f92013-04-23 20:18:55249
[email protected]38b3fd12013-06-18 08:19:01250 if (options.channel_id_enabled) {
[email protected]03dd32532014-05-30 07:11:25251 scoped_ptr<ChannelIDKey> channel_id_key;
[email protected]05bfc260f2014-06-07 06:31:25252 QuicAsyncStatus status =
253 crypto_config.channel_id_source()->GetChannelIDKey(kServerHostname,
254 &channel_id_key,
255 NULL);
256 EXPECT_EQ(QUIC_SUCCESS, status);
[email protected]03dd32532014-05-30 07:11:25257 EXPECT_EQ(channel_id_key->SerializeKey(),
258 server->crypto_negotiated_params().channel_id);
[email protected]38b3fd12013-06-18 08:19:01259 }
260
[email protected]fe053f92013-04-23 20:18:55261 return client.num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33262}
263
264// static
[email protected]ef95114d2013-04-17 17:57:01265void CryptoTestUtils::SetupCryptoServerConfigForTest(
266 const QuicClock* clock,
267 QuicRandom* rand,
268 QuicConfig* config,
269 QuicCryptoServerConfig* crypto_config) {
270 config->SetDefaults();
[email protected]b064310782013-05-30 21:12:17271 QuicCryptoServerConfig::ConfigOptions options;
272 options.channel_id_enabled = true;
[email protected]ef95114d2013-04-17 17:57:01273 scoped_ptr<CryptoHandshakeMessage> scfg(
[email protected]b064310782013-05-30 21:12:17274 crypto_config->AddDefaultConfig(rand, clock, options));
[email protected]ef95114d2013-04-17 17:57:01275}
276
277// static
[email protected]0bbeb6972013-05-23 04:10:21278void CryptoTestUtils::CommunicateHandshakeMessages(
279 PacketSavingConnection* a_conn,
280 QuicCryptoStream* a,
281 PacketSavingConnection* b_conn,
282 QuicCryptoStream* b) {
[email protected]6fc79ea2014-07-10 04:30:23283 CommunicateHandshakeMessagesAndDoWork(a_conn, a, b_conn, b, NULL);
284}
285
286// static
287void CryptoTestUtils::CommunicateHandshakeMessagesAndDoWork(
288 PacketSavingConnection* a_conn,
289 QuicCryptoStream* a,
290 PacketSavingConnection* b_conn,
291 QuicCryptoStream* b,
292 WorkSource* work_source) {
[email protected]0bbeb6972013-05-23 04:10:21293 size_t a_i = 0, b_i = 0;
294 while (!a->handshake_confirmed()) {
295 ASSERT_GT(a_conn->packets_.size(), a_i);
[email protected]b46d6992013-11-25 19:30:52296 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
[email protected]0bbeb6972013-05-23 04:10:21297 << " packets a->b";
298 MovePackets(a_conn, &a_i, b, b_conn);
[email protected]6fc79ea2014-07-10 04:30:23299 if (work_source) {
300 work_source->DoPendingWork();
301 }
[email protected]0bbeb6972013-05-23 04:10:21302
303 ASSERT_GT(b_conn->packets_.size(), b_i);
[email protected]b46d6992013-11-25 19:30:52304 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
[email protected]0bbeb6972013-05-23 04:10:21305 << " packets b->a";
[email protected]0bbeb6972013-05-23 04:10:21306 MovePackets(b_conn, &b_i, a, a_conn);
[email protected]6fc79ea2014-07-10 04:30:23307 if (work_source) {
308 work_source->DoPendingWork();
309 }
[email protected]0bbeb6972013-05-23 04:10:21310 }
311}
312
[email protected]b694e48c2014-03-18 17:10:13313// static
[email protected]691f45a982013-11-19 10:52:04314pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
315 PacketSavingConnection* a_conn,
316 QuicCryptoStream* a,
317 size_t a_i,
318 PacketSavingConnection* b_conn,
319 QuicCryptoStream* b,
320 size_t b_i) {
[email protected]b46d6992013-11-25 19:30:52321 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
[email protected]691f45a982013-11-19 10:52:04322 << " packets a->b";
323 MovePackets(a_conn, &a_i, b, b_conn);
324
[email protected]b46d6992013-11-25 19:30:52325 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
[email protected]691f45a982013-11-19 10:52:04326 << " packets b->a";
327 if (b_conn->packets_.size() - b_i == 2) {
[email protected]b46d6992013-11-25 19:30:52328 LOG(INFO) << "here";
[email protected]691f45a982013-11-19 10:52:04329 }
330 MovePackets(b_conn, &b_i, a, a_conn);
331
332 return make_pair(a_i, b_i);
333}
334
[email protected]0bbeb6972013-05-23 04:10:21335// static
[email protected]ccc66e8a2013-03-26 08:26:14336string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33337 QuicTag tag) {
338 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14339 if (it == message.tag_value_map().end()) {
340 return string();
341 }
342 return it->second;
343}
344
[email protected]2532de12013-05-09 12:29:33345class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04346 public:
[email protected]2532de12013-05-09 12:29:33347 MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
[email protected]c244c5a12013-05-07 20:55:04348 : cert_(cert.as_string()),
349 hash_(hash),
350 index_(index) {
351 }
352
[email protected]2532de12013-05-09 12:29:33353 virtual StringPiece GetCommonHashes() const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04354 CHECK(false) << "not implemented";
355 return StringPiece();
356 }
357
[email protected]2532de12013-05-09 12:29:33358 virtual StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04359 if (hash == hash_ && index == index_) {
360 return cert_;
361 }
362 return StringPiece();
363 }
364
365 virtual bool MatchCert(StringPiece cert,
366 StringPiece common_set_hashes,
367 uint64* out_hash,
[email protected]2532de12013-05-09 12:29:33368 uint32* out_index) const OVERRIDE {
[email protected]c244c5a12013-05-07 20:55:04369 if (cert != cert_) {
370 return false;
371 }
372
373 if (common_set_hashes.size() % sizeof(uint64) != 0) {
374 return false;
375 }
376 bool client_has_set = false;
377 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) {
378 uint64 hash;
379 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
380 if (hash == hash_) {
381 client_has_set = true;
382 break;
383 }
384 }
385
386 if (!client_has_set) {
387 return false;
388 }
389
390 *out_hash = hash_;
391 *out_index = index_;
392 return true;
393 }
394
395 private:
396 const string cert_;
397 const uint64 hash_;
398 const uint32 index_;
399};
400
[email protected]2532de12013-05-09 12:29:33401CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
[email protected]899951652013-05-16 12:52:39402 uint64 hash,
403 uint32 index) {
[email protected]2532de12013-05-09 12:29:33404 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04405}
406
[email protected]14e8106c2013-03-14 16:25:33407void CryptoTestUtils::CompareClientAndServerKeys(
408 QuicCryptoClientStream* client,
409 QuicCryptoServerStream* server) {
[email protected]8ba81212013-05-03 13:11:48410 const QuicEncrypter* client_encrypter(
411 client->session()->connection()->encrypter(ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48412 const QuicDecrypter* client_decrypter(
[email protected]2532de12013-05-09 12:29:33413 client->session()->connection()->decrypter());
414 const QuicEncrypter* client_forward_secure_encrypter(
415 client->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
416 const QuicDecrypter* client_forward_secure_decrypter(
[email protected]8ba81212013-05-03 13:11:48417 client->session()->connection()->alternative_decrypter());
418 const QuicEncrypter* server_encrypter(
419 server->session()->connection()->encrypter(ENCRYPTION_INITIAL));
420 const QuicDecrypter* server_decrypter(
421 server->session()->connection()->decrypter());
[email protected]2532de12013-05-09 12:29:33422 const QuicEncrypter* server_forward_secure_encrypter(
423 server->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
424 const QuicDecrypter* server_forward_secure_decrypter(
425 server->session()->connection()->alternative_decrypter());
[email protected]8ba81212013-05-03 13:11:48426
427 StringPiece client_encrypter_key = client_encrypter->GetKey();
428 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
429 StringPiece client_decrypter_key = client_decrypter->GetKey();
430 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33431 StringPiece client_forward_secure_encrypter_key =
432 client_forward_secure_encrypter->GetKey();
433 StringPiece client_forward_secure_encrypter_iv =
434 client_forward_secure_encrypter->GetNoncePrefix();
435 StringPiece client_forward_secure_decrypter_key =
436 client_forward_secure_decrypter->GetKey();
437 StringPiece client_forward_secure_decrypter_iv =
438 client_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48439 StringPiece server_encrypter_key = server_encrypter->GetKey();
440 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
441 StringPiece server_decrypter_key = server_decrypter->GetKey();
442 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
[email protected]2532de12013-05-09 12:29:33443 StringPiece server_forward_secure_encrypter_key =
444 server_forward_secure_encrypter->GetKey();
445 StringPiece server_forward_secure_encrypter_iv =
446 server_forward_secure_encrypter->GetNoncePrefix();
447 StringPiece server_forward_secure_decrypter_key =
448 server_forward_secure_decrypter->GetKey();
449 StringPiece server_forward_secure_decrypter_iv =
450 server_forward_secure_decrypter->GetNoncePrefix();
[email protected]8ba81212013-05-03 13:11:48451
[email protected]14e8106c2013-03-14 16:25:33452 CompareCharArraysWithHexError("client write key",
453 client_encrypter_key.data(),
454 client_encrypter_key.length(),
455 server_decrypter_key.data(),
456 server_decrypter_key.length());
457 CompareCharArraysWithHexError("client write IV",
458 client_encrypter_iv.data(),
459 client_encrypter_iv.length(),
460 server_decrypter_iv.data(),
461 server_decrypter_iv.length());
462 CompareCharArraysWithHexError("server write key",
463 server_encrypter_key.data(),
464 server_encrypter_key.length(),
465 client_decrypter_key.data(),
466 client_decrypter_key.length());
467 CompareCharArraysWithHexError("server write IV",
468 server_encrypter_iv.data(),
469 server_encrypter_iv.length(),
470 client_decrypter_iv.data(),
471 client_decrypter_iv.length());
[email protected]2532de12013-05-09 12:29:33472 CompareCharArraysWithHexError("client forward secure write key",
473 client_forward_secure_encrypter_key.data(),
474 client_forward_secure_encrypter_key.length(),
475 server_forward_secure_decrypter_key.data(),
476 server_forward_secure_decrypter_key.length());
477 CompareCharArraysWithHexError("client forward secure write IV",
478 client_forward_secure_encrypter_iv.data(),
479 client_forward_secure_encrypter_iv.length(),
480 server_forward_secure_decrypter_iv.data(),
481 server_forward_secure_decrypter_iv.length());
482 CompareCharArraysWithHexError("server forward secure write key",
483 server_forward_secure_encrypter_key.data(),
484 server_forward_secure_encrypter_key.length(),
485 client_forward_secure_decrypter_key.data(),
486 client_forward_secure_decrypter_key.length());
487 CompareCharArraysWithHexError("server forward secure write IV",
488 server_forward_secure_encrypter_iv.data(),
489 server_forward_secure_encrypter_iv.length(),
490 client_forward_secure_decrypter_iv.data(),
491 client_forward_secure_decrypter_iv.length());
[email protected]ed3fc15d2013-03-08 18:37:44492}
[email protected]0bbeb6972013-05-23 04:10:21493
494// static
495QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
496 const size_t len = strlen(tagstr);
497 CHECK_NE(0u, len);
498
499 QuicTag tag = 0;
500
501 if (tagstr[0] == '#') {
502 CHECK_EQ(static_cast<size_t>(1 + 2*4), len);
503 tagstr++;
504
505 for (size_t i = 0; i < 8; i++) {
506 tag <<= 4;
507
508 uint8 v = 0;
509 CHECK(HexChar(tagstr[i], &v));
510 tag |= v;
511 }
512
513 return tag;
514 }
515
516 CHECK_LE(len, 4u);
517 for (size_t i = 0; i < 4; i++) {
518 tag >>= 8;
519 if (i < len) {
520 tag |= static_cast<uint32>(tagstr[i]) << 24;
521 }
522 }
523
524 return tag;
525}
526
527// static
528CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
529 va_list ap;
530 va_start(ap, message_tag);
531
532 CryptoHandshakeMessage message = BuildMessage(message_tag, ap);
533 va_end(ap);
534 return message;
535}
536
537// static
538CryptoHandshakeMessage CryptoTestUtils::BuildMessage(const char* message_tag,
539 va_list ap) {
540 CryptoHandshakeMessage msg;
541 msg.set_tag(ParseTag(message_tag));
542
543 for (;;) {
544 const char* tagstr = va_arg(ap, const char*);
545 if (tagstr == NULL) {
546 break;
547 }
548
[email protected]4e49b6a2013-06-18 16:39:28549 if (tagstr[0] == '$') {
550 // Special value.
551 const char* const special = tagstr + 1;
552 if (strcmp(special, "padding") == 0) {
553 const int min_bytes = va_arg(ap, int);
554 msg.set_minimum_size(min_bytes);
555 } else {
556 CHECK(false) << "Unknown special value: " << special;
557 }
558
559 continue;
560 }
561
[email protected]0bbeb6972013-05-23 04:10:21562 const QuicTag tag = ParseTag(tagstr);
563 const char* valuestr = va_arg(ap, const char*);
564
565 size_t len = strlen(valuestr);
566 if (len > 0 && valuestr[0] == '#') {
567 valuestr++;
568 len--;
569
[email protected]257f24f2014-04-01 09:15:37570 CHECK_EQ(0u, len % 2);
[email protected]0bbeb6972013-05-23 04:10:21571 scoped_ptr<uint8[]> buf(new uint8[len/2]);
572
573 for (size_t i = 0; i < len/2; i++) {
574 uint8 v = 0;
575 CHECK(HexChar(valuestr[i*2], &v));
576 buf[i] = v << 4;
577 CHECK(HexChar(valuestr[i*2 + 1], &v));
578 buf[i] |= v;
579 }
580
581 msg.SetStringPiece(
582 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len/2));
583 continue;
584 }
585
586 msg.SetStringPiece(tag, valuestr);
587 }
588
[email protected]4e49b6a2013-06-18 16:39:28589 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
590 // that any padding is included.
591 scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
592 scoped_ptr<CryptoHandshakeMessage> parsed(
593 CryptoFramer::ParseMessage(bytes->AsStringPiece()));
594 CHECK(parsed.get());
595
596 return *parsed;
[email protected]0bbeb6972013-05-23 04:10:21597}
598
[email protected]ed3fc15d2013-03-08 18:37:44599} // namespace test
600} // namespace net