blob: 811da803f1a59c3e60021afc2c6155436fa2a242 [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]e4c3ea62014-03-15 00:45:1435const char kServerHostname[] = "test.example.com";
36const uint16 kServerPort = 80;
37
[email protected]fe053f92013-04-23 20:18:5538// CryptoFramerVisitor is a framer visitor that records handshake messages.
39class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
40 public:
41 CryptoFramerVisitor()
42 : error_(false) {
43 }
[email protected]ed3fc15d2013-03-08 18:37:4444
dchengb03027d2014-10-21 12:00:2045 void OnError(CryptoFramer* framer) override { error_ = true; }
[email protected]ed3fc15d2013-03-08 18:37:4446
dchengb03027d2014-10-21 12:00:2047 void OnHandshakeMessage(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
[email protected]9693157b2014-08-08 11:13:4965// |*inout_packet_index| through to the last packet (or until a packet fails to
66// decrypt) and has |dest_stream| process them. |*inout_packet_index| is updated
67// with an index one greater than the last packet processed.
[email protected]fe053f92013-04-23 20:18:5568void 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++) {
[email protected]9693157b2014-08-08 11:13:4987 if (!framer.ProcessPacket(*source_conn->encrypted_packets_[index])) {
88 // The framer will be unable to decrypt forward-secure packets sent after
89 // the handshake is complete. Don't treat them as handshake packets.
90 break;
91 }
92
rtennetia4228ea2015-06-04 02:31:4493 for (const QuicStreamFrame& stream_frame : framer.stream_frames()) {
94 ASSERT_TRUE(crypto_framer.ProcessInput(stream_frame.data));
[email protected]fe053f92013-04-23 20:18:5595 ASSERT_FALSE(crypto_visitor.error());
96 }
97 }
98 *inout_packet_index = index;
99
[email protected]2532de12013-05-09 12:29:33100 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
101
[email protected]fe053f92013-04-23 20:18:55102 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
103
rtennetia4228ea2015-06-04 02:31:44104 for (const CryptoHandshakeMessage& message : crypto_visitor.messages()) {
105 dest_stream->OnHandshakeMessage(message);
[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|
rtennetibe635732014-10-02 22:51:42128// argument to GetChannelIDKey is nullptr.
[email protected]6fc79ea2014-07-10 04:30:23129class AsyncTestChannelIDSource : public ChannelIDSource,
[email protected]dc6094a2014-07-23 01:50:04130 public CryptoTestUtils::CallbackSource {
[email protected]6fc79ea2014-07-10 04:30:23131 public:
132 // Takes ownership of |sync_source|, a synchronous ChannelIDSource.
133 explicit AsyncTestChannelIDSource(ChannelIDSource* sync_source)
134 : sync_source_(sync_source) {}
dchengb03027d2014-10-21 12:00:20135 ~AsyncTestChannelIDSource() override {}
[email protected]6fc79ea2014-07-10 04:30:23136
137 // ChannelIDSource implementation.
dchengb03027d2014-10-21 12:00:20138 QuicAsyncStatus GetChannelIDKey(const string& hostname,
139 scoped_ptr<ChannelIDKey>* channel_id_key,
140 ChannelIDSourceCallback* callback) override {
[email protected]6fc79ea2014-07-10 04:30:23141 // Synchronous mode.
142 if (!callback) {
rtennetibe635732014-10-02 22:51:42143 return sync_source_->GetChannelIDKey(hostname, channel_id_key, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23144 }
145
146 // Asynchronous mode.
147 QuicAsyncStatus status =
rtennetibe635732014-10-02 22:51:42148 sync_source_->GetChannelIDKey(hostname, &channel_id_key_, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23149 if (status != QUIC_SUCCESS) {
150 return QUIC_FAILURE;
151 }
152 callback_.reset(callback);
153 return QUIC_PENDING;
154 }
155
[email protected]dc6094a2014-07-23 01:50:04156 // CallbackSource implementation.
dchengb03027d2014-10-21 12:00:20157 void RunPendingCallbacks() override {
[email protected]6fc79ea2014-07-10 04:30:23158 if (callback_.get()) {
159 callback_->Run(&channel_id_key_);
160 callback_.reset();
161 }
162 }
163
164 private:
165 scoped_ptr<ChannelIDSource> sync_source_;
166 scoped_ptr<ChannelIDSourceCallback> callback_;
167 scoped_ptr<ChannelIDKey> channel_id_key_;
168};
169
[email protected]ed3fc15d2013-03-08 18:37:44170} // anonymous namespace
171
[email protected]899951652013-05-16 12:52:39172CryptoTestUtils::FakeClientOptions::FakeClientOptions()
[email protected]b064310782013-05-30 21:12:17173 : dont_verify_certs(false),
[email protected]6fc79ea2014-07-10 04:30:23174 channel_id_enabled(false),
175 channel_id_source_async(false) {
[email protected]899951652013-05-16 12:52:39176}
177
[email protected]ed3fc15d2013-03-08 18:37:44178// static
[email protected]fe053f92013-04-23 20:18:55179int CryptoTestUtils::HandshakeWithFakeServer(
[email protected]ed3fc15d2013-03-08 18:37:44180 PacketSavingConnection* client_conn,
[email protected]14e8106c2013-03-14 16:25:33181 QuicCryptoClientStream* client) {
rtenneti6f48aa92015-03-16 02:18:48182 PacketSavingConnection* server_conn = new PacketSavingConnection(
183 Perspective::IS_SERVER, client_conn->supported_versions());
rtennetid39bd762015-06-12 01:05:52184
185 QuicConfig config = DefaultQuicConfig();
[email protected]b064310782013-05-30 21:12:17186 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
187 QuicRandom::GetInstance());
rtennetid39bd762015-06-12 01:05:52188 SetupCryptoServerConfigForTest(server_conn->clock(),
189 server_conn->random_generator(), &config,
190 &crypto_config);
[email protected]ccb34212014-07-18 09:27:50191
rtennetib865eb82015-06-17 20:21:46192 TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44193
194 // The client's handshake must have been started already.
rtennetib6ac61a52015-02-11 20:20:52195 CHECK_NE(0u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44196
rtennetid39bd762015-06-12 01:05:52197 CommunicateHandshakeMessages(client_conn, client, server_conn,
198 server_session.GetCryptoStream());
[email protected]14e8106c2013-03-14 16:25:33199
rtennetid39bd762015-06-12 01:05:52200 CompareClientAndServerKeys(client, server_session.GetCryptoStream());
[email protected]fe053f92013-04-23 20:18:55201
202 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44203}
204
205// static
[email protected]fe053f92013-04-23 20:18:55206int CryptoTestUtils::HandshakeWithFakeClient(
[email protected]ed3fc15d2013-03-08 18:37:44207 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39208 QuicCryptoServerStream* server,
209 const FakeClientOptions& options) {
rtenneti6f48aa92015-03-16 02:18:48210 PacketSavingConnection* client_conn =
211 new PacketSavingConnection(Perspective::IS_CLIENT);
rtenneti85d89712014-11-20 03:32:24212 // Advance the time, because timers do not like uninitialized times.
213 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
[email protected]ef95114d2013-04-17 17:57:01214
rtennetid39bd762015-06-12 01:05:52215 QuicCryptoClientConfig crypto_config;
[email protected]0cceb922014-07-01 02:00:56216 bool is_https = false;
rtennetibe635732014-10-02 22:51:42217 AsyncTestChannelIDSource* async_channel_id_source = nullptr;
[email protected]b064310782013-05-30 21:12:17218 if (options.channel_id_enabled) {
[email protected]0cceb922014-07-01 02:00:56219 is_https = true;
[email protected]6fc79ea2014-07-10 04:30:23220
221 ChannelIDSource* source = ChannelIDSourceForTesting();
222 if (options.channel_id_source_async) {
223 async_channel_id_source = new AsyncTestChannelIDSource(source);
224 source = async_channel_id_source;
225 }
226 crypto_config.SetChannelIDSource(source);
[email protected]b064310782013-05-30 21:12:17227 }
[email protected]0cceb922014-07-01 02:00:56228 QuicServerId server_id(kServerHostname, kServerPort, is_https,
[email protected]257f24f2014-04-01 09:15:37229 PRIVACY_MODE_DISABLED);
rtennetid39bd762015-06-12 01:05:52230 if (!options.dont_verify_certs) {
231 // TODO(wtc): replace this with ProofVerifierForTesting() when we have
232 // a working ProofSourceForTesting().
233 crypto_config.SetProofVerifier(FakeProofVerifierForTesting());
234 }
rtennetib865eb82015-06-17 20:21:46235 TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(),
236 server_id, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44237
rtennetid39bd762015-06-12 01:05:52238 client_session.GetCryptoStream()->CryptoConnect();
rtennetib6ac61a52015-02-11 20:20:52239 CHECK_EQ(1u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44240
[email protected]dc6094a2014-07-23 01:50:04241 CommunicateHandshakeMessagesAndRunCallbacks(
rtennetid39bd762015-06-12 01:05:52242 client_conn, client_session.GetCryptoStream(), server_conn, server,
243 async_channel_id_source);
[email protected]14e8106c2013-03-14 16:25:33244
rtennetid39bd762015-06-12 01:05:52245 CompareClientAndServerKeys(client_session.GetCryptoStream(), server);
[email protected]fe053f92013-04-23 20:18:55246
[email protected]38b3fd12013-06-18 08:19:01247 if (options.channel_id_enabled) {
[email protected]03dd32532014-05-30 07:11:25248 scoped_ptr<ChannelIDKey> channel_id_key;
rtennetibe635732014-10-02 22:51:42249 QuicAsyncStatus status = crypto_config.channel_id_source()->GetChannelIDKey(
250 kServerHostname, &channel_id_key, nullptr);
[email protected]05bfc260f2014-06-07 06:31:25251 EXPECT_EQ(QUIC_SUCCESS, status);
[email protected]03dd32532014-05-30 07:11:25252 EXPECT_EQ(channel_id_key->SerializeKey(),
253 server->crypto_negotiated_params().channel_id);
rtennetid39bd762015-06-12 01:05:52254 EXPECT_EQ(
255 options.channel_id_source_async,
256 client_session.GetCryptoStream()->WasChannelIDSourceCallbackRun());
[email protected]38b3fd12013-06-18 08:19:01257 }
258
rtennetid39bd762015-06-12 01:05:52259 return client_session.GetCryptoStream()->num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33260}
261
262// static
[email protected]ef95114d2013-04-17 17:57:01263void CryptoTestUtils::SetupCryptoServerConfigForTest(
264 const QuicClock* clock,
265 QuicRandom* rand,
266 QuicConfig* config,
267 QuicCryptoServerConfig* crypto_config) {
[email protected]b064310782013-05-30 21:12:17268 QuicCryptoServerConfig::ConfigOptions options;
269 options.channel_id_enabled = true;
[email protected]ef95114d2013-04-17 17:57:01270 scoped_ptr<CryptoHandshakeMessage> scfg(
[email protected]b064310782013-05-30 21:12:17271 crypto_config->AddDefaultConfig(rand, clock, options));
[email protected]ef95114d2013-04-17 17:57:01272}
273
274// static
[email protected]0bbeb6972013-05-23 04:10:21275void CryptoTestUtils::CommunicateHandshakeMessages(
276 PacketSavingConnection* a_conn,
277 QuicCryptoStream* a,
278 PacketSavingConnection* b_conn,
279 QuicCryptoStream* b) {
rtennetibe635732014-10-02 22:51:42280 CommunicateHandshakeMessagesAndRunCallbacks(a_conn, a, b_conn, b, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23281}
282
283// static
[email protected]dc6094a2014-07-23 01:50:04284void CryptoTestUtils::CommunicateHandshakeMessagesAndRunCallbacks(
[email protected]6fc79ea2014-07-10 04:30:23285 PacketSavingConnection* a_conn,
286 QuicCryptoStream* a,
287 PacketSavingConnection* b_conn,
288 QuicCryptoStream* b,
[email protected]dc6094a2014-07-23 01:50:04289 CallbackSource* callback_source) {
[email protected]0bbeb6972013-05-23 04:10:21290 size_t a_i = 0, b_i = 0;
291 while (!a->handshake_confirmed()) {
rtennetib6ac61a52015-02-11 20:20:52292 ASSERT_GT(a_conn->encrypted_packets_.size(), a_i);
293 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
294 << " packets a->b";
[email protected]0bbeb6972013-05-23 04:10:21295 MovePackets(a_conn, &a_i, b, b_conn);
[email protected]dc6094a2014-07-23 01:50:04296 if (callback_source) {
297 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23298 }
[email protected]0bbeb6972013-05-23 04:10:21299
rtennetib6ac61a52015-02-11 20:20:52300 ASSERT_GT(b_conn->encrypted_packets_.size(), b_i);
301 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
302 << " packets b->a";
[email protected]0bbeb6972013-05-23 04:10:21303 MovePackets(b_conn, &b_i, a, a_conn);
[email protected]dc6094a2014-07-23 01:50:04304 if (callback_source) {
305 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23306 }
[email protected]0bbeb6972013-05-23 04:10:21307 }
308}
309
[email protected]b694e48c2014-03-18 17:10:13310// static
[email protected]691f45a982013-11-19 10:52:04311pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
312 PacketSavingConnection* a_conn,
313 QuicCryptoStream* a,
314 size_t a_i,
315 PacketSavingConnection* b_conn,
316 QuicCryptoStream* b,
317 size_t b_i) {
rtennetib6ac61a52015-02-11 20:20:52318 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
319 << " packets a->b";
[email protected]691f45a982013-11-19 10:52:04320 MovePackets(a_conn, &a_i, b, b_conn);
321
rtennetib6ac61a52015-02-11 20:20:52322 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
323 << " packets b->a";
324 if (b_conn->encrypted_packets_.size() - b_i == 2) {
325 VLOG(1) << "here";
[email protected]691f45a982013-11-19 10:52:04326 }
327 MovePackets(b_conn, &b_i, a, a_conn);
328
rtenneti16a20772015-02-17 18:58:48329 return std::make_pair(a_i, b_i);
[email protected]691f45a982013-11-19 10:52:04330}
331
[email protected]0bbeb6972013-05-23 04:10:21332// static
[email protected]ccc66e8a2013-03-26 08:26:14333string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33334 QuicTag tag) {
335 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14336 if (it == message.tag_value_map().end()) {
337 return string();
338 }
339 return it->second;
340}
341
[email protected]2532de12013-05-09 12:29:33342class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04343 public:
[email protected]2532de12013-05-09 12:29:33344 MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
[email protected]c244c5a12013-05-07 20:55:04345 : cert_(cert.as_string()),
346 hash_(hash),
347 index_(index) {
348 }
349
dchengb03027d2014-10-21 12:00:20350 StringPiece GetCommonHashes() const override {
[email protected]c244c5a12013-05-07 20:55:04351 CHECK(false) << "not implemented";
352 return StringPiece();
353 }
354
dchengb03027d2014-10-21 12:00:20355 StringPiece GetCert(uint64 hash, uint32 index) const override {
[email protected]c244c5a12013-05-07 20:55:04356 if (hash == hash_ && index == index_) {
357 return cert_;
358 }
359 return StringPiece();
360 }
361
dchengb03027d2014-10-21 12:00:20362 bool MatchCert(StringPiece cert,
363 StringPiece common_set_hashes,
364 uint64* out_hash,
365 uint32* out_index) const override {
[email protected]c244c5a12013-05-07 20:55:04366 if (cert != cert_) {
367 return false;
368 }
369
370 if (common_set_hashes.size() % sizeof(uint64) != 0) {
371 return false;
372 }
373 bool client_has_set = false;
374 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) {
375 uint64 hash;
376 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
377 if (hash == hash_) {
378 client_has_set = true;
379 break;
380 }
381 }
382
383 if (!client_has_set) {
384 return false;
385 }
386
387 *out_hash = hash_;
388 *out_index = index_;
389 return true;
390 }
391
392 private:
393 const string cert_;
394 const uint64 hash_;
395 const uint32 index_;
396};
397
[email protected]2532de12013-05-09 12:29:33398CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
[email protected]899951652013-05-16 12:52:39399 uint64 hash,
400 uint32 index) {
[email protected]2532de12013-05-09 12:29:33401 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04402}
403
[email protected]14e8106c2013-03-14 16:25:33404void CryptoTestUtils::CompareClientAndServerKeys(
405 QuicCryptoClientStream* client,
406 QuicCryptoServerStream* server) {
rch1e543ec2015-03-29 07:04:40407 QuicFramer* client_framer =
408 QuicConnectionPeer::GetFramer(client->session()->connection());
409 QuicFramer* server_framer =
410 QuicConnectionPeer::GetFramer(server->session()->connection());
[email protected]8ba81212013-05-03 13:11:48411 const QuicEncrypter* client_encrypter(
rch1e543ec2015-03-29 07:04:40412 QuicFramerPeer::GetEncrypter(client_framer, 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(
rch1e543ec2015-03-29 07:04:40416 QuicFramerPeer::GetEncrypter(client_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33417 const QuicDecrypter* client_forward_secure_decrypter(
[email protected]8ba81212013-05-03 13:11:48418 client->session()->connection()->alternative_decrypter());
419 const QuicEncrypter* server_encrypter(
rch1e543ec2015-03-29 07:04:40420 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_INITIAL));
[email protected]8ba81212013-05-03 13:11:48421 const QuicDecrypter* server_decrypter(
422 server->session()->connection()->decrypter());
[email protected]2532de12013-05-09 12:29:33423 const QuicEncrypter* server_forward_secure_encrypter(
rch1e543ec2015-03-29 07:04:40424 QuicFramerPeer::GetEncrypter(server_framer, ENCRYPTION_FORWARD_SECURE));
[email protected]2532de12013-05-09 12:29:33425 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]2fe8b632014-07-31 11:36:37453 StringPiece client_subkey_secret =
454 client->crypto_negotiated_params().subkey_secret;
455 StringPiece server_subkey_secret =
456 server->crypto_negotiated_params().subkey_secret;
457
458
459 const char kSampleLabel[] = "label";
460 const char kSampleContext[] = "context";
461 const size_t kSampleOutputLength = 32;
462 string client_key_extraction;
463 string server_key_extraction;
464 EXPECT_TRUE(client->ExportKeyingMaterial(kSampleLabel,
465 kSampleContext,
466 kSampleOutputLength,
467 &client_key_extraction));
468 EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel,
469 kSampleContext,
470 kSampleOutputLength,
471 &server_key_extraction));
472
[email protected]14e8106c2013-03-14 16:25:33473 CompareCharArraysWithHexError("client write key",
474 client_encrypter_key.data(),
475 client_encrypter_key.length(),
476 server_decrypter_key.data(),
477 server_decrypter_key.length());
478 CompareCharArraysWithHexError("client write IV",
479 client_encrypter_iv.data(),
480 client_encrypter_iv.length(),
481 server_decrypter_iv.data(),
482 server_decrypter_iv.length());
483 CompareCharArraysWithHexError("server write key",
484 server_encrypter_key.data(),
485 server_encrypter_key.length(),
486 client_decrypter_key.data(),
487 client_decrypter_key.length());
488 CompareCharArraysWithHexError("server write IV",
489 server_encrypter_iv.data(),
490 server_encrypter_iv.length(),
491 client_decrypter_iv.data(),
492 client_decrypter_iv.length());
[email protected]2532de12013-05-09 12:29:33493 CompareCharArraysWithHexError("client forward secure write key",
494 client_forward_secure_encrypter_key.data(),
495 client_forward_secure_encrypter_key.length(),
496 server_forward_secure_decrypter_key.data(),
497 server_forward_secure_decrypter_key.length());
498 CompareCharArraysWithHexError("client forward secure write IV",
499 client_forward_secure_encrypter_iv.data(),
500 client_forward_secure_encrypter_iv.length(),
501 server_forward_secure_decrypter_iv.data(),
502 server_forward_secure_decrypter_iv.length());
503 CompareCharArraysWithHexError("server forward secure write key",
504 server_forward_secure_encrypter_key.data(),
505 server_forward_secure_encrypter_key.length(),
506 client_forward_secure_decrypter_key.data(),
507 client_forward_secure_decrypter_key.length());
508 CompareCharArraysWithHexError("server forward secure write IV",
509 server_forward_secure_encrypter_iv.data(),
510 server_forward_secure_encrypter_iv.length(),
511 client_forward_secure_decrypter_iv.data(),
512 client_forward_secure_decrypter_iv.length());
[email protected]2fe8b632014-07-31 11:36:37513 CompareCharArraysWithHexError("subkey secret",
514 client_subkey_secret.data(),
515 client_subkey_secret.length(),
516 server_subkey_secret.data(),
517 server_subkey_secret.length());
518 CompareCharArraysWithHexError("sample key extraction",
519 client_key_extraction.data(),
520 client_key_extraction.length(),
521 server_key_extraction.data(),
522 server_key_extraction.length());
[email protected]ed3fc15d2013-03-08 18:37:44523}
[email protected]0bbeb6972013-05-23 04:10:21524
525// static
526QuicTag CryptoTestUtils::ParseTag(const char* tagstr) {
527 const size_t len = strlen(tagstr);
528 CHECK_NE(0u, len);
529
530 QuicTag tag = 0;
531
532 if (tagstr[0] == '#') {
533 CHECK_EQ(static_cast<size_t>(1 + 2*4), len);
534 tagstr++;
535
536 for (size_t i = 0; i < 8; i++) {
537 tag <<= 4;
538
539 uint8 v = 0;
540 CHECK(HexChar(tagstr[i], &v));
541 tag |= v;
542 }
543
544 return tag;
545 }
546
547 CHECK_LE(len, 4u);
548 for (size_t i = 0; i < 4; i++) {
549 tag >>= 8;
550 if (i < len) {
551 tag |= static_cast<uint32>(tagstr[i]) << 24;
552 }
553 }
554
555 return tag;
556}
557
558// static
559CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) {
560 va_list ap;
561 va_start(ap, message_tag);
562
563 CryptoHandshakeMessage message = BuildMessage(message_tag, ap);
564 va_end(ap);
565 return message;
566}
567
568// static
569CryptoHandshakeMessage CryptoTestUtils::BuildMessage(const char* message_tag,
570 va_list ap) {
571 CryptoHandshakeMessage msg;
572 msg.set_tag(ParseTag(message_tag));
573
574 for (;;) {
575 const char* tagstr = va_arg(ap, const char*);
rtennetibe635732014-10-02 22:51:42576 if (tagstr == nullptr) {
[email protected]0bbeb6972013-05-23 04:10:21577 break;
578 }
579
[email protected]4e49b6a2013-06-18 16:39:28580 if (tagstr[0] == '$') {
581 // Special value.
582 const char* const special = tagstr + 1;
583 if (strcmp(special, "padding") == 0) {
584 const int min_bytes = va_arg(ap, int);
585 msg.set_minimum_size(min_bytes);
586 } else {
587 CHECK(false) << "Unknown special value: " << special;
588 }
589
590 continue;
591 }
592
[email protected]0bbeb6972013-05-23 04:10:21593 const QuicTag tag = ParseTag(tagstr);
594 const char* valuestr = va_arg(ap, const char*);
595
596 size_t len = strlen(valuestr);
597 if (len > 0 && valuestr[0] == '#') {
598 valuestr++;
599 len--;
600
[email protected]257f24f2014-04-01 09:15:37601 CHECK_EQ(0u, len % 2);
[email protected]0bbeb6972013-05-23 04:10:21602 scoped_ptr<uint8[]> buf(new uint8[len/2]);
603
604 for (size_t i = 0; i < len/2; i++) {
605 uint8 v = 0;
606 CHECK(HexChar(valuestr[i*2], &v));
607 buf[i] = v << 4;
608 CHECK(HexChar(valuestr[i*2 + 1], &v));
609 buf[i] |= v;
610 }
611
612 msg.SetStringPiece(
613 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len/2));
614 continue;
615 }
616
617 msg.SetStringPiece(tag, valuestr);
618 }
619
[email protected]4e49b6a2013-06-18 16:39:28620 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
621 // that any padding is included.
622 scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg));
623 scoped_ptr<CryptoHandshakeMessage> parsed(
624 CryptoFramer::ParseMessage(bytes->AsStringPiece()));
625 CHECK(parsed.get());
626
627 return *parsed;
[email protected]0bbeb6972013-05-23 04:10:21628}
629
[email protected]ed3fc15d2013-03-08 18:37:44630} // namespace test
631} // namespace net