blob: 84c1c9f7e3360ac9da21541a46706e1f15047172 [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
61// MovePackets parses crypto handshake messages from packet number
[email protected]9693157b2014-08-08 11:13:4962// |*inout_packet_index| through to the last packet (or until a packet fails to
63// decrypt) and has |dest_stream| process them. |*inout_packet_index| is updated
64// with an index one greater than the last packet processed.
[email protected]fe053f92013-04-23 20:18:5565void MovePackets(PacketSavingConnection* source_conn,
66 size_t *inout_packet_index,
[email protected]2532de12013-05-09 12:29:3367 QuicCryptoStream* dest_stream,
68 PacketSavingConnection* dest_conn) {
[email protected]4d640792013-12-18 22:21:0869 SimpleQuicFramer framer(source_conn->supported_versions());
[email protected]fe053f92013-04-23 20:18:5570 CryptoFramer crypto_framer;
71 CryptoFramerVisitor crypto_visitor;
72
[email protected]2532de12013-05-09 12:29:3373 // In order to properly test the code we need to perform encryption and
74 // decryption so that the crypters latch when expected. The crypters are in
75 // |dest_conn|, but we don't want to try and use them there. Instead we swap
76 // them into |framer|, perform the decryption with them, and then swap them
77 // back.
78 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
79
[email protected]fe053f92013-04-23 20:18:5580 crypto_framer.set_visitor(&crypto_visitor);
81
82 size_t index = *inout_packet_index;
[email protected]2532de12013-05-09 12:29:3383 for (; index < source_conn->encrypted_packets_.size(); index++) {
[email protected]9693157b2014-08-08 11:13:4984 if (!framer.ProcessPacket(*source_conn->encrypted_packets_[index])) {
85 // The framer will be unable to decrypt forward-secure packets sent after
86 // the handshake is complete. Don't treat them as handshake packets.
87 break;
88 }
89
rtennetia4228ea2015-06-04 02:31:4490 for (const QuicStreamFrame& stream_frame : framer.stream_frames()) {
91 ASSERT_TRUE(crypto_framer.ProcessInput(stream_frame.data));
[email protected]fe053f92013-04-23 20:18:5592 ASSERT_FALSE(crypto_visitor.error());
93 }
94 }
95 *inout_packet_index = index;
96
[email protected]2532de12013-05-09 12:29:3397 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
98
[email protected]fe053f92013-04-23 20:18:5599 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
100
rtennetia4228ea2015-06-04 02:31:44101 for (const CryptoHandshakeMessage& message : crypto_visitor.messages()) {
102 dest_stream->OnHandshakeMessage(message);
[email protected]ed3fc15d2013-03-08 18:37:44103 }
104}
105
[email protected]0bbeb6972013-05-23 04:10:21106// HexChar parses |c| as a hex character. If valid, it sets |*value| to the
107// value of the hex character and returns true. Otherwise it returns false.
108bool HexChar(char c, uint8* value) {
109 if (c >= '0' && c <= '9') {
110 *value = c - '0';
111 return true;
112 }
113 if (c >= 'a' && c <= 'f') {
[email protected]b064310782013-05-30 21:12:17114 *value = c - 'a' + 10;
[email protected]0bbeb6972013-05-23 04:10:21115 return true;
116 }
117 if (c >= 'A' && c <= 'F') {
[email protected]b064310782013-05-30 21:12:17118 *value = c - 'A' + 10;
[email protected]0bbeb6972013-05-23 04:10:21119 return true;
120 }
121 return false;
122}
123
[email protected]6fc79ea2014-07-10 04:30:23124// A ChannelIDSource that works in asynchronous mode unless the |callback|
rtennetibe635732014-10-02 22:51:42125// argument to GetChannelIDKey is nullptr.
[email protected]6fc79ea2014-07-10 04:30:23126class AsyncTestChannelIDSource : public ChannelIDSource,
[email protected]dc6094a2014-07-23 01:50:04127 public CryptoTestUtils::CallbackSource {
[email protected]6fc79ea2014-07-10 04:30:23128 public:
129 // Takes ownership of |sync_source|, a synchronous ChannelIDSource.
130 explicit AsyncTestChannelIDSource(ChannelIDSource* sync_source)
131 : sync_source_(sync_source) {}
dchengb03027d2014-10-21 12:00:20132 ~AsyncTestChannelIDSource() override {}
[email protected]6fc79ea2014-07-10 04:30:23133
134 // ChannelIDSource implementation.
dchengb03027d2014-10-21 12:00:20135 QuicAsyncStatus GetChannelIDKey(const string& hostname,
136 scoped_ptr<ChannelIDKey>* channel_id_key,
137 ChannelIDSourceCallback* callback) override {
[email protected]6fc79ea2014-07-10 04:30:23138 // Synchronous mode.
139 if (!callback) {
rtennetibe635732014-10-02 22:51:42140 return sync_source_->GetChannelIDKey(hostname, channel_id_key, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23141 }
142
143 // Asynchronous mode.
144 QuicAsyncStatus status =
rtennetibe635732014-10-02 22:51:42145 sync_source_->GetChannelIDKey(hostname, &channel_id_key_, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23146 if (status != QUIC_SUCCESS) {
147 return QUIC_FAILURE;
148 }
149 callback_.reset(callback);
150 return QUIC_PENDING;
151 }
152
[email protected]dc6094a2014-07-23 01:50:04153 // CallbackSource implementation.
dchengb03027d2014-10-21 12:00:20154 void RunPendingCallbacks() override {
[email protected]6fc79ea2014-07-10 04:30:23155 if (callback_.get()) {
156 callback_->Run(&channel_id_key_);
157 callback_.reset();
158 }
159 }
160
161 private:
162 scoped_ptr<ChannelIDSource> sync_source_;
163 scoped_ptr<ChannelIDSourceCallback> callback_;
164 scoped_ptr<ChannelIDKey> channel_id_key_;
165};
166
[email protected]ed3fc15d2013-03-08 18:37:44167} // anonymous namespace
168
[email protected]899951652013-05-16 12:52:39169CryptoTestUtils::FakeClientOptions::FakeClientOptions()
rch1fe2eeb2015-10-26 14:45:57170 : channel_id_enabled(false), channel_id_source_async(false) {}
[email protected]899951652013-05-16 12:52:39171
[email protected]ed3fc15d2013-03-08 18:37:44172// static
[email protected]fe053f92013-04-23 20:18:55173int CryptoTestUtils::HandshakeWithFakeServer(
rtenneti8a4a0732015-10-18 00:45:51174 MockHelper* helper,
[email protected]ed3fc15d2013-03-08 18:37:44175 PacketSavingConnection* client_conn,
[email protected]14e8106c2013-03-14 16:25:33176 QuicCryptoClientStream* client) {
rtenneti6f48aa92015-03-16 02:18:48177 PacketSavingConnection* server_conn = new PacketSavingConnection(
rtenneti8a4a0732015-10-18 00:45:51178 helper, Perspective::IS_SERVER, client_conn->supported_versions());
rtennetid39bd762015-06-12 01:05:52179
180 QuicConfig config = DefaultQuicConfig();
[email protected]b064310782013-05-30 21:12:17181 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
rch1fe2eeb2015-10-26 14:45:57182 QuicRandom::GetInstance(),
183 ProofSourceForTesting());
rtennetid39bd762015-06-12 01:05:52184 SetupCryptoServerConfigForTest(server_conn->clock(),
185 server_conn->random_generator(), &config,
186 &crypto_config);
[email protected]ccb34212014-07-18 09:27:50187
rtennetib865eb82015-06-17 20:21:46188 TestQuicSpdyServerSession server_session(server_conn, config, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44189
190 // The client's handshake must have been started already.
rtennetib6ac61a52015-02-11 20:20:52191 CHECK_NE(0u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44192
rtennetid39bd762015-06-12 01:05:52193 CommunicateHandshakeMessages(client_conn, client, server_conn,
194 server_session.GetCryptoStream());
rtennetid39bd762015-06-12 01:05:52195 CompareClientAndServerKeys(client, server_session.GetCryptoStream());
[email protected]fe053f92013-04-23 20:18:55196
197 return client->num_sent_client_hellos();
[email protected]ed3fc15d2013-03-08 18:37:44198}
199
200// static
[email protected]fe053f92013-04-23 20:18:55201int CryptoTestUtils::HandshakeWithFakeClient(
rtenneti8a4a0732015-10-18 00:45:51202 MockHelper* helper,
[email protected]ed3fc15d2013-03-08 18:37:44203 PacketSavingConnection* server_conn,
[email protected]899951652013-05-16 12:52:39204 QuicCryptoServerStream* server,
zhongyic92bc492015-09-22 19:14:36205 const QuicServerId& server_id,
[email protected]899951652013-05-16 12:52:39206 const FakeClientOptions& options) {
rtenneti6f48aa92015-03-16 02:18:48207 PacketSavingConnection* client_conn =
rtenneti8a4a0732015-10-18 00:45:51208 new PacketSavingConnection(helper, Perspective::IS_CLIENT);
rtenneti85d89712014-11-20 03:32:24209 // Advance the time, because timers do not like uninitialized times.
210 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
[email protected]ef95114d2013-04-17 17:57:01211
rch1fe2eeb2015-10-26 14:45:57212 QuicCryptoClientConfig crypto_config(ProofVerifierForTesting());
rtennetibe635732014-10-02 22:51:42213 AsyncTestChannelIDSource* async_channel_id_source = nullptr;
[email protected]b064310782013-05-30 21:12:17214 if (options.channel_id_enabled) {
[email protected]6fc79ea2014-07-10 04:30:23215
216 ChannelIDSource* source = ChannelIDSourceForTesting();
217 if (options.channel_id_source_async) {
218 async_channel_id_source = new AsyncTestChannelIDSource(source);
219 source = async_channel_id_source;
220 }
221 crypto_config.SetChannelIDSource(source);
[email protected]b064310782013-05-30 21:12:17222 }
rtennetib865eb82015-06-17 20:21:46223 TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(),
224 server_id, &crypto_config);
[email protected]ed3fc15d2013-03-08 18:37:44225
rtennetid39bd762015-06-12 01:05:52226 client_session.GetCryptoStream()->CryptoConnect();
rtennetib6ac61a52015-02-11 20:20:52227 CHECK_EQ(1u, client_conn->encrypted_packets_.size());
[email protected]ed3fc15d2013-03-08 18:37:44228
[email protected]dc6094a2014-07-23 01:50:04229 CommunicateHandshakeMessagesAndRunCallbacks(
rtennetid39bd762015-06-12 01:05:52230 client_conn, client_session.GetCryptoStream(), server_conn, server,
231 async_channel_id_source);
[email protected]14e8106c2013-03-14 16:25:33232
rtennetid39bd762015-06-12 01:05:52233 CompareClientAndServerKeys(client_session.GetCryptoStream(), server);
[email protected]fe053f92013-04-23 20:18:55234
[email protected]38b3fd12013-06-18 08:19:01235 if (options.channel_id_enabled) {
[email protected]03dd32532014-05-30 07:11:25236 scoped_ptr<ChannelIDKey> channel_id_key;
rtennetibe635732014-10-02 22:51:42237 QuicAsyncStatus status = crypto_config.channel_id_source()->GetChannelIDKey(
zhongyic92bc492015-09-22 19:14:36238 server_id.host(), &channel_id_key, nullptr);
[email protected]05bfc260f2014-06-07 06:31:25239 EXPECT_EQ(QUIC_SUCCESS, status);
[email protected]03dd32532014-05-30 07:11:25240 EXPECT_EQ(channel_id_key->SerializeKey(),
241 server->crypto_negotiated_params().channel_id);
rtennetid39bd762015-06-12 01:05:52242 EXPECT_EQ(
243 options.channel_id_source_async,
244 client_session.GetCryptoStream()->WasChannelIDSourceCallbackRun());
[email protected]38b3fd12013-06-18 08:19:01245 }
246
rtennetid39bd762015-06-12 01:05:52247 return client_session.GetCryptoStream()->num_sent_client_hellos();
[email protected]14e8106c2013-03-14 16:25:33248}
249
250// static
[email protected]ef95114d2013-04-17 17:57:01251void CryptoTestUtils::SetupCryptoServerConfigForTest(
252 const QuicClock* clock,
253 QuicRandom* rand,
254 QuicConfig* config,
255 QuicCryptoServerConfig* crypto_config) {
[email protected]b064310782013-05-30 21:12:17256 QuicCryptoServerConfig::ConfigOptions options;
257 options.channel_id_enabled = true;
[email protected]ef95114d2013-04-17 17:57:01258 scoped_ptr<CryptoHandshakeMessage> scfg(
[email protected]b064310782013-05-30 21:12:17259 crypto_config->AddDefaultConfig(rand, clock, options));
[email protected]ef95114d2013-04-17 17:57:01260}
261
262// static
[email protected]0bbeb6972013-05-23 04:10:21263void CryptoTestUtils::CommunicateHandshakeMessages(
264 PacketSavingConnection* a_conn,
265 QuicCryptoStream* a,
266 PacketSavingConnection* b_conn,
267 QuicCryptoStream* b) {
rtennetibe635732014-10-02 22:51:42268 CommunicateHandshakeMessagesAndRunCallbacks(a_conn, a, b_conn, b, nullptr);
[email protected]6fc79ea2014-07-10 04:30:23269}
270
271// static
[email protected]dc6094a2014-07-23 01:50:04272void CryptoTestUtils::CommunicateHandshakeMessagesAndRunCallbacks(
[email protected]6fc79ea2014-07-10 04:30:23273 PacketSavingConnection* a_conn,
274 QuicCryptoStream* a,
275 PacketSavingConnection* b_conn,
276 QuicCryptoStream* b,
[email protected]dc6094a2014-07-23 01:50:04277 CallbackSource* callback_source) {
[email protected]0bbeb6972013-05-23 04:10:21278 size_t a_i = 0, b_i = 0;
279 while (!a->handshake_confirmed()) {
rtennetib6ac61a52015-02-11 20:20:52280 ASSERT_GT(a_conn->encrypted_packets_.size(), a_i);
281 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
282 << " packets a->b";
[email protected]0bbeb6972013-05-23 04:10:21283 MovePackets(a_conn, &a_i, b, b_conn);
[email protected]dc6094a2014-07-23 01:50:04284 if (callback_source) {
285 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23286 }
[email protected]0bbeb6972013-05-23 04:10:21287
rtennetib6ac61a52015-02-11 20:20:52288 ASSERT_GT(b_conn->encrypted_packets_.size(), b_i);
289 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
290 << " packets b->a";
[email protected]0bbeb6972013-05-23 04:10:21291 MovePackets(b_conn, &b_i, a, a_conn);
[email protected]dc6094a2014-07-23 01:50:04292 if (callback_source) {
293 callback_source->RunPendingCallbacks();
[email protected]6fc79ea2014-07-10 04:30:23294 }
[email protected]0bbeb6972013-05-23 04:10:21295 }
296}
297
[email protected]b694e48c2014-03-18 17:10:13298// static
[email protected]691f45a982013-11-19 10:52:04299pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
300 PacketSavingConnection* a_conn,
301 QuicCryptoStream* a,
302 size_t a_i,
303 PacketSavingConnection* b_conn,
304 QuicCryptoStream* b,
305 size_t b_i) {
rtennetib6ac61a52015-02-11 20:20:52306 VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
307 << " packets a->b";
[email protected]691f45a982013-11-19 10:52:04308 MovePackets(a_conn, &a_i, b, b_conn);
309
rtennetib6ac61a52015-02-11 20:20:52310 VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
311 << " packets b->a";
312 if (b_conn->encrypted_packets_.size() - b_i == 2) {
313 VLOG(1) << "here";
[email protected]691f45a982013-11-19 10:52:04314 }
315 MovePackets(b_conn, &b_i, a, a_conn);
316
rtenneti16a20772015-02-17 18:58:48317 return std::make_pair(a_i, b_i);
[email protected]691f45a982013-11-19 10:52:04318}
319
[email protected]0bbeb6972013-05-23 04:10:21320// static
[email protected]ccc66e8a2013-03-26 08:26:14321string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
[email protected]2532de12013-05-09 12:29:33322 QuicTag tag) {
323 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
[email protected]ccc66e8a2013-03-26 08:26:14324 if (it == message.tag_value_map().end()) {
325 return string();
326 }
327 return it->second;
328}
329
[email protected]2532de12013-05-09 12:29:33330class MockCommonCertSets : public CommonCertSets {
[email protected]c244c5a12013-05-07 20:55:04331 public:
[email protected]2532de12013-05-09 12:29:33332 MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
[email protected]c244c5a12013-05-07 20:55:04333 : cert_(cert.as_string()),
334 hash_(hash),
335 index_(index) {
336 }
337
dchengb03027d2014-10-21 12:00:20338 StringPiece GetCommonHashes() const override {
[email protected]c244c5a12013-05-07 20:55:04339 CHECK(false) << "not implemented";
340 return StringPiece();
341 }
342
dchengb03027d2014-10-21 12:00:20343 StringPiece GetCert(uint64 hash, uint32 index) const override {
[email protected]c244c5a12013-05-07 20:55:04344 if (hash == hash_ && index == index_) {
345 return cert_;
346 }
347 return StringPiece();
348 }
349
dchengb03027d2014-10-21 12:00:20350 bool MatchCert(StringPiece cert,
351 StringPiece common_set_hashes,
352 uint64* out_hash,
353 uint32* out_index) const override {
[email protected]c244c5a12013-05-07 20:55:04354 if (cert != cert_) {
355 return false;
356 }
357
358 if (common_set_hashes.size() % sizeof(uint64) != 0) {
359 return false;
360 }
361 bool client_has_set = false;
362 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) {
363 uint64 hash;
364 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash));
365 if (hash == hash_) {
366 client_has_set = true;
367 break;
368 }
369 }
370
371 if (!client_has_set) {
372 return false;
373 }
374
375 *out_hash = hash_;
376 *out_index = index_;
377 return true;
378 }
379
380 private:
381 const string cert_;
382 const uint64 hash_;
383 const uint32 index_;
384};
385
[email protected]2532de12013-05-09 12:29:33386CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
[email protected]899951652013-05-16 12:52:39387 uint64 hash,
388 uint32 index) {
[email protected]2532de12013-05-09 12:29:33389 return new class MockCommonCertSets(cert, hash, index);
[email protected]c244c5a12013-05-07 20:55:04390}
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
[email protected]ed3fc15d2013-03-08 18:37:44611} // namespace test
612} // namespace net